10926 lines
388 KiB
C++
10926 lines
388 KiB
C++
#include "NativeCodeGenerator.h"
|
|
#include "CompilerTypes.h"
|
|
|
|
static const int CPU_REG_A = 256;
|
|
static const int CPU_REG_X = 257;
|
|
static const int CPU_REG_Y = 258;
|
|
static const int CPU_REG_C = 259;
|
|
static const int CPU_REG_Z = 260;
|
|
|
|
static const int NUM_REGS = 261;
|
|
|
|
static const uint32 LIVE_CPU_REG_A = 0x00000001;
|
|
static const uint32 LIVE_CPU_REG_X = 0x00000002;
|
|
static const uint32 LIVE_CPU_REG_Y = 0x00000004;
|
|
static const uint32 LIVE_CPU_REG_C = 0x00000008;
|
|
static const uint32 LIVE_CPU_REG_Z = 0x00000010;
|
|
static const uint32 LIVE_MEM = 0x00000020;
|
|
|
|
static int GlobalValueNumber = 0;
|
|
|
|
NativeRegisterData::NativeRegisterData(void)
|
|
: mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++)
|
|
{
|
|
|
|
}
|
|
|
|
void NativeRegisterData::Reset(void)
|
|
{
|
|
mMode = NRDM_UNKNOWN;
|
|
mValue = GlobalValueNumber++;
|
|
}
|
|
|
|
void NativeRegisterDataSet::Reset(void)
|
|
{
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
mRegs[i].Reset();
|
|
}
|
|
|
|
void NativeRegisterDataSet::ResetZeroPage(int addr)
|
|
{
|
|
mRegs[addr].Reset();
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (mRegs[i].mMode == NRDM_ZERO_PAGE && mRegs[i].mValue == addr)
|
|
mRegs[i].Reset();
|
|
}
|
|
}
|
|
|
|
void NativeRegisterDataSet::ResetAbsolute(LinkerObject* linkerObject, int addr)
|
|
{
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (mRegs[i].mMode == NRDM_ABSOLUTE && mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue == addr)
|
|
mRegs[i].Reset();
|
|
}
|
|
}
|
|
|
|
void NativeRegisterDataSet::ResetIndirect(void)
|
|
{
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (mRegs[i].mMode == NRDM_ABSOLUTE)
|
|
mRegs[i].Reset();
|
|
}
|
|
}
|
|
|
|
|
|
void NativeRegisterDataSet::Intersect(const NativeRegisterDataSet& set)
|
|
{
|
|
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (mRegs[i].mMode == NRDM_UNKNOWN)
|
|
{
|
|
if (set.mRegs[i].mMode != NRDM_UNKNOWN || mRegs[i].mValue != set.mRegs[i].mValue)
|
|
mRegs[i].Reset();
|
|
}
|
|
else if (mRegs[i].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
if (set.mRegs[i].mMode != NRDM_IMMEDIATE || mRegs[i].mValue != set.mRegs[i].mValue)
|
|
mRegs[i].Reset();
|
|
}
|
|
else if (mRegs[i].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
if (set.mRegs[i].mMode != NRDM_IMMEDIATE_ADDRESS || mRegs[i].mValue != set.mRegs[i].mValue || mRegs[i].mLinkerObject != set.mRegs[i].mLinkerObject || mRegs[i].mFlags != set.mRegs[i].mFlags)
|
|
mRegs[i].Reset();
|
|
}
|
|
}
|
|
|
|
bool changed;
|
|
do
|
|
{
|
|
changed = false;
|
|
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (mRegs[i].mMode == NRDM_ZERO_PAGE)
|
|
{
|
|
if (set.mRegs[i].mMode != NRDM_ZERO_PAGE || mRegs[i].mValue != set.mRegs[i].mValue)
|
|
{
|
|
mRegs[i].Reset();
|
|
changed = true;
|
|
}
|
|
else if (mRegs[mRegs[i].mValue].mValue != set.mRegs[set.mRegs[i].mValue].mValue)
|
|
{
|
|
mRegs[i].Reset();
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (mRegs[i].mMode == NRDM_ABSOLUTE)
|
|
{
|
|
if (set.mRegs[i].mMode != NRDM_ABSOLUTE || mRegs[i].mValue != set.mRegs[i].mValue)
|
|
{
|
|
mRegs[i].Reset();
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (changed);
|
|
}
|
|
|
|
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags)
|
|
: mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags)
|
|
{}
|
|
|
|
bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
|
|
{
|
|
bool used = false;
|
|
|
|
mLive = 0;
|
|
if (requiredTemps[CPU_REG_A])
|
|
mLive |= LIVE_CPU_REG_A;
|
|
if (requiredTemps[CPU_REG_X])
|
|
mLive |= LIVE_CPU_REG_X;
|
|
if (requiredTemps[CPU_REG_Y])
|
|
mLive |= LIVE_CPU_REG_Y;
|
|
if (requiredTemps[CPU_REG_Z])
|
|
mLive |= LIVE_CPU_REG_Z;
|
|
if (requiredTemps[CPU_REG_C])
|
|
mLive |= LIVE_CPU_REG_C;
|
|
if (mMode == ASMIM_ZERO_PAGE && requiredTemps[mAddress])
|
|
mLive |= LIVE_MEM;
|
|
if (mMode == ASMIM_INDIRECT_Y && (requiredTemps[mAddress] || requiredTemps[mAddress + 1]))
|
|
mLive |= LIVE_MEM;
|
|
|
|
if (mType == ASMIT_JSR)
|
|
{
|
|
requiredTemps -= CPU_REG_C;
|
|
requiredTemps -= CPU_REG_Z;
|
|
requiredTemps -= CPU_REG_A;
|
|
requiredTemps -= CPU_REG_X;
|
|
requiredTemps -= CPU_REG_Y;
|
|
|
|
if (mFlags & NCIF_RUNTIME)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
requiredTemps += BC_REG_ACCU + i;
|
|
requiredTemps += BC_REG_WORK + i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
requiredTemps += BC_REG_LOCALS;
|
|
requiredTemps += BC_REG_LOCALS + 1;
|
|
if (mLinkerObject)
|
|
{
|
|
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++)
|
|
{
|
|
for (int j = 0; j < mLinkerObject->mTempSizes[i]; j++)
|
|
requiredTemps += mLinkerObject->mTemporaries[i] + j;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (mType == ASMIT_RTS)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
requiredTemps += BC_REG_ACCU + i;
|
|
}
|
|
|
|
requiredTemps += BC_REG_STACK;
|
|
requiredTemps += BC_REG_STACK + 1;
|
|
requiredTemps += BC_REG_LOCALS;
|
|
requiredTemps += BC_REG_LOCALS + 1;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (mType == ASMIT_BYTE)
|
|
return true;
|
|
|
|
// check side effects
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_STA:
|
|
case ASMIT_STX:
|
|
case ASMIT_STY:
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
if (mMode != ASMIM_IMPLIED && mMode != ASMIM_ZERO_PAGE)
|
|
used = true;
|
|
break;
|
|
case ASMIT_JSR:
|
|
case ASMIT_JMP:
|
|
case ASMIT_BEQ:
|
|
case ASMIT_BNE:
|
|
case ASMIT_BPL:
|
|
case ASMIT_BMI:
|
|
case ASMIT_BCC:
|
|
case ASMIT_BCS:
|
|
used = true;
|
|
break;
|
|
}
|
|
|
|
if (requiredTemps[CPU_REG_C])
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_CLC:
|
|
case ASMIT_SEC:
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_CMP:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (requiredTemps[CPU_REG_Z])
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
case ASMIT_CMP:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
case ASMIT_LDA:
|
|
case ASMIT_LDX:
|
|
case ASMIT_LDY:
|
|
case ASMIT_BIT:
|
|
case ASMIT_INX:
|
|
case ASMIT_DEX:
|
|
case ASMIT_INY:
|
|
case ASMIT_DEY:
|
|
case ASMIT_TYA:
|
|
case ASMIT_TXA:
|
|
case ASMIT_TAY:
|
|
case ASMIT_TAX:
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (requiredTemps[CPU_REG_A])
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
if (mMode == ASMIM_IMPLIED)
|
|
used = true;
|
|
break;
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
case ASMIT_LDA:
|
|
case ASMIT_TXA:
|
|
case ASMIT_TYA:
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (requiredTemps[CPU_REG_X])
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_LDX:
|
|
case ASMIT_INX:
|
|
case ASMIT_DEX:
|
|
case ASMIT_TAX:
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (requiredTemps[CPU_REG_Y])
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_LDY:
|
|
case ASMIT_INY:
|
|
case ASMIT_DEY:
|
|
case ASMIT_TAY:
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
case ASMIT_STA:
|
|
case ASMIT_STX:
|
|
case ASMIT_STY:
|
|
if (requiredTemps[mAddress])
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (used)
|
|
{
|
|
switch (mMode)
|
|
{
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_ABSOLUTE_X:
|
|
requiredTemps += CPU_REG_X;
|
|
break;
|
|
|
|
case ASMIM_ZERO_PAGE_Y:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
requiredTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIM_INDIRECT_Y:
|
|
requiredTemps += CPU_REG_Y;
|
|
requiredTemps += mAddress;
|
|
requiredTemps += mAddress + 1;
|
|
break;
|
|
}
|
|
|
|
// check carry flags
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
requiredTemps += CPU_REG_C;
|
|
break;
|
|
case ASMIT_CMP:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_CLC:
|
|
case ASMIT_SEC:
|
|
requiredTemps -= CPU_REG_C;
|
|
break;
|
|
case ASMIT_BCC:
|
|
case ASMIT_BCS:
|
|
requiredTemps += CPU_REG_C;
|
|
break;
|
|
case ASMIT_BEQ:
|
|
case ASMIT_BNE:
|
|
case ASMIT_BPL:
|
|
case ASMIT_BMI:
|
|
requiredTemps += CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
// check zero flags
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_CMP:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
case ASMIT_LDA:
|
|
case ASMIT_LDX:
|
|
case ASMIT_LDY:
|
|
case ASMIT_BIT:
|
|
case ASMIT_TAY:
|
|
case ASMIT_TYA:
|
|
case ASMIT_TAX:
|
|
case ASMIT_TXA:
|
|
requiredTemps -= CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
// check CPU register
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
if (mMode == ASMIM_IMPLIED)
|
|
requiredTemps += CPU_REG_A;
|
|
break;
|
|
|
|
case ASMIT_LDA:
|
|
requiredTemps -= CPU_REG_A;
|
|
break;
|
|
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
requiredTemps += CPU_REG_A;
|
|
break;
|
|
case ASMIT_LDX:
|
|
requiredTemps -= CPU_REG_X;
|
|
break;
|
|
case ASMIT_INX:
|
|
case ASMIT_DEX:
|
|
requiredTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_LDY:
|
|
requiredTemps -= CPU_REG_Y;
|
|
break;
|
|
case ASMIT_INY:
|
|
case ASMIT_DEY:
|
|
requiredTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIT_CMP:
|
|
case ASMIT_STA:
|
|
requiredTemps += CPU_REG_A;
|
|
break;
|
|
case ASMIT_CPX:
|
|
case ASMIT_STX:
|
|
requiredTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_CPY:
|
|
case ASMIT_STY:
|
|
requiredTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIT_TXA:
|
|
requiredTemps += CPU_REG_X;
|
|
requiredTemps -= CPU_REG_A;
|
|
break;
|
|
case ASMIT_TYA:
|
|
requiredTemps += CPU_REG_Y;
|
|
requiredTemps -= CPU_REG_A;
|
|
break;
|
|
case ASMIT_TAX:
|
|
requiredTemps += CPU_REG_A;
|
|
requiredTemps -= CPU_REG_X;
|
|
break;
|
|
case ASMIT_TAY:
|
|
requiredTemps += CPU_REG_A;
|
|
requiredTemps -= CPU_REG_Y;
|
|
break;
|
|
}
|
|
|
|
if (mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_STA:
|
|
case ASMIT_STX:
|
|
case ASMIT_STY:
|
|
requiredTemps -= mAddress;
|
|
break;
|
|
default:
|
|
requiredTemps += mAddress;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::LoadsAccu(void) const
|
|
{
|
|
return mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || mType == ASMIT_JSR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesAccuAndFlag(void) const
|
|
{
|
|
return
|
|
mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
|
|
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
|
|
mType == ASMIT_SBC || mType == ASMIT_ADC || mType == ASMIT_JSR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::RequiresYReg(void) const
|
|
{
|
|
if (mMode == ASMIM_ABSOLUTE_Y || mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_ZERO_PAGE_Y)
|
|
return true;
|
|
if (mType == ASMIT_TYA || mType == ASMIT_STY || mType == ASMIT_CPY || mType == ASMIT_INY || mType == ASMIT_DEY)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesYReg(void) const
|
|
{
|
|
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesXReg(void) const
|
|
{
|
|
return mType == ASMIT_TAX || mType == ASMIT_LDX || mType == ASMIT_INX || mType == ASMIT_DEX || mType == ASMIT_JSR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesZeroPage(int address) const
|
|
{
|
|
if (mMode == ASMIM_ZERO_PAGE && mAddress == address)
|
|
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::UsesZeroPage(int address) const
|
|
{
|
|
if (mMode == ASMIM_ZERO_PAGE && mAddress == address)
|
|
return true;
|
|
else if (mMode == ASMIM_INDIRECT_Y && (mAddress == address || mAddress == address + 1))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
bool NativeCodeInstruction::ChangesGlobalMemory(void) const
|
|
{
|
|
if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
|
|
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY || mType == ASMIT_JSR;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesCarry(void) const
|
|
{
|
|
return
|
|
mType == ASMIT_CLC || mType == ASMIT_SEC ||
|
|
mType == ASMIT_ADC || mType == ASMIT_SBC ||
|
|
mType == ASMIT_LSR || mType == ASMIT_ASL || mType == ASMIT_ROL || mType == ASMIT_ROR ||
|
|
mType == ASMIT_CMP || mType == ASMIT_CPX || mType == ASMIT_CPY ||
|
|
mType == ASMIT_JSR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::RequiresAccu(void) const
|
|
{
|
|
if (mMode == ASMIM_IMPLIED)
|
|
{
|
|
return
|
|
mType == ASMIT_TAX || mType == ASMIT_TAY ||
|
|
mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR;
|
|
}
|
|
else
|
|
{
|
|
return
|
|
mType == ASMIT_STA ||
|
|
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
|
|
mType == ASMIT_SBC || mType == ASMIT_ADC || mType == ASMIT_CMP;
|
|
}
|
|
}
|
|
|
|
bool NativeCodeInstruction::UsesAccu(void) const
|
|
{
|
|
if (ChangesAccu())
|
|
return true;
|
|
|
|
return mType == ASMIT_STA || mType == ASMIT_CMP || mType == ASMIT_TAX || mType == ASMIT_TAY;
|
|
}
|
|
|
|
bool NativeCodeInstruction::ChangesAccu(void) const
|
|
{
|
|
if (mMode == ASMIM_IMPLIED)
|
|
{
|
|
return
|
|
mType == ASMIT_TXA || mType == ASMIT_TYA ||
|
|
mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR;
|
|
}
|
|
else
|
|
{
|
|
return
|
|
mType == ASMIT_JSR ||
|
|
mType == ASMIT_LDA ||
|
|
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
|
|
mType == ASMIT_SBC || mType == ASMIT_ADC;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool NativeCodeInstruction::ChangesAddress(void) const
|
|
{
|
|
if (mMode != ASMIM_IMPLIED)
|
|
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::IsShift(void) const
|
|
{
|
|
return mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR;
|
|
}
|
|
|
|
bool NativeCodeInstruction::IsCommutative(void) const
|
|
{
|
|
return mType == ASMIT_ADC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR;
|
|
}
|
|
|
|
|
|
bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
|
|
{
|
|
if (mType == ins.mType && mMode == ins.mMode)
|
|
{
|
|
switch (mMode)
|
|
{
|
|
case ASMIM_IMPLIED:
|
|
return true;
|
|
case ASMIM_IMMEDIATE:
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_ZERO_PAGE_Y:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_INDIRECT_Y:
|
|
return ins.mAddress == mAddress;
|
|
case ASMIM_IMMEDIATE_ADDRESS:
|
|
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress && ins.mFlags == mFlags);
|
|
case ASMIM_ABSOLUTE:
|
|
case ASMIM_ABSOLUTE_X:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeInstruction::SameEffectiveAddress(const NativeCodeInstruction& ins) const
|
|
{
|
|
if (mMode != ins.mMode)
|
|
return false;
|
|
|
|
switch (mMode)
|
|
{
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_ZERO_PAGE_Y:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_INDIRECT_Y:
|
|
return ins.mAddress == mAddress;
|
|
case ASMIM_ABSOLUTE:
|
|
case ASMIM_ABSOLUTE_X:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool NativeCodeInstruction::ApplySimulation(const NativeRegisterDataSet& data)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_LDA:
|
|
case ASMIT_LDX:
|
|
case ASMIT_LDY:
|
|
case ASMIT_CMP:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_AND:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
if (mMode == ASMIM_ZERO_PAGE && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mMode = ASMIM_IMMEDIATE;
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
return true;
|
|
}
|
|
else if (mMode == ASMIM_ZERO_PAGE && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
mMode = ASMIM_IMMEDIATE_ADDRESS;
|
|
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
|
|
mFlags = data.mRegs[mAddress].mFlags;
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (mMode == ASMIM_INDIRECT_Y && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mMode = ASMIM_ABSOLUTE_Y;
|
|
mAddress = data.mRegs[mAddress].mValue + 256 * data.mRegs[mAddress + 1].mValue;
|
|
mLinkerObject = nullptr;
|
|
}
|
|
else if (mMode == ASMIM_INDIRECT_Y && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject)
|
|
{
|
|
mMode = ASMIM_ABSOLUTE_Y;
|
|
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data)
|
|
{
|
|
int reg = -1;
|
|
if (mMode == ASMIM_ZERO_PAGE)
|
|
reg = mAddress;
|
|
else if (mMode == ASMIM_IMPLIED)
|
|
reg = CPU_REG_A;
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_JSR:
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
data.mRegs[BC_REG_ACCU + i].Reset();
|
|
data.mRegs[BC_REG_WORK + i].Reset();
|
|
data.mRegs[BC_REG_ADDR + i].Reset();
|
|
}
|
|
data.mRegs[BC_REG_WORK_Y].Reset();
|
|
break;
|
|
|
|
case ASMIT_ROL:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue << 1) | data.mRegs[CPU_REG_C].mValue;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[reg].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ROR:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue >> 1) | (data.mRegs[CPU_REG_C].mValue << 7);
|
|
data.mRegs[CPU_REG_C].mValue = data.mRegs[reg].mValue & 1;
|
|
data.mRegs[reg].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ASL:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue << 1);
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[reg].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LSR:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue >> 1);
|
|
data.mRegs[CPU_REG_C].mValue = data.mRegs[reg].mValue & 1;
|
|
data.mRegs[reg].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_INC:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[reg].mValue = (data.mRegs[reg].mValue + 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[reg].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_DEC:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[reg].mValue = (data.mRegs[reg].mValue + 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[reg].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_ADC:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue + data.mRegs[CPU_REG_A].mValue + data.mRegs[CPU_REG_C].mValue;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[CPU_REG_A].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_SBC:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_A].mValue + data.mRegs[CPU_REG_C].mValue;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[CPU_REG_A].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_AND:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue & data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_A].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else if ((data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[reg].mValue == 0) || (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0))
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = 0;
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = 0;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ORA:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue | data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_A].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else if ((data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[reg].mValue == 0xff) || (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0xff))
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = 0xff;
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = 0xff;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_EOR:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue | data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_A].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_INX:
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X].mValue = (data.mRegs[CPU_REG_X].mValue + 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_DEX:
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X].mValue = (data.mRegs[CPU_REG_X].mValue - 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_INY:
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y].mValue = (data.mRegs[CPU_REG_Y].mValue + 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_DEY:
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y].mValue = (data.mRegs[CPU_REG_Y].mValue - 1) & 255;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_TXA:
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_TYA:
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_TAX:
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X].mValue = data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_TAY:
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y].mValue = data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mValue;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_CMP:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_A].mValue + 1;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_CPX:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_X].mValue + 1;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_CPY:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (data.mRegs[reg].mValue ^ 0xff) + data.mRegs[CPU_REG_Y].mValue + 1;
|
|
data.mRegs[CPU_REG_C].mValue = t >= 256;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t & 255;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDA:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue;
|
|
data.mRegs[CPU_REG_A].mValue = t;
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE_ADDRESS)
|
|
{
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
data.mRegs[CPU_REG_A].mLinkerObject = mLinkerObject;
|
|
data.mRegs[CPU_REG_A].mFlags = mFlags;
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE_ADDRESS;
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDX:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue;
|
|
data.mRegs[CPU_REG_X].mValue = t;
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X].mValue = mAddress;
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDY:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = data.mRegs[reg].mValue;
|
|
data.mRegs[CPU_REG_Y].mValue = t;
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = t;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_STA:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE || data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
data.mRegs[reg] = data.mRegs[CPU_REG_A];
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ASMIT_STX:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[reg].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
data.mRegs[reg].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ASMIT_STY:
|
|
if (reg >= 0)
|
|
{
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[reg].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
data.mRegs[reg].mMode = NRDM_IMMEDIATE;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[reg].Reset();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsType& carryop)
|
|
{
|
|
bool changed = false;
|
|
|
|
carryop = ASMIT_NOP;
|
|
|
|
mFlags &= ~NCIF_YZERO;
|
|
|
|
if ((data.mRegs[CPU_REG_Y].mMode & NRDM_IMMEDIATE) && (data.mRegs[CPU_REG_Y].mValue == 0))
|
|
mFlags |= NCIF_YZERO;
|
|
|
|
if (mType == ASMIT_JSR)
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
data.ResetZeroPage(BC_REG_ACCU + i);
|
|
data.ResetZeroPage(BC_REG_WORK + i);
|
|
data.ResetZeroPage(BC_REG_ADDR + i);
|
|
}
|
|
data.ResetZeroPage(BC_REG_WORK_Y);
|
|
|
|
return false;
|
|
}
|
|
|
|
if (data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mValue == 0)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ROL:
|
|
mType = ASMIT_ASL;
|
|
changed = true;
|
|
break;
|
|
case ASMIT_ROR:
|
|
mType = ASMIT_LSR;
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_CLC:
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = 0;
|
|
break;
|
|
case ASMIT_SEC:
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = 1;
|
|
break;
|
|
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
if (mMode == ASMIM_IMPLIED)
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_LDA:
|
|
if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
}
|
|
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE_ADDRESS)
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE_ADDRESS;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
data.mRegs[CPU_REG_A].mLinkerObject = mLinkerObject;
|
|
data.mRegs[CPU_REG_A].mFlags = mFlags;
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
else
|
|
{
|
|
if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE)
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ADC:
|
|
if (data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mValue == 0)
|
|
{
|
|
if (mMode == ASMIM_IMMEDIATE && mAddress == 0)
|
|
{
|
|
mType = ASMIT_ORA;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0)
|
|
{
|
|
mType = ASMIT_LDA;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_SBC:
|
|
if (data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
if (mMode == ASMIM_IMMEDIATE && mAddress == 0 && data.mRegs[CPU_REG_C].mValue == 1)
|
|
{
|
|
mType = ASMIT_ORA;
|
|
changed = true;
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
int t = (mAddress ^ 0xff) + data.mRegs[CPU_REG_A].mValue + data.mRegs[CPU_REG_C].mValue;
|
|
|
|
mType = ASMIT_LDA;
|
|
mAddress = t & 0xff;
|
|
|
|
int c = t >= 256;
|
|
|
|
if (t && !data.mRegs[CPU_REG_C].mValue)
|
|
carryop = ASMIT_SEC;
|
|
else if (!t && data.mRegs[CPU_REG_C].mValue)
|
|
carryop = ASMIT_CLC;
|
|
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
case ASMIT_CMP:
|
|
if (mMode == ASMIM_IMMEDIATE && 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 - mAddress;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_A].mValue >= mAddress;
|
|
}
|
|
else if (mMode == ASMIM_IMMEDIATE && mAddress == 0)
|
|
{
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = 1;
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
case ASMIT_CPX:
|
|
if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mValue - mAddress;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_X].mValue >= mAddress;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
case ASMIT_CPY:
|
|
if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mValue - mAddress;
|
|
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_Y].mValue >= mAddress;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_C].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
if (mMode == ASMIM_IMMEDIATE && data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
if (mType == ASMIT_ORA)
|
|
mAddress |= data.mRegs[CPU_REG_A].mValue;
|
|
else if (mType == ASMIT_AND)
|
|
mAddress &= data.mRegs[CPU_REG_A].mValue;
|
|
else if (mType == ASMIT_EOR)
|
|
mAddress ^= data.mRegs[CPU_REG_A].mValue;
|
|
mType = ASMIT_LDA;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0)
|
|
{
|
|
if (mType == ASMIT_ORA || mType == ASMIT_EOR)
|
|
{
|
|
mType = ASMIT_LDA;
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
else
|
|
{
|
|
mType = ASMIT_LDA;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
mAddress = 0;
|
|
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = 0;
|
|
}
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
case ASMIT_LDX:
|
|
if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_X].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mMode != ASMIM_ZERO_PAGE)
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
case ASMIT_INX:
|
|
case ASMIT_DEX:
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
case ASMIT_LDY:
|
|
if (mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Y].mValue = mAddress;
|
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mMode != ASMIM_ZERO_PAGE)
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
}
|
|
break;
|
|
case ASMIT_INY:
|
|
case ASMIT_DEY:
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
data.mRegs[CPU_REG_Z].Reset();
|
|
break;
|
|
|
|
case ASMIT_TXA:
|
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
|
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_TYA:
|
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
|
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_TAX:
|
|
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.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;
|
|
}
|
|
|
|
if (mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_LDA:
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_A].mValue == mAddress)
|
|
{
|
|
if (mLive & LIVE_CPU_REG_Z)
|
|
{
|
|
mType = ASMIT_ORA;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
mAddress = 0;
|
|
}
|
|
else
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
}
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_A] = data.mRegs[mAddress];
|
|
mAddress = data.mRegs[CPU_REG_A].mValue;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
data.mRegs[CPU_REG_A] = data.mRegs[mAddress];
|
|
mAddress = data.mRegs[CPU_REG_A].mValue;
|
|
mLinkerObject = data.mRegs[CPU_REG_A].mLinkerObject;
|
|
mFlags = (mFlags & ~(NCIF_LOWER | NCIF_UPPER)) | (data.mRegs[CPU_REG_A].mFlags & (NCIF_LOWER | NCIF_UPPER));
|
|
mMode = ASMIM_IMMEDIATE_ADDRESS;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE)
|
|
{
|
|
data.mRegs[CPU_REG_A] = data.mRegs[mAddress];
|
|
mAddress = data.mRegs[CPU_REG_A].mValue;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[CPU_REG_X].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_X].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_TXA;
|
|
mMode = ASMIM_IMPLIED;
|
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
|
|
}
|
|
else if (data.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_Y].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_TYA;
|
|
mMode = ASMIM_IMPLIED;
|
|
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_A].mValue = data.mRegs[mAddress].mValue;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDX:
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_X].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X] = data.mRegs[mAddress];
|
|
mAddress = data.mRegs[CPU_REG_X].mValue;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_A].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_TAX;
|
|
mMode = ASMIM_IMPLIED;
|
|
data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A];
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].Reset();
|
|
if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_X].mValue = data.mRegs[mAddress].mValue;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_X].mValue = mAddress;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDY:
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_Y].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y] = data.mRegs[mAddress];
|
|
mAddress = data.mRegs[CPU_REG_Y].mValue;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_A].mValue == mAddress)
|
|
{
|
|
mType = ASMIT_TAY;
|
|
mMode = ASMIM_IMPLIED;
|
|
data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A];
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].Reset();
|
|
if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[CPU_REG_Y].mValue = data.mRegs[mAddress].mValue;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_Y].mValue = mAddress;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_AND:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_CMP:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE)
|
|
{
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
changed = true;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_ABSOLUTE)
|
|
{
|
|
mMode = ASMIM_ABSOLUTE;
|
|
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
changed = true;
|
|
}
|
|
break;
|
|
|
|
case ASMIT_STA:
|
|
data.ResetZeroPage(mAddress);
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE || data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
data.mRegs[mAddress] = data.mRegs[CPU_REG_A];
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE)
|
|
{
|
|
data.mRegs[mAddress].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue;
|
|
}
|
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE)
|
|
{
|
|
data.mRegs[mAddress] = data.mRegs[CPU_REG_A];
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
}
|
|
break;
|
|
case ASMIT_STX:
|
|
data.ResetZeroPage(mAddress);
|
|
if (data.mRegs[CPU_REG_X].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[mAddress].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_X].mValue;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_X].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_X].mValue = mAddress;
|
|
}
|
|
break;
|
|
case ASMIT_STY:
|
|
data.ResetZeroPage(mAddress);
|
|
if (data.mRegs[CPU_REG_Y].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
data.mRegs[mAddress].mMode = NRDM_IMMEDIATE;
|
|
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_Y].mValue;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_Y].mMode = NRDM_ZERO_PAGE;
|
|
data.mRegs[CPU_REG_Y].mValue = mAddress;
|
|
}
|
|
break;
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
data.ResetZeroPage(mAddress);
|
|
break;
|
|
}
|
|
}
|
|
else if (mMode == ASMIM_INDIRECT_Y)
|
|
{
|
|
if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress + 1].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress].mValue + 1 == data.mRegs[mAddress + 1].mValue)
|
|
{
|
|
mAddress = data.mRegs[mAddress].mValue;
|
|
}
|
|
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject)
|
|
{
|
|
mMode = ASMIM_ABSOLUTE_Y;
|
|
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
|
|
mAddress = data.mRegs[mAddress + 1].mValue;
|
|
}
|
|
|
|
if (ChangesAddress())
|
|
data.ResetIndirect();
|
|
}
|
|
else if (mMode == ASMIM_ABSOLUTE)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_LDA:
|
|
if (!(mFlags & NCIF_VOLATILE))
|
|
{
|
|
if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE && data.mRegs[CPU_REG_A].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_A].mValue == mAddress)
|
|
{
|
|
if (mLive & LIVE_CPU_REG_Z)
|
|
{
|
|
mType = ASMIT_ORA;
|
|
mMode = ASMIM_IMMEDIATE;
|
|
mAddress = 0;
|
|
}
|
|
else
|
|
{
|
|
mType = ASMIT_NOP;
|
|
mMode = ASMIM_IMPLIED;
|
|
}
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
data.mRegs[CPU_REG_A].mMode = NRDM_ABSOLUTE;
|
|
data.mRegs[CPU_REG_A].mLinkerObject = mLinkerObject;
|
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
|
}
|
|
}
|
|
else
|
|
data.mRegs[CPU_REG_A].Reset();
|
|
break;
|
|
default:
|
|
if (ChangesAddress())
|
|
data.ResetAbsolute(mLinkerObject, mAddress);
|
|
}
|
|
}
|
|
else if (mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
|
|
{
|
|
if (ChangesAddress())
|
|
data.ResetAbsolute(mLinkerObject, mAddress);
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps)
|
|
{
|
|
// check runtime calls
|
|
|
|
if (mType == ASMIT_JSR)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (!providedTemps[BC_REG_ACCU + i])
|
|
requiredTemps += BC_REG_ACCU + i;
|
|
providedTemps += BC_REG_ACCU + i;
|
|
if (!providedTemps[BC_REG_WORK + i])
|
|
requiredTemps += BC_REG_WORK + i;
|
|
providedTemps += BC_REG_WORK + i;
|
|
if (!providedTemps[BC_REG_ADDR + i])
|
|
requiredTemps += BC_REG_ADDR + i;
|
|
providedTemps += BC_REG_ADDR + i;
|
|
}
|
|
|
|
if (!(mFlags & NCIF_RUNTIME))
|
|
{
|
|
if (mLinkerObject)
|
|
{
|
|
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++)
|
|
{
|
|
for (int j = 0; j < mLinkerObject->mTempSizes[i]; j++)
|
|
{
|
|
if (!providedTemps[mLinkerObject->mTemporaries[i] + j])
|
|
requiredTemps += mLinkerObject->mTemporaries[i] + j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
providedTemps += CPU_REG_A;
|
|
providedTemps += CPU_REG_X;
|
|
providedTemps += CPU_REG_Y;
|
|
providedTemps += CPU_REG_C;
|
|
providedTemps += CPU_REG_Z;
|
|
return;
|
|
}
|
|
|
|
if (mType == ASMIT_RTS)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (!providedTemps[BC_REG_ACCU + i])
|
|
requiredTemps += BC_REG_ACCU + i;
|
|
}
|
|
|
|
if (!providedTemps[BC_REG_STACK])
|
|
requiredTemps += BC_REG_STACK;
|
|
if (!providedTemps[BC_REG_STACK + 1])
|
|
requiredTemps += BC_REG_STACK + 1;
|
|
if (!providedTemps[BC_REG_LOCALS])
|
|
requiredTemps += BC_REG_LOCALS;
|
|
if (!providedTemps[BC_REG_LOCALS + 1])
|
|
requiredTemps += BC_REG_LOCALS + 1;
|
|
|
|
return;
|
|
}
|
|
|
|
// check index
|
|
|
|
switch (mMode)
|
|
{
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_ABSOLUTE_X:
|
|
if (!providedTemps[CPU_REG_X])
|
|
requiredTemps += CPU_REG_X;
|
|
break;
|
|
|
|
case ASMIM_ZERO_PAGE_Y:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
if (!providedTemps[CPU_REG_Y])
|
|
requiredTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIM_INDIRECT_Y:
|
|
if (!providedTemps[CPU_REG_Y])
|
|
requiredTemps += CPU_REG_Y;
|
|
if (!providedTemps[mAddress])
|
|
requiredTemps += mAddress;
|
|
if (!providedTemps[mAddress + 1])
|
|
requiredTemps += mAddress + 1;
|
|
break;
|
|
}
|
|
|
|
// check carry flags
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
if (!providedTemps[CPU_REG_C])
|
|
requiredTemps += CPU_REG_C;
|
|
providedTemps += CPU_REG_C;
|
|
break;
|
|
case ASMIT_CMP:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_CLC:
|
|
case ASMIT_SEC:
|
|
providedTemps += CPU_REG_C;
|
|
break;
|
|
case ASMIT_BCC:
|
|
case ASMIT_BCS:
|
|
if (!providedTemps[CPU_REG_C])
|
|
requiredTemps += CPU_REG_C;
|
|
break;
|
|
case ASMIT_BEQ:
|
|
case ASMIT_BNE:
|
|
case ASMIT_BPL:
|
|
case ASMIT_BMI:
|
|
if (!providedTemps[CPU_REG_Z])
|
|
requiredTemps += CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
// check zero flag
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_CMP:
|
|
case ASMIT_CPX:
|
|
case ASMIT_CPY:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
case ASMIT_LDA:
|
|
case ASMIT_LDX:
|
|
case ASMIT_LDY:
|
|
case ASMIT_BIT:
|
|
providedTemps += CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
// check CPU register
|
|
|
|
switch (mType)
|
|
{
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
if (mMode == ASMIM_IMPLIED)
|
|
{
|
|
if (!providedTemps[CPU_REG_A])
|
|
requiredTemps += CPU_REG_A;
|
|
providedTemps += CPU_REG_A;
|
|
}
|
|
break;
|
|
|
|
case ASMIT_LDA:
|
|
providedTemps += CPU_REG_A;
|
|
break;
|
|
|
|
case ASMIT_CMP:
|
|
case ASMIT_STA:
|
|
if (!providedTemps[CPU_REG_A])
|
|
requiredTemps += CPU_REG_A;
|
|
break;
|
|
case ASMIT_CPX:
|
|
case ASMIT_STX:
|
|
if (!providedTemps[CPU_REG_X])
|
|
requiredTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_CPY:
|
|
case ASMIT_STY:
|
|
if (!providedTemps[CPU_REG_Y])
|
|
requiredTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIT_ADC:
|
|
case ASMIT_SBC:
|
|
case ASMIT_ORA:
|
|
case ASMIT_EOR:
|
|
case ASMIT_AND:
|
|
if (!providedTemps[CPU_REG_A])
|
|
requiredTemps += CPU_REG_A;
|
|
providedTemps += CPU_REG_A;
|
|
break;
|
|
case ASMIT_LDX:
|
|
providedTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_INX:
|
|
case ASMIT_DEX:
|
|
if (!providedTemps[CPU_REG_X])
|
|
requiredTemps += CPU_REG_X;
|
|
providedTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_LDY:
|
|
providedTemps += CPU_REG_Y;
|
|
break;
|
|
case ASMIT_INY:
|
|
case ASMIT_DEY:
|
|
if (!providedTemps[CPU_REG_Y])
|
|
requiredTemps += CPU_REG_Y;
|
|
providedTemps += CPU_REG_Y;
|
|
break;
|
|
|
|
case ASMIT_TAX:
|
|
if (!providedTemps[CPU_REG_A])
|
|
requiredTemps += CPU_REG_A;
|
|
providedTemps += CPU_REG_X;
|
|
break;
|
|
case ASMIT_TAY:
|
|
if (!providedTemps[CPU_REG_A])
|
|
requiredTemps += CPU_REG_A;
|
|
providedTemps += CPU_REG_Y;
|
|
break;
|
|
case ASMIT_TXA:
|
|
if (!providedTemps[CPU_REG_X])
|
|
requiredTemps += CPU_REG_X;
|
|
providedTemps += CPU_REG_A;
|
|
break;
|
|
case ASMIT_TYA:
|
|
if (!providedTemps[CPU_REG_Y])
|
|
requiredTemps += CPU_REG_Y;
|
|
providedTemps += CPU_REG_A;
|
|
break;
|
|
}
|
|
|
|
if (mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ASMIT_STA:
|
|
case ASMIT_STX:
|
|
case ASMIT_STY:
|
|
providedTemps += mAddress;
|
|
break;
|
|
case ASMIT_ROL:
|
|
case ASMIT_ROR:
|
|
case ASMIT_ASL:
|
|
case ASMIT_LSR:
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
if (!providedTemps[mAddress])
|
|
requiredTemps += mAddress;
|
|
providedTemps += mAddress;
|
|
break;
|
|
default:
|
|
if (!providedTemps[mAddress])
|
|
requiredTemps += mAddress;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
|
|
{
|
|
if (mType == ASMIT_BYTE)
|
|
block->PutByte(mAddress);
|
|
else if (mType == ASMIT_JSR && mLinkerObject && (mLinkerObject->mFlags & LOBJF_INLINE))
|
|
{
|
|
int pos = block->mCode.Size();
|
|
for (int i = 0; i < mLinkerObject->mSize - 1; i++)
|
|
block->PutByte(mLinkerObject->mData[i]);
|
|
for (int i = 0; i < mLinkerObject->mReferences.Size(); i++)
|
|
{
|
|
LinkerReference rl = *(mLinkerObject->mReferences[i]);
|
|
if (rl.mFlags & LREF_TEMPORARY)
|
|
{
|
|
block->mCode[pos + rl.mOffset] += mLinkerObject->mTemporaries[rl.mRefOffset];
|
|
}
|
|
else
|
|
{
|
|
rl.mOffset += pos;
|
|
if (rl.mRefObject == rl.mObject)
|
|
{
|
|
rl.mRefObject = nullptr;
|
|
rl.mRefOffset += pos;
|
|
}
|
|
block->mRelocations.Push(rl);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mMode == ASMIM_IMMEDIATE_ADDRESS)
|
|
block->PutByte(AsmInsOpcodes[mType][ASMIM_IMMEDIATE]);
|
|
else
|
|
block->PutByte(AsmInsOpcodes[mType][mMode]);
|
|
|
|
switch (mMode)
|
|
{
|
|
case ASMIM_IMPLIED:
|
|
break;
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_ZERO_PAGE_X:
|
|
case ASMIM_ZERO_PAGE_Y:
|
|
case ASMIM_INDIRECT_X:
|
|
case ASMIM_INDIRECT_Y:
|
|
block->PutByte(uint8(mAddress));
|
|
break;
|
|
case ASMIM_IMMEDIATE:
|
|
case ASMIM_IMMEDIATE_ADDRESS:
|
|
if (mLinkerObject)
|
|
{
|
|
LinkerReference rl;
|
|
rl.mOffset = block->mCode.Size();
|
|
rl.mFlags = 0;
|
|
if (mFlags & NCIF_LOWER)
|
|
rl.mFlags |= LREF_LOWBYTE;
|
|
if (mFlags & NCIF_UPPER)
|
|
rl.mFlags |= LREF_HIGHBYTE;
|
|
rl.mRefObject = mLinkerObject;
|
|
|
|
rl.mRefObject = mLinkerObject;
|
|
rl.mRefOffset = mAddress;
|
|
block->mRelocations.Push(rl);
|
|
block->PutByte(0);
|
|
}
|
|
else
|
|
{
|
|
block->PutByte(uint16(mAddress));
|
|
}
|
|
break;
|
|
case ASMIM_ABSOLUTE:
|
|
case ASMIM_INDIRECT:
|
|
case ASMIM_ABSOLUTE_X:
|
|
case ASMIM_ABSOLUTE_Y:
|
|
if (mLinkerObject)
|
|
{
|
|
LinkerReference rl;
|
|
rl.mOffset = block->mCode.Size();
|
|
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
|
rl.mRefObject = mLinkerObject;
|
|
rl.mRefOffset = mAddress;
|
|
block->mRelocations.Push(rl);
|
|
block->PutWord(0);
|
|
}
|
|
else
|
|
{
|
|
block->PutWord(uint16(mAddress));
|
|
}
|
|
break;
|
|
case ASMIM_RELATIVE:
|
|
block->PutByte(uint8(mAddress));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void NativeCodeBasicBlock::PutByte(uint8 code)
|
|
{
|
|
this->mCode.Push(code);
|
|
}
|
|
|
|
void NativeCodeBasicBlock::PutWord(uint16 code)
|
|
{
|
|
this->mCode.Push((uint8)(code & 0xff));
|
|
this->mCode.Push((uint8)(code >> 8));
|
|
}
|
|
|
|
static AsmInsType InvertBranchCondition(AsmInsType code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case ASMIT_BEQ: return ASMIT_BNE;
|
|
case ASMIT_BNE: return ASMIT_BEQ;
|
|
case ASMIT_BPL: return ASMIT_BMI;
|
|
case ASMIT_BMI: return ASMIT_BPL;
|
|
case ASMIT_BCS: return ASMIT_BCC;
|
|
case ASMIT_BCC: return ASMIT_BCS;
|
|
default:
|
|
return code;
|
|
}
|
|
}
|
|
|
|
static AsmInsType TransposeBranchCondition(AsmInsType code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case ASMIT_BEQ: return ASMIT_BEQ;
|
|
case ASMIT_BNE: return ASMIT_BNE;
|
|
case ASMIT_BPL: return ASMIT_BMI;
|
|
case ASMIT_BMI: return ASMIT_BPL;
|
|
case ASMIT_BCS: return ASMIT_BCC;
|
|
case ASMIT_BCC: return ASMIT_BCS;
|
|
default:
|
|
return code;
|
|
}
|
|
}
|
|
|
|
|
|
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, int offset)
|
|
{
|
|
PutByte(0x4c);
|
|
|
|
LinkerReference rl;
|
|
rl.mObject = nullptr;
|
|
rl.mOffset = mCode.Size();
|
|
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
|
rl.mRefObject = nullptr;
|
|
rl.mRefOffset = mOffset + mCode.Size() + offset - 1;
|
|
mRelocations.Push(rl);
|
|
|
|
PutWord(0);
|
|
return 3;
|
|
}
|
|
|
|
int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset)
|
|
{
|
|
if (offset >= -126 && offset <= 129)
|
|
{
|
|
PutByte(AsmInsOpcodes[code][ASMIM_RELATIVE]);
|
|
PutByte(offset - 2);
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
PutByte(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]);
|
|
PutByte(3);
|
|
PutByte(0x4c);
|
|
|
|
LinkerReference rl;
|
|
rl.mObject = nullptr;
|
|
rl.mOffset = mCode.Size();
|
|
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
|
rl.mRefObject = nullptr;
|
|
rl.mRefOffset = mOffset + mCode.Size() + offset - 3;
|
|
mRelocations.Push(rl);
|
|
|
|
PutWord(0);
|
|
return 5;
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction * ins, InterType type, int reg)
|
|
{
|
|
if (type == IT_FLOAT)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mConst.mFloatConst;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (type == IT_POINTER)
|
|
{
|
|
if (ins->mConst.mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mConst.mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mConst.mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + ins->mConst.mVarIndex + ins->mConst.mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mConst.mMemory == IM_LOCAL || ins->mConst.mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mConst.mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mConst.mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mConst.mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mConst.mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 2);
|
|
|
|
if (index != 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, areg));
|
|
if (index != 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, areg + 1));
|
|
if (index != 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mConst.mMemory == IM_PROCEDURE)
|
|
{
|
|
NativeCodeInstruction lins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER);
|
|
NativeCodeInstruction hins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER);
|
|
|
|
mIns.Push(lins);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(hins);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
else if (type == IT_INT32)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins)
|
|
{
|
|
LoadConstantToReg(proc, ins, ins->mDst.mType, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]);
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CheckFrameIndex(int& reg, int& index, int size, int treg)
|
|
{
|
|
if (index < 0 || index + size > 256)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR + 1));
|
|
index = 0;
|
|
if (treg == 0)
|
|
reg = BC_REG_ADDR;
|
|
else
|
|
reg = treg;
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstruction * ins)
|
|
{
|
|
uint32 flags = NCIF_LOWER | NCIF_UPPER;
|
|
if (ins->mVolatile)
|
|
flags |= NCIF_VOLATILE;
|
|
|
|
if (ins->mSrc[0].mType == IT_FLOAT)
|
|
{
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[0].mFloatConst;
|
|
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 3));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y,BC_REG_STACK));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
|
|
|
if (ins->mSrc[0].mFinal && CheckPredAccuStore(sreg))
|
|
{
|
|
// cull previous store from accu to temp using direcrt forwarding from accu
|
|
mIns.SetSize(mIns.Size() - 8);
|
|
sreg = BC_REG_ACCU;
|
|
}
|
|
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 3));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (ins->mSrc[0].mType == IT_POINTER)
|
|
{
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (InterTypeSize[ins->mSrc[0].mType] == 1)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 2)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 4)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 3));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (InterTypeSize[ins->mSrc[0].mType] == 1)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 2)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 4)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, ins->mSrc[1].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, ins->mSrc[1].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + 3, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 3));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[1].mIntConst;
|
|
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
|
|
if (ins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(reg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, InterTypeSize[ins->mSrc[0].mType]);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
|
|
if (InterTypeSize[ins->mSrc[0].mType] == 2)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 4)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int reg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
int index = ins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(reg, index, InterTypeSize[ins->mSrc[0].mType]);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
|
|
if (InterTypeSize[ins->mSrc[0].mType] == 2)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
else if (InterTypeSize[ins->mSrc[0].mType] == 4)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins)
|
|
{
|
|
int size = InterTypeSize[wins->mSrc[0].mType];
|
|
|
|
AsmInsMode rmode = ASMIM_INDIRECT_Y;
|
|
int rindex = rins->mSrc[0].mIntConst;
|
|
int rareg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
LinkerObject* rlobject = nullptr;
|
|
|
|
uint32 rflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (rins->mVolatile)
|
|
rflags |= NCIF_VOLATILE;
|
|
|
|
switch (rins->mSrc[0].mMemory)
|
|
{
|
|
case IM_PARAM:
|
|
rindex += rins->mSrc[0].mVarIndex + proc->mLocalSize + 2 + mFrameOffset;
|
|
break;
|
|
case IM_LOCAL:
|
|
rindex += proc->mLocalVars[rins->mSrc[0].mVarIndex]->mOffset + mFrameOffset;
|
|
break;
|
|
case IM_PROCEDURE:
|
|
case IM_GLOBAL:
|
|
rmode = ASMIM_ABSOLUTE;
|
|
rlobject = rins->mSrc[0].mLinkerObject;
|
|
rindex = rins->mSrc[0].mIntConst;
|
|
break;
|
|
case IM_FRAME:
|
|
rindex = rins->mSrc[0].mVarIndex + rins->mSrc[0].mIntConst + 2;
|
|
rareg = BC_REG_STACK;
|
|
break;
|
|
case IM_INDIRECT:
|
|
rareg = BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp];
|
|
break;
|
|
case IM_ABSOLUTE:
|
|
rmode = ASMIM_ABSOLUTE;
|
|
rindex = rins->mSrc[0].mIntConst;
|
|
break;
|
|
case IM_FPARAM:
|
|
rmode = ASMIM_ZERO_PAGE;
|
|
rareg = BC_REG_FPARAMS + rins->mSrc[0].mVarIndex + rins->mSrc[0].mIntConst;
|
|
break;
|
|
}
|
|
|
|
AsmInsMode wmode = ASMIM_INDIRECT_Y;
|
|
int windex = wins->mSrc[1].mIntConst;
|
|
int wareg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
LinkerObject* wlobject = nullptr;
|
|
|
|
uint32 wflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (wins->mVolatile)
|
|
wflags |= NCIF_VOLATILE;
|
|
|
|
switch (wins->mSrc[1].mMemory)
|
|
{
|
|
case IM_PARAM:
|
|
windex += wins->mSrc[1].mVarIndex + proc->mLocalSize + 2 + mFrameOffset;
|
|
break;
|
|
case IM_LOCAL:
|
|
windex += proc->mLocalVars[wins->mSrc[1].mVarIndex]->mOffset + mFrameOffset;
|
|
break;
|
|
case IM_PROCEDURE:
|
|
case IM_GLOBAL:
|
|
wmode = ASMIM_ABSOLUTE;
|
|
wlobject = wins->mSrc[1].mLinkerObject;
|
|
windex = wins->mSrc[1].mIntConst;
|
|
break;
|
|
case IM_FRAME:
|
|
windex = wins->mSrc[1].mVarIndex + wins->mSrc[1].mIntConst + 2;
|
|
wareg = BC_REG_STACK;
|
|
break;
|
|
case IM_INDIRECT:
|
|
wareg = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp];
|
|
break;
|
|
case IM_ABSOLUTE:
|
|
wmode = ASMIM_ABSOLUTE;
|
|
windex = wins->mSrc[1].mIntConst;
|
|
break;
|
|
case IM_FPARAM:
|
|
wmode = ASMIM_ZERO_PAGE;
|
|
wareg = BC_REG_FPARAMS + wins->mSrc[1].mVarIndex + wins->mSrc[1].mIntConst;
|
|
break;
|
|
}
|
|
|
|
if (rmode == ASMIM_INDIRECT_Y)
|
|
CheckFrameIndex(rareg, rindex, size, BC_REG_ADDR);
|
|
|
|
if (wmode == ASMIM_INDIRECT_Y)
|
|
CheckFrameIndex(wareg, windex, size, BC_REG_ACCU);
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
if (rmode == ASMIM_INDIRECT_Y)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rindex + i));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, rareg));
|
|
}
|
|
else if (rmode == ASMIM_ZERO_PAGE)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, rareg + i));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rindex + i, rlobject, rflags));
|
|
|
|
if (wmode == ASMIM_INDIRECT_Y)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, windex + i));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, wareg));
|
|
}
|
|
else if (wmode == ASMIM_ZERO_PAGE)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, wareg + i));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, windex + i, wlobject, wflags));
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadStoreValue(InterCodeProcedure* proc, const InterInstruction * rins, const InterInstruction * wins)
|
|
{
|
|
uint32 rflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (rins->mVolatile)
|
|
rflags |= NCIF_VOLATILE;
|
|
|
|
uint32 wflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (wins->mVolatile)
|
|
wflags |= NCIF_VOLATILE;
|
|
|
|
|
|
if (rins->mDst.mType == IT_FLOAT)
|
|
{
|
|
|
|
}
|
|
else if (rins->mDst.mType == IT_POINTER)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if (InterTypeSize[wins->mSrc[0].mType] == 1)
|
|
{
|
|
if (rins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (rins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins->mSrc[0].mIntConst, rins->mSrc[0].mLinkerObject, rflags));
|
|
}
|
|
else if (rins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins->mSrc[0].mIntConst, nullptr, rflags));
|
|
}
|
|
else if (rins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + rins->mSrc[0].mVarIndex + rins->mSrc[0].mIntConst));
|
|
}
|
|
else if (rins->mSrc[0].mMemory == IM_LOCAL || rins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = rins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (rins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[rins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += rins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rins->mSrc[0].mMemory == IM_INDIRECT)
|
|
{
|
|
int areg = BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp];
|
|
int index = rins->mSrc[0].mIntConst;
|
|
|
|
CheckFrameIndex(areg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
}
|
|
}
|
|
|
|
if (wins->mSrc[1].mTemp < 0)
|
|
{
|
|
if (wins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins->mSrc[1].mIntConst, wins->mSrc[1].mLinkerObject, wflags));
|
|
}
|
|
else if (wins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins->mSrc[1].mIntConst, nullptr, wflags));
|
|
}
|
|
else if (wins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + wins->mSrc[1].mVarIndex + wins->mSrc[1].mIntConst));
|
|
}
|
|
else if (wins->mSrc[1].mMemory == IM_LOCAL || wins->mSrc[1].mMemory == IM_PARAM)
|
|
{
|
|
int index = wins->mSrc[1].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (wins->mSrc[1].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[wins->mSrc[1].mVarIndex]->mOffset;
|
|
else
|
|
index += wins->mSrc[1].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg));
|
|
}
|
|
else if (wins->mSrc[1].mMemory == IM_FRAME)
|
|
{
|
|
int index = wins->mSrc[1].mVarIndex + wins->mSrc[1].mIntConst + 2;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (wins->mSrc[1].mMemory == IM_INDIRECT)
|
|
{
|
|
int areg = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp];
|
|
int index = wins->mSrc[1].mIntConst;
|
|
|
|
CheckFrameIndex(areg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::LoadOpStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* oins, int oindex, const InterInstruction* wins)
|
|
{
|
|
int size = InterTypeSize[wins->mSrc[0].mType];
|
|
|
|
AsmInsType at = ASMIT_ADC, an = ASMIT_ADC;
|
|
AsmInsMode am = oins->mSrc[oindex].mTemp < 0 ? ASMIM_IMMEDIATE : ASMIM_ZERO_PAGE;
|
|
|
|
switch (oins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC));
|
|
at = an = ASMIT_ADC;
|
|
break;
|
|
case IA_SUB:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC));
|
|
at = an = ASMIT_SBC;
|
|
break;
|
|
case IA_AND:
|
|
at = an = ASMIT_AND;
|
|
break;
|
|
case IA_OR:
|
|
at = an = ASMIT_ORA;
|
|
break;
|
|
case IA_XOR:
|
|
at = an = ASMIT_EOR;
|
|
break;
|
|
case IA_SHL:
|
|
if (oindex == 0 && oins->mSrc[oindex].mTemp < 0 && oins->mSrc[oindex].mIntConst == 1)
|
|
{
|
|
at = ASMIT_ASL;
|
|
an = ASMIT_ROL;
|
|
am = ASMIM_IMPLIED;
|
|
}
|
|
else
|
|
return false;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
int rindex = rins->mSrc[0].mIntConst;
|
|
int rareg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
|
|
if (rins->mSrc[0].mMemory == IM_INDIRECT)
|
|
rareg = BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp];
|
|
else if (rins->mSrc[0].mMemory == IM_LOCAL)
|
|
rindex += proc->mLocalVars[rins->mSrc[0].mVarIndex]->mOffset + mFrameOffset;
|
|
else if (rins->mSrc[0].mMemory == IM_PARAM)
|
|
rindex += rins->mSrc[0].mVarIndex + proc->mLocalSize + 2 + mFrameOffset;
|
|
else
|
|
return false;
|
|
|
|
int windex = wins->mSrc[1].mIntConst;
|
|
int wareg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
|
|
if (wins->mSrc[1].mMemory == IM_INDIRECT)
|
|
wareg = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp];
|
|
else if (wins->mSrc[1].mMemory == IM_LOCAL)
|
|
windex += proc->mLocalVars[wins->mSrc[1].mVarIndex]->mOffset + mFrameOffset;
|
|
else if (wins->mSrc[1].mMemory == IM_PARAM)
|
|
windex += wins->mSrc[1].mVarIndex + proc->mLocalSize + 2 + mFrameOffset;
|
|
else
|
|
return false;
|
|
|
|
uint32 rflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (rins->mVolatile)
|
|
rflags |= NCIF_VOLATILE;
|
|
|
|
uint32 wflags = NCIF_LOWER | NCIF_UPPER;
|
|
if (wins->mVolatile)
|
|
wflags |= NCIF_VOLATILE;
|
|
|
|
CheckFrameIndex(rareg, rindex, size, BC_REG_ADDR);
|
|
CheckFrameIndex(wareg, windex, size, BC_REG_ACCU);
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rindex + i));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, rareg));
|
|
if (am == ASMIM_IMPLIED)
|
|
mIns.Push(NativeCodeInstruction(at, ASMIM_IMPLIED));
|
|
else if (am == ASMIM_IMMEDIATE)
|
|
mIns.Push(NativeCodeInstruction(at, ASMIM_IMMEDIATE, (oins->mSrc[oindex].mIntConst >> (8 * i)) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(at, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[oins->mSrc[oindex].mTemp] + i));
|
|
at = an;
|
|
if (rindex != windex)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, windex + i));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, wareg));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterInstruction * ins, int reg, const NativeCodeInstruction* ainsl, const NativeCodeInstruction* ainsh)
|
|
{
|
|
uint32 flags = NCIF_LOWER | NCIF_UPPER;
|
|
if (ins->mVolatile)
|
|
flags |= NCIF_VOLATILE;
|
|
|
|
if (ins->mDst.mType == IT_FLOAT)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 2, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 3, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 3, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_INDIRECT)
|
|
{
|
|
int areg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
|
int index = ins->mSrc[0].mIntConst;
|
|
|
|
CheckFrameIndex(areg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
}
|
|
}
|
|
else if (ins->mDst.mType == IT_POINTER)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, ins->mSrc[0].mLinkerObject, flags));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, nullptr, flags));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, nullptr, flags));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 1));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_INDIRECT)
|
|
{
|
|
int areg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
|
int index = ins->mSrc[0].mIntConst;
|
|
|
|
CheckFrameIndex(areg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
if (reg == areg)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
if (reg == areg)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (InterTypeSize[ins->mDst.mType] == 1)
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, nullptr, flags));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 1);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
}
|
|
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mDst.mType] == 2)
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, ins->mSrc[0].mLinkerObject, flags));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, nullptr, flags));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, nullptr, flags));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 1));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 2);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mDst.mType] == 4)
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 2, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 3, ins->mSrc[0].mLinkerObject, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 1, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 2, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + 3, nullptr, flags));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
|
|
{
|
|
int index = ins->mSrc[0].mIntConst;
|
|
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
|
|
if (ins->mSrc[0].mMemory == IM_LOCAL)
|
|
index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
|
|
else
|
|
index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;
|
|
index += mFrameOffset;
|
|
CheckFrameIndex(areg, index, 4);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mMemory == IM_INDIRECT)
|
|
{
|
|
int areg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
|
int index = ins->mSrc[0].mIntConst;
|
|
|
|
CheckFrameIndex(areg, index, InterTypeSize[ins->mDst.mType]);
|
|
|
|
if (InterTypeSize[ins->mDst.mType] == 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
else if (InterTypeSize[ins->mDst.mType] == 2)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsl)
|
|
{
|
|
if (ainsl->mType == ASMIT_ADC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
else if (ainsl->mType == ASMIT_SBC)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(*ainsl);
|
|
}
|
|
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
if (reg == areg)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
if (ainsh) mIns.Push(*ainsh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
if (reg == areg)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
}
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
}
|
|
else if (InterTypeSize[ins->mDst.mType] == 4)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstruction * ins)
|
|
{
|
|
LoadValueToReg(proc, ins, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], nullptr, nullptr);
|
|
}
|
|
|
|
NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc)
|
|
{
|
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
|
|
int size = ins->mConst.mOperandSize;
|
|
if (size < 4)
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, i));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
|
|
}
|
|
|
|
return this;
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
if (size < 128)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BPL);
|
|
}
|
|
else if (size <= 256)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
|
|
}
|
|
|
|
return eblock;
|
|
}
|
|
}
|
|
|
|
NativeCodeBasicBlock* NativeCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)
|
|
{
|
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0xff));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
return eblock;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::CheckPredAccuStore(int reg)
|
|
{
|
|
if (mIns.Size() < 8)
|
|
return false;
|
|
|
|
int p = mIns.Size() - 8;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (mIns[p + 0].mType != ASMIT_LDA || mIns[p + 0].mMode != ASMIM_ZERO_PAGE || mIns[p + 0].mAddress != BC_REG_ACCU + i)
|
|
return false;
|
|
if (mIns[p + 1].mType != ASMIT_STA || mIns[p + 1].mMode != ASMIM_ZERO_PAGE || mIns[p + 1].mAddress != reg + i)
|
|
return false;
|
|
|
|
p += 2;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift)
|
|
{
|
|
if (shift == 0)
|
|
{
|
|
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
else if (shift >= 5)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
for (int i = shift; i < 8; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, (0xff << shift) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
|
|
for (int i = 0; i < shift; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
|
|
}
|
|
}
|
|
|
|
int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul)
|
|
{
|
|
if (sins)
|
|
LoadValueToReg(proc, sins, BC_REG_ACCU, nullptr, nullptr);
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[index].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[index].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
}
|
|
|
|
int lshift = 0, lmul = mul;
|
|
while (!(lmul & 1))
|
|
{
|
|
lmul >>= 1;
|
|
lshift++;
|
|
}
|
|
|
|
switch (lmul)
|
|
{
|
|
#if 1
|
|
case 1:
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
case 3:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAY, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
case 5:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
case 7:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
case 9:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
#if 1
|
|
case 25:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAY, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
|
return BC_REG_ACCU;
|
|
#endif
|
|
#endif
|
|
default:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
|
|
NativeCodeGenerator::Runtime& rt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mul16by8")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, rt.mOffset, rt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
return BC_REG_WORK + 2;
|
|
}
|
|
}
|
|
|
|
static bool IsPowerOf2(unsigned n)
|
|
{
|
|
return (n & (n - 1)) == 0;
|
|
}
|
|
|
|
static int Binlog(unsigned n)
|
|
{
|
|
int k = -1;
|
|
|
|
while (n)
|
|
{
|
|
n >>= 1;
|
|
k++;
|
|
}
|
|
|
|
return k;
|
|
}
|
|
NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction * sins1, const InterInstruction * sins0)
|
|
{
|
|
int treg = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
|
|
|
|
if (ins->mDst.mType == IT_FLOAT)
|
|
{
|
|
int sreg0 = ins->mSrc[0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[1].mFloatConst;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
else if (sins1)
|
|
{
|
|
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
|
|
}
|
|
else if (ins->mSrc[1].mFinal && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]))
|
|
{
|
|
// cull previous store from accu to temp using direcrt forwarding
|
|
mIns.SetSize(mIns.Size() - 8);
|
|
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])
|
|
sreg0 = BC_REG_ACCU;
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[0].mFloatConst;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
else if (sins0)
|
|
{
|
|
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
{
|
|
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_SUB:
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("faddsub")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_MUL:
|
|
{
|
|
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("fmul")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_DIVS:
|
|
case IA_DIVU:
|
|
{
|
|
NativeCodeGenerator::Runtime& art(nproc->mGenerator->ResolveRuntime(Ident::Unique("fdiv")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, art.mOffset, art.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
}
|
|
else if (ins->mDst.mType == IT_INT32)
|
|
{
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
case IA_SUB:
|
|
case IA_OR:
|
|
case IA_AND:
|
|
case IA_XOR:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
AsmInsType atype;
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
atype = ASMIT_ADC;
|
|
break;
|
|
case IA_SUB:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
atype = ASMIT_SBC;
|
|
break;
|
|
case IA_OR:
|
|
atype = ASMIT_ORA;
|
|
break;
|
|
case IA_AND:
|
|
atype = ASMIT_AND;
|
|
break;
|
|
case IA_XOR:
|
|
atype = ASMIT_EOR;
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> (8 * i)) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + i));
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> (8 * i)) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + i));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + i));
|
|
}
|
|
} break;
|
|
|
|
case IA_MUL:
|
|
case IA_DIVS:
|
|
case IA_MODS:
|
|
case IA_DIVU:
|
|
case IA_MODU:
|
|
{
|
|
if (sins1)
|
|
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
|
|
else if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
|
|
if (sins0)
|
|
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
|
|
else if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
|
|
int reg = BC_REG_ACCU;
|
|
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_MUL:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mul32")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 4;
|
|
} break;
|
|
case IA_DIVS:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("divs32")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_MODS:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mods32")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 4;
|
|
} break;
|
|
case IA_DIVU:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("divu32")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_MODU:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("modu32")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 4;
|
|
} break;
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
} break;
|
|
case IA_SHL:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 31;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x1f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 24) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
this->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
} break;
|
|
|
|
case IA_SHR:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 31;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x1f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 24) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
this->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
} break;
|
|
|
|
case IA_SAR:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 31;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, shift));
|
|
this->Close(lblock, nullptr, ASMIT_JMP);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x1f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 24) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
this->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 2));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
return eblock;
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
case IA_OR:
|
|
case IA_AND:
|
|
case IA_XOR:
|
|
{
|
|
if (ins->mOperator == IA_ADD && (
|
|
ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst == 1 && !sins1 && ins->mSrc[1].mTemp == ins->mDst.mTemp ||
|
|
ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mIntConst == 1 && !sins0 && ins->mSrc[0].mTemp == ins->mDst.mTemp))
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
NativeCodeBasicBlock* iblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
|
|
this->Close(eblock, iblock, ASMIT_BNE);
|
|
|
|
iblock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg + 1));
|
|
|
|
iblock->Close(eblock, nullptr, ASMIT_JMP);
|
|
return eblock;
|
|
}
|
|
}
|
|
else if (ins->mOperator == IA_ADD && InterTypeSize[ins->mDst.mType] == 1 && (
|
|
ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst == -1 && !sins1 && ins->mSrc[1].mTemp == ins->mDst.mTemp ||
|
|
ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mIntConst == -1 && !sins0 && ins->mSrc[0].mTemp == ins->mDst.mTemp))
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
else
|
|
{
|
|
NativeCodeInstruction insl, insh;
|
|
|
|
AsmInsType atype;
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_ADD:
|
|
atype = ASMIT_ADC;
|
|
break;
|
|
case IA_OR:
|
|
atype = ASMIT_ORA;
|
|
break;
|
|
case IA_AND:
|
|
atype = ASMIT_AND;
|
|
break;
|
|
case IA_XOR:
|
|
atype = ASMIT_EOR;
|
|
break;
|
|
}
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff);
|
|
insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff);
|
|
if (sins0)
|
|
LoadValueToReg(proc, sins0, treg, &insl, &insh);
|
|
else
|
|
{
|
|
if (ins->mOperator == IA_ADD)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(insl);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(insh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
else if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff);
|
|
insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff);
|
|
if (sins1)
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
else
|
|
{
|
|
if (ins->mOperator == IA_ADD)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(insl);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(insh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sins1 && sins0)
|
|
{
|
|
if (sins0->mSrc[0].mMemory == IM_INDIRECT && sins1->mSrc[0].mMemory == IM_INDIRECT && sins0->mSrc[0].mIntConst < 255 && sins1->mSrc[0].mIntConst < 255)
|
|
{
|
|
if (ins->mOperator == IA_ADD)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins0->mSrc[0].mIntConst + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins0->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins1->mSrc[0].mIntConst + 0));
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins1->mSrc[0].mTemp]));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
if (ins->mDst.mTemp == sins0->mSrc[0].mTemp || ins->mDst.mTemp == sins1->mSrc[0].mTemp)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins0->mSrc[0].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins0->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, sins1->mSrc[0].mIntConst + 1));
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[sins1->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
if (ins->mDst.mTemp == sins0->mSrc[0].mTemp || ins->mDst.mTemp == sins1->mSrc[0].mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK_Y));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
else
|
|
{
|
|
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg);
|
|
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg + 1);
|
|
|
|
if (sins1->mDst.mTemp == ins->mDst.mTemp)
|
|
{
|
|
LoadValueToReg(proc, sins1, treg, nullptr, nullptr);
|
|
LoadValueToReg(proc, sins0, treg, &insl, &insh);
|
|
}
|
|
else
|
|
{
|
|
LoadValueToReg(proc, sins0, treg, nullptr, nullptr);
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
}
|
|
}
|
|
}
|
|
else if (sins1)
|
|
{
|
|
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]);
|
|
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1);
|
|
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
}
|
|
else if (sins0)
|
|
{
|
|
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]);
|
|
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1);
|
|
|
|
LoadValueToReg(proc, sins0, treg, &insl, &insh);
|
|
}
|
|
else
|
|
{
|
|
if (ins->mOperator == IA_ADD)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
case IA_SUB:
|
|
{
|
|
NativeCodeInstruction insl, insh;
|
|
|
|
if (InterTypeSize[ins->mDst.mType] == 1 &&
|
|
ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mIntConst == 1 && !sins0 && ins->mSrc[0].mTemp == ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
else if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff);
|
|
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff);
|
|
if (sins1)
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(insl);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(insh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
if (sins0)
|
|
{
|
|
LoadValueToReg(proc, sins0, treg, nullptr, nullptr);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sins0)
|
|
{
|
|
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_WORK + 0);
|
|
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_WORK + 1);
|
|
|
|
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
|
|
}
|
|
else
|
|
{
|
|
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]);
|
|
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1);
|
|
}
|
|
|
|
if (sins1)
|
|
{
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(insl);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(insh);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
case IA_MUL:
|
|
case IA_DIVS:
|
|
case IA_MODS:
|
|
case IA_DIVU:
|
|
case IA_MODU:
|
|
{
|
|
int reg = BC_REG_ACCU;
|
|
|
|
if (ins->mOperator == IA_MUL && ins->mSrc[1].mTemp < 0 && (ins->mSrc[1].mIntConst & ~0xff) == 0)
|
|
{
|
|
reg = ShortMultiply(proc, nproc, ins, sins0, 0, ins->mSrc[1].mIntConst & 0xff);
|
|
}
|
|
else if (ins->mOperator == IA_MUL && ins->mSrc[0].mTemp < 0 && (ins->mSrc[0].mIntConst & ~0xff) == 0)
|
|
{
|
|
reg = ShortMultiply(proc, nproc, ins, sins1, 1, ins->mSrc[0].mIntConst & 0xff);
|
|
}
|
|
else
|
|
{
|
|
if (sins1)
|
|
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
|
|
else if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
}
|
|
|
|
if (sins0)
|
|
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
|
|
else if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
}
|
|
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_MUL:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mul16")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 2;
|
|
} break;
|
|
case IA_DIVS:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("divs16")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_MODS:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mods16")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 2;
|
|
} break;
|
|
case IA_DIVU:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("divu16")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
} break;
|
|
case IA_MODU:
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("modu16")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
reg = BC_REG_WORK + 2;
|
|
} break;
|
|
}
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
} break;
|
|
case IA_SHL:
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0 && (ins->mSrc[0].mIntConst & 15) == 1 && sins1)
|
|
{
|
|
NativeCodeInstruction insl(ASMIT_ASL, ASMIM_IMPLIED);
|
|
NativeCodeInstruction insh(ASMIT_ROL, ASMIM_IMPLIED);
|
|
LoadValueToReg(proc, sins1, treg, &insl, &insh);
|
|
return this;
|
|
}
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 15;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (shift == 7)
|
|
{
|
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
else if (shift >= 8)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
for (int i = 8; i < shift; i++)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
for (int i = 1; i < shift; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff))
|
|
{
|
|
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
|
|
|
|
if (l < 8)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 8 + l, frt.mLinkerObject));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2)));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
} break;
|
|
case IA_SHR:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 15;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (shift == 1)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
}
|
|
else if (shift >= 8)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
for (int i = 8; i < shift; i++)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
for (int i = 1; i < shift; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg ));
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff))
|
|
{
|
|
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 39 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 47 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2)));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
} break;
|
|
case IA_SAR:
|
|
{
|
|
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp], nullptr, nullptr);
|
|
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], nullptr, nullptr);
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
int shift = ins->mSrc[0].mIntConst & 15;
|
|
if (shift == 0)
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (shift == 7)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else if (shift == 6)
|
|
{
|
|
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
|
if (sreg != treg)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, treg + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (shift >= 8)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
for (int i = 8; i < shift; i++)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> (shift - 8)));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> (shift - 8)));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
|
|
for (int i = 0; i < shift; i++)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff))
|
|
{
|
|
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
|
|
|
|
if (l == 15)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ABSOLUTE_X, frt.mOffset + 39 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 47 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 39 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, frt.mOffset + 47 - l, frt.mLinkerObject));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
|
|
if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
}
|
|
else if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 2 + 1 + 2));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 2 + 1 + 2)));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
}
|
|
} break;
|
|
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins)
|
|
{
|
|
int treg = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
|
|
|
|
if (ins->mDst.mType == IT_FLOAT)
|
|
{
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_NEG:
|
|
case IA_ABS:
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
|
|
if (ins->mOperator == IA_NEG)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x7f));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
break;
|
|
case IA_FLOOR:
|
|
case IA_CEIL:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
|
|
NativeCodeGenerator::Runtime& frx(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplita")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frx.mOffset, frx.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
if (ins->mOperator == IA_FLOOR)
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ffloor")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
}
|
|
else
|
|
{
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fceil")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
}
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_NEG:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
if (ins->mDst.mType == IT_INT32)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
break;
|
|
|
|
case IA_NOT:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
|
if (ins->mDst.mType == IT_INT32)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins)
|
|
{
|
|
switch (ins->mOperator)
|
|
{
|
|
case IA_FLOAT2INT:
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ftoi")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
|
|
} break;
|
|
case IA_INT2FLOAT:
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("ffromi")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
|
|
} break;
|
|
case IA_EXT8TO16S:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
break;
|
|
case IA_EXT8TO16U:
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
break;
|
|
case IA_EXT16TO32S:
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
break;
|
|
case IA_EXT16TO32U:
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump)
|
|
{
|
|
InterOperator op = ins->mOperator;
|
|
|
|
if (ins->mSrc[0].mType == IT_FLOAT)
|
|
{
|
|
int li = 0, ri = 1;
|
|
if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS)
|
|
{
|
|
li = 1; ri = 0;
|
|
}
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[li].mFloatConst;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
else if (ins->mSrc[li].mFinal && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp]))
|
|
{
|
|
// cull previous store from accu to temp using direcrt forwarding
|
|
mIns.SetSize(mIns.Size() - 8);
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[ri].mFloatConst;
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
|
|
}
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fcmp")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
switch (op)
|
|
{
|
|
case IA_CMPEQ:
|
|
Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPNE:
|
|
Close(falseJump, trueJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPLU:
|
|
case IA_CMPLS:
|
|
case IA_CMPGU:
|
|
case IA_CMPGS:
|
|
Close(trueJump, falseJump, ASMIT_BMI);
|
|
break;
|
|
case IA_CMPLEU:
|
|
case IA_CMPLES:
|
|
case IA_CMPGEU:
|
|
case IA_CMPGES:
|
|
Close(falseJump, trueJump, ASMIT_BMI);
|
|
break;
|
|
}
|
|
}
|
|
else if (ins->mSrc[0].mType == IT_INT32)
|
|
{
|
|
int li = 1, ri = 0;
|
|
if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS)
|
|
{
|
|
li = 0; ri = 1;
|
|
}
|
|
|
|
if (op >= IA_CMPGES && ins->mOperator <= IA_CMPLS)
|
|
{
|
|
if (ins->mSrc[ri].mTemp >= 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK));
|
|
}
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ((ins->mSrc[li].mIntConst >> 24) & 0xff) ^ 0x80));
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
}
|
|
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ((ins->mSrc[ri].mIntConst >> 24) & 0xff) ^ 0x80));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_WORK));
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[li].mIntConst >> 24) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 3));
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins->mSrc[ri].mIntConst >> 24) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 3));
|
|
}
|
|
|
|
NativeCodeBasicBlock* eblock3 = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock2 = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock1 = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* nblock = nproc->AllocateBlock();
|
|
|
|
this->Close(nblock, eblock3, ASMIT_BNE);
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
eblock3->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[li].mIntConst >> 16) & 0xff));
|
|
else
|
|
eblock3->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 2));
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
eblock3->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins->mSrc[ri].mIntConst >> 16) & 0xff));
|
|
else
|
|
eblock3->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 2));
|
|
|
|
eblock3->Close(nblock, eblock2, ASMIT_BNE);
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
eblock2->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[li].mIntConst >> 8) & 0xff));
|
|
else
|
|
eblock2->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 1));
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
eblock2->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins->mSrc[ri].mIntConst >> 8) & 0xff));
|
|
else
|
|
eblock2->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 1));
|
|
|
|
eblock2->Close(nblock, eblock1, ASMIT_BNE);
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
eblock1->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[li].mIntConst & 0xff));
|
|
else
|
|
eblock1->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp]));
|
|
if (ins->mSrc[ri].mTemp < 0)
|
|
eblock1->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ins->mSrc[ri].mIntConst & 0xff));
|
|
else
|
|
eblock1->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp]));
|
|
|
|
switch (op)
|
|
{
|
|
case IA_CMPEQ:
|
|
nblock->Close(falseJump, nullptr, ASMIT_JMP);
|
|
eblock1->Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPNE:
|
|
nblock->Close(trueJump, nullptr, ASMIT_JMP);
|
|
eblock1->Close(falseJump, trueJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPLU:
|
|
case IA_CMPLS:
|
|
case IA_CMPGU:
|
|
case IA_CMPGS:
|
|
eblock1->Close(nblock, nullptr, ASMIT_JMP);
|
|
nblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
case IA_CMPLEU:
|
|
case IA_CMPLES:
|
|
case IA_CMPGEU:
|
|
case IA_CMPGES:
|
|
eblock1->Close(nblock, nullptr, ASMIT_JMP);
|
|
nblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mIntConst == 0 || ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst == 0)
|
|
{
|
|
int rt = ins->mSrc[1].mTemp;
|
|
if (rt < 0)
|
|
{
|
|
rt = ins->mSrc[0].mTemp;
|
|
switch (op)
|
|
{
|
|
case IA_CMPLEU:
|
|
op = IA_CMPGEU;
|
|
break;
|
|
case IA_CMPGEU:
|
|
op = IA_CMPLEU;
|
|
break;
|
|
case IA_CMPLU:
|
|
op = IA_CMPGU;
|
|
break;
|
|
case IA_CMPGU:
|
|
op = IA_CMPLU;
|
|
break;
|
|
case IA_CMPLES:
|
|
op = IA_CMPGES;
|
|
break;
|
|
case IA_CMPGES:
|
|
op = IA_CMPLES;
|
|
break;
|
|
case IA_CMPLS:
|
|
op = IA_CMPGS;
|
|
break;
|
|
case IA_CMPGS:
|
|
op = IA_CMPLS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (op)
|
|
{
|
|
case IA_CMPEQ:
|
|
case IA_CMPLEU:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPNE:
|
|
case IA_CMPGU:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(trueJump, falseJump, ASMIT_BNE);
|
|
break;
|
|
case IA_CMPGEU:
|
|
this->Close(trueJump, nullptr, ASMIT_JMP);
|
|
break;
|
|
case IA_CMPLU:
|
|
this->Close(falseJump, nullptr, ASMIT_JMP);
|
|
break;
|
|
case IA_CMPGES:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(trueJump, falseJump, ASMIT_BPL);
|
|
break;
|
|
case IA_CMPLS:
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(trueJump, falseJump, ASMIT_BMI);
|
|
break;
|
|
case IA_CMPGS:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, falseJump, ASMIT_BPL);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BNE);
|
|
break;
|
|
}
|
|
case IA_CMPLES:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, trueJump, ASMIT_BPL);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
#if 1
|
|
else if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mIntConst < 256 && ins->mSrc[1].mIntConst > 0 || ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst < 256 && ins->mSrc[0].mIntConst > 0)
|
|
{
|
|
int rt = ins->mSrc[1].mTemp;
|
|
int ival = ins->mSrc[0].mIntConst;
|
|
if (rt < 0)
|
|
{
|
|
rt = ins->mSrc[0].mTemp;
|
|
ival = ins->mSrc[1].mIntConst;
|
|
switch (op)
|
|
{
|
|
case IA_CMPLEU:
|
|
op = IA_CMPGEU;
|
|
break;
|
|
case IA_CMPGEU:
|
|
op = IA_CMPLEU;
|
|
break;
|
|
case IA_CMPLU:
|
|
op = IA_CMPGU;
|
|
break;
|
|
case IA_CMPGU:
|
|
op = IA_CMPLU;
|
|
break;
|
|
case IA_CMPLES:
|
|
op = IA_CMPGES;
|
|
break;
|
|
case IA_CMPGES:
|
|
op = IA_CMPLES;
|
|
break;
|
|
case IA_CMPLS:
|
|
op = IA_CMPGS;
|
|
break;
|
|
case IA_CMPGS:
|
|
op = IA_CMPLS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (op)
|
|
{
|
|
case IA_CMPEQ:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, falseJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
}
|
|
case IA_CMPNE:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, trueJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(falseJump, trueJump, ASMIT_BEQ);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPLEU:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, falseJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ival));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPGEU:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, trueJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPLU:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, falseJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPGU:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(eblock, trueJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ival));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPLES:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* sblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(sblock, trueJump, ASMIT_BPL);
|
|
sblock->Close(eblock, falseJump, ASMIT_BEQ);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ival));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPGES:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* sblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(sblock, falseJump, ASMIT_BPL);
|
|
sblock->Close(eblock, trueJump, ASMIT_BEQ);
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPLS:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* sblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(sblock, trueJump, ASMIT_BPL);
|
|
sblock->Close(eblock, falseJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ival));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
case IA_CMPGS:
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* sblock = nproc->AllocateBlock();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 1));
|
|
this->Close(sblock, falseJump, ASMIT_BPL);
|
|
sblock->Close(eblock, trueJump, ASMIT_BEQ);
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ival));
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[rt] + 0));
|
|
eblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
|
NativeCodeBasicBlock* nblock = nproc->AllocateBlock();
|
|
|
|
int li = 1, ri = 0;
|
|
if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS)
|
|
{
|
|
li = 0; ri = 1;
|
|
}
|
|
|
|
int iconst = 0;
|
|
bool rconst = false;
|
|
|
|
if (ins->mSrc[li].mTemp < 0 && (op == IA_CMPGES || op == IA_CMPLS) && int16(ins->mSrc[li].mIntConst) > - 32768)
|
|
{
|
|
iconst = ins->mSrc[li].mIntConst - 1;
|
|
rconst = true;
|
|
li = ri; ri = 1 - li;
|
|
|
|
NativeCodeBasicBlock* t = trueJump; trueJump = falseJump; falseJump = t;
|
|
}
|
|
else if (ins->mSrc[li].mTemp < 0 && (op == IA_CMPLES || op == IA_CMPGS) && int16(ins->mSrc[li].mIntConst) < 32767)
|
|
{
|
|
iconst = ins->mSrc[li].mIntConst + 1;
|
|
rconst = true;
|
|
li = ri; ri = 1 - li;
|
|
|
|
NativeCodeBasicBlock* t = trueJump; trueJump = falseJump; falseJump = t;
|
|
}
|
|
else if (ins->mSrc[ri].mTemp < 0)
|
|
{
|
|
iconst = ins->mSrc[ri].mIntConst;
|
|
rconst = true;
|
|
}
|
|
|
|
if (op >= IA_CMPGES && ins->mOperator <= IA_CMPLS)
|
|
{
|
|
if (!rconst)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK));
|
|
}
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ((ins->mSrc[li].mIntConst >> 8) & 0xff) ^ 0x80));
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
|
|
}
|
|
|
|
if (rconst)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ((iconst >> 8) & 0xff) ^ 0x80));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_WORK));
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[li].mIntConst >> 8) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp] + 1));
|
|
if (rconst)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (iconst >> 8) & 0xff));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp] + 1));
|
|
}
|
|
|
|
this->Close(nblock, eblock, ASMIT_BNE);
|
|
|
|
if (ins->mSrc[li].mTemp < 0)
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[li].mIntConst & 0xff));
|
|
else
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[li].mTemp]));
|
|
if (rconst)
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, iconst & 0xff));
|
|
else
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[ri].mTemp]));
|
|
|
|
switch (op)
|
|
{
|
|
case IA_CMPEQ:
|
|
nblock->Close(falseJump, nullptr, ASMIT_JMP);
|
|
eblock->Close(trueJump, falseJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPNE:
|
|
nblock->Close(trueJump, nullptr, ASMIT_JMP);
|
|
eblock->Close(falseJump, trueJump, ASMIT_BEQ);
|
|
break;
|
|
case IA_CMPLU:
|
|
case IA_CMPLS:
|
|
case IA_CMPGU:
|
|
case IA_CMPGS:
|
|
eblock->Close(nblock, nullptr, ASMIT_JMP);
|
|
nblock->Close(trueJump, falseJump, ASMIT_BCC);
|
|
break;
|
|
case IA_CMPLEU:
|
|
case IA_CMPLES:
|
|
case IA_CMPGEU:
|
|
case IA_CMPGES:
|
|
eblock->Close(nblock, nullptr, ASMIT_JMP);
|
|
nblock->Close(falseJump, trueJump, ASMIT_BCC);
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0)
|
|
{
|
|
if (sins1)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst == 0)
|
|
LoadValueToReg(proc, sins1, ins->mDst.mTemp, nullptr, nullptr);
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
NativeCodeInstruction ainsl(ASMIT_ADC, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff);
|
|
NativeCodeInstruction ainsh(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff);
|
|
|
|
LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], &ainsl, &ainsh);
|
|
}
|
|
else
|
|
{
|
|
NativeCodeInstruction ainsl(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]);
|
|
NativeCodeInstruction ainsh(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1);
|
|
|
|
LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp], &ainsl, &ainsh);
|
|
}
|
|
}
|
|
}
|
|
else if (ins->mSrc[1].mTemp < 0)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
if (ins->mSrc[1].mMemory == IM_GLOBAL)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_LOWER));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
// if the global variable is smaller than 256 bytes, we can safely ignore the upper byte?
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
|
|
if (ins->mSrc[1].mLinkerObject->mSize < 256)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[1].mIntConst & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_PROCEDURE)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_LOWER));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
else if (ins->mSrc[1].mMemory == IM_FPARAM)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ins->mSrc[0].mTemp >= 0 || ins->mSrc[0].mIntConst != 0)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mIntConst)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
|
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mIntConst)
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
}
|
|
else
|
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProcedure * nproc, const InterInstruction * ins)
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
NativeCodeInstruction lins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, NCIF_LOWER);
|
|
NativeCodeInstruction hins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, NCIF_UPPER);
|
|
|
|
mIns.Push(lins);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU));
|
|
mIns.Push(hins);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
}
|
|
|
|
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bcexec")));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
|
|
|
|
if (ins->mDst.mTemp >= 0)
|
|
{
|
|
if (ins->mDst.mType == IT_FLOAT)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
if (InterTypeSize[ins->mDst.mType] > 2)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction* ins)
|
|
{
|
|
if (ins->mCode == IC_ASSEMBLER)
|
|
{
|
|
for (int i = 1; i < ins->mNumOperands; i++)
|
|
{
|
|
if (ins->mSrc[i].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[i].mMemory == IM_FPARAM)
|
|
ins->mSrc[0].mLinkerObject->mTemporaries[i - 1] = BC_REG_FPARAMS + ins->mSrc[i].mVarIndex + ins->mSrc[i].mIntConst;
|
|
}
|
|
else
|
|
ins->mSrc[0].mLinkerObject->mTemporaries[i - 1] = BC_REG_TMP + proc->mTempOffset[ins->mSrc[i].mTemp];
|
|
ins->mSrc[0].mLinkerObject->mTempSizes[i - 1] = InterTypeSize[ins->mSrc[i].mType];
|
|
}
|
|
ins->mSrc[0].mLinkerObject->mNumTemporaries = ins->mNumOperands - 1;
|
|
}
|
|
|
|
assert(ins->mSrc[0].mLinkerObject);
|
|
|
|
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject));
|
|
|
|
if (ins->mDst.mTemp >= 0)
|
|
{
|
|
if (ins->mDst.mType == IT_FLOAT)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
}
|
|
else
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
if (InterTypeSize[ins->mDst.mType] > 2)
|
|
{
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 2));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::BuildLocalRegSets(void)
|
|
{
|
|
int i;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
mLocalRequiredRegs = NumberSet(NUM_REGS);
|
|
mLocalProvidedRegs = NumberSet(NUM_REGS);
|
|
|
|
mEntryRequiredRegs = NumberSet(NUM_REGS);
|
|
mEntryProvidedRegs = NumberSet(NUM_REGS);
|
|
mExitRequiredRegs = NumberSet(NUM_REGS);
|
|
mExitProvidedRegs = NumberSet(NUM_REGS);
|
|
|
|
for (i = 0; i < mIns.Size(); i++)
|
|
{
|
|
mIns[i].FilterRegUsage(mLocalRequiredRegs, mLocalProvidedRegs);
|
|
}
|
|
|
|
switch (mBranch)
|
|
{
|
|
case ASMIT_BCC:
|
|
case ASMIT_BCS:
|
|
if (!mLocalProvidedRegs[CPU_REG_C])
|
|
mLocalRequiredRegs += CPU_REG_C;
|
|
break;
|
|
case ASMIT_BEQ:
|
|
case ASMIT_BNE:
|
|
case ASMIT_BMI:
|
|
case ASMIT_BPL:
|
|
if (!mLocalProvidedRegs[CPU_REG_Z])
|
|
mLocalRequiredRegs += CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
mEntryRequiredRegs = mLocalRequiredRegs;
|
|
mExitProvidedRegs = mLocalProvidedRegs;
|
|
|
|
if (mTrueJump) mTrueJump->BuildLocalRegSets();
|
|
if (mFalseJump) mFalseJump->BuildLocalRegSets();
|
|
}
|
|
|
|
}
|
|
|
|
void NativeCodeBasicBlock::BuildGlobalProvidedRegSet(NumberSet fromProvidedRegs)
|
|
{
|
|
if (!mVisited || !(fromProvidedRegs <= mEntryProvidedRegs))
|
|
{
|
|
mEntryProvidedRegs |= fromProvidedRegs;
|
|
fromProvidedRegs |= mExitProvidedRegs;
|
|
|
|
mVisited = true;
|
|
|
|
if (mTrueJump) mTrueJump->BuildGlobalProvidedRegSet(fromProvidedRegs);
|
|
if (mFalseJump) mFalseJump->BuildGlobalProvidedRegSet(fromProvidedRegs);
|
|
}
|
|
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::BuildGlobalRequiredRegSet(NumberSet& fromRequiredRegs)
|
|
{
|
|
bool revisit = false;
|
|
int i;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
NumberSet newRequiredRegs(mExitRequiredRegs);
|
|
|
|
if (mTrueJump && mTrueJump->BuildGlobalRequiredRegSet(newRequiredRegs)) revisit = true;
|
|
if (mFalseJump && mFalseJump->BuildGlobalRequiredRegSet(newRequiredRegs)) revisit = true;
|
|
|
|
if (!(newRequiredRegs <= mExitRequiredRegs))
|
|
{
|
|
revisit = true;
|
|
|
|
mExitRequiredRegs = newRequiredRegs;
|
|
newRequiredRegs -= mLocalProvidedRegs;
|
|
mEntryRequiredRegs |= newRequiredRegs;
|
|
}
|
|
|
|
}
|
|
|
|
fromRequiredRegs |= mEntryRequiredRegs;
|
|
|
|
return revisit;
|
|
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
NumberSet requiredRegs(mExitRequiredRegs);
|
|
int i;
|
|
|
|
switch (mBranch)
|
|
{
|
|
case ASMIT_BCC:
|
|
case ASMIT_BCS:
|
|
requiredRegs += CPU_REG_C;
|
|
break;
|
|
case ASMIT_BEQ:
|
|
case ASMIT_BNE:
|
|
case ASMIT_BMI:
|
|
case ASMIT_BPL:
|
|
requiredRegs += CPU_REG_Z;
|
|
break;
|
|
}
|
|
|
|
for (i = mIns.Size() - 1; i >= 0; i--)
|
|
{
|
|
if (mIns[i].mType != ASMIT_NOP && !mIns[i].IsUsedResultInstructions(requiredRegs))
|
|
{
|
|
if (i > 0 && mIns[i - 1].mMode == ASMIM_RELATIVE && mIns[i - 1].mAddress > 0)
|
|
{
|
|
mIns[i - 1].mType = ASMIT_NOP;
|
|
mIns[i - 1].mMode = ASMIM_IMPLIED;
|
|
}
|
|
mIns[i].mType = ASMIT_NOP;
|
|
mIns[i].mMode = ASMIM_IMPLIED;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (mTrueJump)
|
|
{
|
|
if (mTrueJump->RemoveUnusedResultInstructions())
|
|
changed = true;
|
|
}
|
|
if (mFalseJump)
|
|
{
|
|
if (mFalseJump->RemoveUnusedResultInstructions())
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
|
|
{
|
|
if (mVisiting)
|
|
mLoopHead = true;
|
|
|
|
if (mNumEntries == 0)
|
|
mFromJump = fromJump;
|
|
else
|
|
mFromJump = nullptr;
|
|
mNumEntries++;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
mVisiting = true;
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->CountEntries(this);
|
|
if (mFalseJump)
|
|
mFalseJump->CountEntries(this);
|
|
|
|
mVisiting = false;
|
|
}
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MergeBasicBlocks(void)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
if (!mLocked)
|
|
{
|
|
while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this && !mTrueJump->mLocked)
|
|
{
|
|
for (int i = 0; i < mTrueJump->mIns.Size(); i++)
|
|
mIns.Push(mTrueJump->mIns[i]);
|
|
mBranch = mTrueJump->mBranch;
|
|
mFalseJump = mTrueJump->mFalseJump;
|
|
mTrueJump = mTrueJump->mTrueJump;
|
|
changed = true;
|
|
}
|
|
|
|
while (mTrueJump && mTrueJump->mIns.Size() == 0 && !mTrueJump->mFalseJump && !mTrueJump->mLocked && mTrueJump != this)
|
|
{
|
|
mTrueJump->mNumEntries--;
|
|
mTrueJump = mTrueJump->mTrueJump;
|
|
mTrueJump->mNumEntries++;
|
|
changed = true;
|
|
}
|
|
|
|
while (mFalseJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this)
|
|
{
|
|
mFalseJump->mNumEntries--;
|
|
mFalseJump = mFalseJump->mTrueJump;
|
|
mFalseJump->mNumEntries++;
|
|
changed = true;
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump == mFalseJump)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->MergeBasicBlocks();
|
|
if (mFalseJump)
|
|
mFalseJump->MergeBasicBlocks();
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CollectEntryBlocks(NativeCodeBasicBlock* block)
|
|
{
|
|
if (block)
|
|
mEntryBlocks.Push(block);
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->CollectEntryBlocks(this);
|
|
if (mFalseJump)
|
|
mFalseJump->CollectEntryBlocks(this);
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::BuildEntryDataSet(const NativeRegisterDataSet& set)
|
|
{
|
|
if (!mVisited)
|
|
mEntryRegisterDataSet = set;
|
|
else
|
|
{
|
|
bool changed = false;
|
|
for (int i = 0; i < NUM_REGS; i++)
|
|
{
|
|
if (set.mRegs[i].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
if (mEntryRegisterDataSet.mRegs[i].mMode == NRDM_IMMEDIATE && set.mRegs[i].mValue == mEntryRegisterDataSet.mRegs[i].mValue)
|
|
{
|
|
}
|
|
else if (mEntryRegisterDataSet.mRegs[i].mMode != NRDM_UNKNOWN)
|
|
{
|
|
mEntryRegisterDataSet.mRegs[i].Reset();
|
|
mVisited = false;
|
|
}
|
|
}
|
|
else if (set.mRegs[i].mMode == NRDM_IMMEDIATE_ADDRESS)
|
|
{
|
|
if (mEntryRegisterDataSet.mRegs[i].mMode == NRDM_IMMEDIATE_ADDRESS &&
|
|
set.mRegs[i].mValue == mEntryRegisterDataSet.mRegs[i].mValue &&
|
|
set.mRegs[i].mLinkerObject == mEntryRegisterDataSet.mRegs[i].mLinkerObject &&
|
|
set.mRegs[i].mFlags == mEntryRegisterDataSet.mRegs[i].mFlags)
|
|
{
|
|
}
|
|
else if (mEntryRegisterDataSet.mRegs[i].mMode != NRDM_UNKNOWN)
|
|
{
|
|
mEntryRegisterDataSet.mRegs[i].Reset();
|
|
mVisited = false;
|
|
}
|
|
}
|
|
else if (mEntryRegisterDataSet.mRegs[i].mMode != NRDM_UNKNOWN)
|
|
{
|
|
mEntryRegisterDataSet.mRegs[i].Reset();
|
|
mVisited = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
mNDataSet = mEntryRegisterDataSet;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
mIns[i].Simulate(mNDataSet);
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->BuildEntryDataSet(mNDataSet);
|
|
if (mFalseJump)
|
|
mFalseJump->BuildEntryDataSet(mNDataSet);
|
|
}
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::ApplyEntryDataSet(void)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
mNDataSet = mEntryRegisterDataSet;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].ApplySimulation(mNDataSet))
|
|
changed = true;
|
|
mIns[i].Simulate(mNDataSet);
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump->ApplyEntryDataSet())
|
|
changed = true;
|
|
if (mFalseJump && mFalseJump->ApplyEntryDataSet())
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CollectZeroPageUsage(NumberSet& used)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
switch (mIns[i].mMode)
|
|
{
|
|
case ASMIM_ZERO_PAGE:
|
|
used += mIns[i].mAddress;
|
|
break;
|
|
case ASMIM_INDIRECT_Y:
|
|
used += mIns[i].mAddress + 0;
|
|
used += mIns[i].mAddress + 1;
|
|
break;
|
|
case ASMIM_ABSOLUTE:
|
|
if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject)
|
|
{
|
|
LinkerObject* lo = mIns[i].mLinkerObject;
|
|
|
|
for (int i = 0; i < lo->mNumTemporaries; i++)
|
|
{
|
|
for (int j = 0; j < lo->mTempSizes[i]; j++)
|
|
used += lo->mTemporaries[i] + j;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->CollectZeroPageUsage(used);
|
|
if (mFalseJump)
|
|
mFalseJump->CollectZeroPageUsage(used);
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::GlobalRegisterXMap(int reg)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
NativeCodeInstruction& ins(mIns[i]);
|
|
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
|
|
{
|
|
switch (ins.mType)
|
|
{
|
|
case ASMIT_STA:
|
|
ins.mType = ASMIT_TAX;
|
|
ins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_LDA:
|
|
ins.mType = ASMIT_TXA;
|
|
ins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_INC:
|
|
ins.mType = ASMIT_INX;
|
|
ins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_DEC:
|
|
ins.mType = ASMIT_DEX;
|
|
ins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->GlobalRegisterXMap(reg);
|
|
if (mFalseJump)
|
|
mFalseJump->GlobalRegisterXMap(reg);
|
|
}
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::LocalRegisterXYMap(void)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
int xregs[256], yregs[256];
|
|
for (int i = 0; i < 256; i++)
|
|
xregs[i] = yregs[i] = -1;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
const NativeCodeInstruction& ins(mIns[i]);
|
|
|
|
if (ins.ChangesXReg())
|
|
{
|
|
for (int i = 0; i < 256; i++)
|
|
xregs[i] = -1;
|
|
}
|
|
if (ins.ChangesYReg())
|
|
{
|
|
for (int i = 0; i < 256; i++)
|
|
yregs[i] = -1;
|
|
}
|
|
|
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (ins.mType)
|
|
{
|
|
case ASMIT_STA:
|
|
if (ins.mAddress >= BC_REG_ACCU && ins.mAddress < BC_REG_ACCU + 4 ||
|
|
ins.mAddress >= BC_REG_WORK && ins.mAddress < BC_REG_WORK + 4)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
if (!(ins.mLive & LIVE_CPU_REG_X))
|
|
{
|
|
if (xregs[ins.mAddress] < 0)
|
|
xregs[ins.mAddress] = i;
|
|
}
|
|
if (!(ins.mLive & LIVE_CPU_REG_Y))
|
|
{
|
|
if (yregs[ins.mAddress] < 0)
|
|
yregs[ins.mAddress] = i;
|
|
}
|
|
}
|
|
break;
|
|
case ASMIT_LDA:
|
|
if (xregs[ins.mAddress] >= 0 && !(ins.mLive & LIVE_MEM))
|
|
{
|
|
changed = true;
|
|
|
|
for (int j = xregs[ins.mAddress]; j <= i; j++)
|
|
{
|
|
NativeCodeInstruction& rins(mIns[j]);
|
|
if (rins.mMode == ASMIM_ZERO_PAGE && rins.mAddress == ins.mAddress)
|
|
{
|
|
switch (rins.mType)
|
|
{
|
|
case ASMIT_STA:
|
|
rins.mType = ASMIT_TAX;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_LDA:
|
|
rins.mType = ASMIT_TXA;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_INC:
|
|
rins.mType = ASMIT_INX;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_DEC:
|
|
rins.mType = ASMIT_DEX;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
}
|
|
}
|
|
rins.mLive |= LIVE_CPU_REG_X;
|
|
}
|
|
for (int i = 0; i < 256; i++)
|
|
xregs[i] = -1;
|
|
}
|
|
else if (yregs[ins.mAddress] >= 0 && !(ins.mLive & LIVE_MEM))
|
|
{
|
|
changed = true;
|
|
|
|
for (int j = yregs[ins.mAddress]; j <= i; j++)
|
|
{
|
|
NativeCodeInstruction& rins(mIns[j]);
|
|
if (rins.mMode == ASMIM_ZERO_PAGE && rins.mAddress == ins.mAddress)
|
|
{
|
|
switch (rins.mType)
|
|
{
|
|
case ASMIT_STA:
|
|
rins.mType = ASMIT_TAY;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_LDA:
|
|
rins.mType = ASMIT_TYA;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_INC:
|
|
rins.mType = ASMIT_INY;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
case ASMIT_DEC:
|
|
rins.mType = ASMIT_DEY;
|
|
rins.mMode = ASMIM_IMPLIED;
|
|
break;
|
|
}
|
|
}
|
|
rins.mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
for (int i = 0; i < 256; i++)
|
|
yregs[i] = -1;
|
|
}
|
|
break;
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
break;
|
|
default:
|
|
xregs[ins.mAddress + 0] = -1;
|
|
yregs[ins.mAddress + 0] = -1;
|
|
break;
|
|
}
|
|
}
|
|
else if (ins.mMode == ASMIM_INDIRECT_Y)
|
|
{
|
|
xregs[ins.mAddress + 0] = -1;
|
|
xregs[ins.mAddress + 1] = -1;
|
|
yregs[ins.mAddress + 0] = -1;
|
|
yregs[ins.mAddress + 1] = -1;
|
|
}
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump->LocalRegisterXYMap())
|
|
changed = true;
|
|
|
|
if (mFalseJump && mFalseJump->LocalRegisterXYMap())
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::GlobalRegisterXYCheck(int* xregs, int* yregs)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
const NativeCodeInstruction& ins(mIns[i]);
|
|
if (ins.ChangesXReg())
|
|
xregs[0] = -1;
|
|
if (ins.ChangesYReg())
|
|
yregs[0] = -1;
|
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
switch (ins.mType)
|
|
{
|
|
case ASMIT_LDA:
|
|
if (yregs[ins.mAddress] >= 0)
|
|
yregs[ins.mAddress]++;
|
|
if (xregs[ins.mAddress] >= 0)
|
|
xregs[ins.mAddress]++;
|
|
break;
|
|
case ASMIT_STA:
|
|
if (ins.mLive & LIVE_CPU_REG_Z)
|
|
{
|
|
xregs[ins.mAddress + 0] = -1;
|
|
yregs[ins.mAddress + 0] = -1;
|
|
}
|
|
else
|
|
{
|
|
if (yregs[ins.mAddress] >= 0)
|
|
yregs[ins.mAddress]++;
|
|
if (xregs[ins.mAddress] >= 0)
|
|
xregs[ins.mAddress]++;
|
|
}
|
|
break;
|
|
case ASMIT_INC:
|
|
case ASMIT_DEC:
|
|
if (yregs[ins.mAddress] >= 0)
|
|
yregs[ins.mAddress] += 3;
|
|
if (xregs[ins.mAddress] >= 0)
|
|
xregs[ins.mAddress] += 3;
|
|
break;
|
|
default:
|
|
xregs[ins.mAddress + 0] = -1;
|
|
yregs[ins.mAddress + 0] = -1;
|
|
break;
|
|
}
|
|
}
|
|
else if (ins.mMode == ASMIM_INDIRECT_Y)
|
|
{
|
|
xregs[ins.mAddress + 0] = -1;
|
|
xregs[ins.mAddress + 1] = -1;
|
|
yregs[ins.mAddress + 0] = -1;
|
|
yregs[ins.mAddress + 1] = -1;
|
|
}
|
|
else if (ins.mMode == ASMIM_ZERO_PAGE_X || ins.mMode == ASMIM_ZERO_PAGE_Y)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
if (xregs[0] >= 0 || yregs[0] >= 0)
|
|
{
|
|
if (mTrueJump)
|
|
mTrueJump->GlobalRegisterXYCheck(xregs, yregs);
|
|
if (mFalseJump)
|
|
mFalseJump->GlobalRegisterXYCheck(xregs, yregs);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::RemapZeroPage(const uint8* remap)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
switch (mIns[i].mMode)
|
|
{
|
|
case ASMIM_ZERO_PAGE:
|
|
case ASMIM_INDIRECT_Y:
|
|
mIns[i].mAddress = remap[mIns[i].mAddress];
|
|
break;
|
|
case ASMIM_ABSOLUTE:
|
|
if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject)
|
|
{
|
|
LinkerObject* lo = mIns[i].mLinkerObject;
|
|
|
|
for (int j = 0; j < lo->mNumTemporaries; j++)
|
|
{
|
|
lo->mTemporaries[j] = remap[lo->mTemporaries[j]];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mTrueJump)
|
|
mTrueJump->RemapZeroPage(remap);
|
|
if (mFalseJump)
|
|
mFalseJump->RemapZeroPage(remap);
|
|
}
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const
|
|
{
|
|
if (mIns.Size() > 0)
|
|
return mIns[mIns.Size() - 1].IsSame(ins);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
if (mEntryBlocks.Size() > 1)
|
|
{
|
|
int i = 0;
|
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mBranch == ASMIT_JMP)
|
|
i++;
|
|
if (i == mEntryBlocks.Size())
|
|
{
|
|
NativeCodeBasicBlock* eb = mEntryBlocks[0];
|
|
|
|
while (eb->mIns.Size() > 0)
|
|
{
|
|
NativeCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
|
i = 1;
|
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->SameTail(ins))
|
|
i++;
|
|
if (i == mEntryBlocks.Size())
|
|
{
|
|
mIns.Insert(0, ins);
|
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
|
{
|
|
NativeCodeBasicBlock* b = mEntryBlocks[i];
|
|
b->mIns.SetSize(b->mIns.Size() - 1);
|
|
}
|
|
changed = true;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump->JoinTailCodeSequences())
|
|
changed = true;
|
|
if (mFalseJump && mFalseJump->JoinTailCodeSequences())
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
|
|
bool NativeCodeBasicBlock::FindGlobalAddress(int at, int reg, int& apos)
|
|
{
|
|
int j = at - 4;
|
|
while (j >= 0)
|
|
{
|
|
if (mIns[j + 0].mType == ASMIT_LDA && mIns[j + 0].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 0].mFlags & NCIF_LOWER) && mIns[j + 0].mLinkerObject &&
|
|
mIns[j + 1].mType == ASMIT_STA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE && mIns[j + 1].mAddress == reg &&
|
|
mIns[j + 2].mType == ASMIT_LDA && mIns[j + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_UPPER) && mIns[j + 2].mLinkerObject == mIns[j + 0].mLinkerObject &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg + 1)
|
|
{
|
|
apos = j + 0;
|
|
return true;
|
|
}
|
|
if (mIns[j + 3].mMode == ASMIM_ZERO_PAGE && (mIns[j + 3].mAddress == reg || mIns[j + 3].mAddress == reg + 1) && mIns[j + 3].ChangesAddress())
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction*& ains, const NativeCodeInstruction*& iins, uint32& flags)
|
|
{
|
|
flags = 0;
|
|
|
|
int j = at - 7;
|
|
while (j >= 0)
|
|
{
|
|
if (mIns[j + 0].mType == ASMIT_CLC &&
|
|
mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 1].mFlags & NCIF_LOWER) && mIns[j + 1].mLinkerObject &&
|
|
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
|
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 1].mLinkerObject &&
|
|
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 &&
|
|
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
|
{
|
|
ains = &(mIns[j + 1]);
|
|
iins = &(mIns[j + 2]);
|
|
apos = j + 0;
|
|
|
|
int ireg = iins->mAddress;
|
|
if (reg == ireg && !direct)
|
|
return false;
|
|
|
|
int k = j + 7;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress())
|
|
return false;
|
|
if (reg == ireg && mIns[k].ChangesYReg())
|
|
return false;
|
|
k++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (
|
|
mIns[j + 0].mType == ASMIT_STA && mIns[j + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[j + 1].mType == ASMIT_CLC &&
|
|
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_LOWER) && mIns[j + 2].mLinkerObject &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
|
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 2].mLinkerObject &&
|
|
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 &&
|
|
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
|
{
|
|
ains = &(mIns[j + 2]);
|
|
iins = &(mIns[j + 0]);
|
|
apos = j + 1;
|
|
|
|
int ireg = iins->mAddress;
|
|
if (reg == ireg && !direct)
|
|
return false;
|
|
|
|
int k = j + 7;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress())
|
|
return false;
|
|
if (reg == ireg && mIns[k].ChangesYReg())
|
|
return false;
|
|
k++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (mIns[j + 0].mType == ASMIT_CLC &&
|
|
mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 1].mFlags & NCIF_LOWER) && mIns[j + 1].mLinkerObject &&
|
|
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ABSOLUTE &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
|
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 1].mLinkerObject &&
|
|
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 &&
|
|
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
|
{
|
|
ains = &(mIns[j + 1]);
|
|
iins = &(mIns[j + 2]);
|
|
apos = j + 0;
|
|
|
|
int k = j + 7;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].ChangesGlobalMemory())
|
|
return false;
|
|
k++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#if 1
|
|
else if (
|
|
mIns[j + 1].mType == ASMIT_CLC &&
|
|
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 2].mFlags & NCIF_LOWER) && mIns[j + 2].mLinkerObject &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
|
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[j + 4].mFlags & NCIF_UPPER) && mIns[j + 4].mLinkerObject == mIns[j + 2].mLinkerObject &&
|
|
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 &&
|
|
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
|
{
|
|
ains = &(mIns[j + 2]);
|
|
iins = nullptr;
|
|
apos = j + 1;
|
|
|
|
if (!direct)
|
|
return false;
|
|
|
|
flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[j + 1].mLive;
|
|
|
|
int k = j + 7;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].ChangesYReg())
|
|
flags &= ~LIVE_CPU_REG_Y;
|
|
if (mIns[k].ChangesXReg())
|
|
flags &= ~LIVE_CPU_REG_X;
|
|
k++;
|
|
}
|
|
|
|
return flags != 0;
|
|
}
|
|
#endif
|
|
|
|
if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress())
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
if (mFromJump)
|
|
{
|
|
while (j >= -6)
|
|
{
|
|
if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress())
|
|
return false;
|
|
j--;
|
|
}
|
|
if (mFromJump->FindGlobalAddressSumY(mFromJump->mIns.Size(), reg, false, apos, ains, iins, flags))
|
|
{
|
|
if (iins->mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
int ireg = iins->mAddress;
|
|
int k = 0;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].mMode == ASMIM_ZERO_PAGE && mIns[k].mAddress == ireg && mIns[k].ChangesAddress())
|
|
return false;
|
|
k++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int k = 0;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].ChangesGlobalMemory())
|
|
return false;
|
|
k++;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg)
|
|
{
|
|
int j = at - 7;
|
|
while (j >= 0)
|
|
{
|
|
if (
|
|
mIns[j + 0].mType == ASMIT_CLC &&
|
|
mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg &&
|
|
mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_ZERO_PAGE && mIns[j + 4].mAddress == mIns[j + 1].mAddress + 1 &&
|
|
mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 &&
|
|
mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1)
|
|
{
|
|
breg = mIns[j + 1].mAddress;
|
|
ireg = mIns[j + 2].mAddress;
|
|
|
|
int k = j + 7;
|
|
while (k < at)
|
|
{
|
|
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress())
|
|
return false;
|
|
if (breg == reg)
|
|
{
|
|
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1))
|
|
return false;
|
|
if (mIns[k].mMode == ASMIM_INDIRECT_Y && mIns[k].mAddress == breg)
|
|
return false;
|
|
}
|
|
k++;
|
|
}
|
|
|
|
apos = j;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress())
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
|
|
{
|
|
int j = at - 1;
|
|
while (j > 0)
|
|
{
|
|
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress)
|
|
{
|
|
mIns.Insert(j + 1, mIns[at + 1]);
|
|
mIns.Insert(j + 2, mIns[at + 3]);
|
|
mIns[at + 4].mType = ASMIT_NOP;
|
|
mIns[at + 4].mMode = ASMIM_IMPLIED;
|
|
return true;
|
|
}
|
|
|
|
if (mIns[j].mLive & LIVE_CPU_REG_Y)
|
|
return false;
|
|
if (mIns[j].ChangesYReg())
|
|
return false;
|
|
if (mIns[j].ChangesZeroPage(mIns[at].mAddress))
|
|
return false;
|
|
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress))
|
|
return false;
|
|
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress + 1))
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
|
|
{
|
|
int j = at - 1;
|
|
while (j > 0)
|
|
{
|
|
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress)
|
|
{
|
|
mIns[j].mLive |= LIVE_CPU_REG_A;
|
|
mIns.Insert(j + 1, mIns[at + 1]);
|
|
mIns[at + 2].mType = ASMIT_NOP;
|
|
mIns[at + 2].mMode = ASMIM_IMPLIED;
|
|
return true;
|
|
}
|
|
if (mIns[j].ChangesZeroPage(mIns[at].mAddress))
|
|
return false;
|
|
if (mIns[j].ChangesGlobalMemory())
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MoveStoreXUp(int at)
|
|
{
|
|
bool done = false;
|
|
|
|
while (at > 0)
|
|
{
|
|
if (mIns[at - 1].ChangesXReg() || mIns[at - 1].mType == ASMIT_STX)
|
|
return done;
|
|
if ((mIns[at - 1].mMode == ASMIM_ZERO_PAGE || mIns[at - 1].mMode == ASMIM_INDIRECT_Y) && mIns[at - 1].mAddress == mIns[at].mAddress)
|
|
return done;
|
|
if (mIns[at - 1].mMode == ASMIM_INDIRECT_Y && mIns[at - 1].mAddress == mIns[at].mAddress + 1)
|
|
return done;
|
|
|
|
NativeCodeInstruction ins = mIns[at - 1];
|
|
mIns[at - 1] = mIns[at];
|
|
mIns[at] = ins;
|
|
at--;
|
|
done = true;
|
|
}
|
|
|
|
return done;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
|
{
|
|
int j = at;
|
|
while (j > 0 && !((mIns[j - 1].mType == ASMIT_STA || mIns[j - 1].mType == ASMIT_LDA) && mIns[j - 1].mMode == ASMIM_ZERO_PAGE && mIns[j - 1].mAddress == mIns[at].mAddress))
|
|
{
|
|
j--;
|
|
if ((mIns[j].mMode == ASMIM_ZERO_PAGE || mIns[j].mMode == ASMIM_INDIRECT_Y) && mIns[j].mAddress == mIns[at + 1].mAddress)
|
|
return false;
|
|
if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress + 1 == mIns[at + 1].mAddress)
|
|
return false;
|
|
if (mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress && mIns[j].ChangesAddress())
|
|
return false;
|
|
if (mIns[j].mMode == ASMIM_ABSOLUTE_Y && mIns[j].mAddress <= mIns[at + 1].mAddress && mIns[j].mType == ASMIT_LDA && !mIns[j].mLinkerObject)
|
|
return false;
|
|
if (mIns[j].mType == ASMIT_JSR)
|
|
return false;
|
|
}
|
|
|
|
if (j > 0 && j < at)
|
|
{
|
|
for (int i = at; i > j; i--)
|
|
{
|
|
mIns[i] = mIns[i - 1];
|
|
}
|
|
mIns[j - 1].mLive |= LIVE_CPU_REG_A;
|
|
mIns[j] = mIns[at + 1];
|
|
mIns[at + 1].mType = ASMIT_NOP;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at)
|
|
{
|
|
int j = at - 1;
|
|
while (j > 0)
|
|
{
|
|
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at + 1].mAddress)
|
|
{
|
|
mIns.Insert(j + 1, mIns[at + 3]); // STA
|
|
mIns.Insert(j + 1, mIns[at + 3]); // ADC
|
|
mIns.Insert(j + 1, mIns[at + 2]); // CLC
|
|
|
|
mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED;
|
|
mIns[at + 4].mType = ASMIT_NOP; mIns[at + 4].mMode = ASMIM_IMPLIED;
|
|
mIns[at + 5].mType = ASMIT_NOP; mIns[at + 5].mMode = ASMIM_IMPLIED;
|
|
mIns[at + 6].mType = ASMIT_NOP; mIns[at + 6].mMode = ASMIM_IMPLIED;
|
|
return true;
|
|
}
|
|
|
|
if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress))
|
|
return false;
|
|
if (mIns[j].UsesZeroPage(mIns[at + 3].mAddress))
|
|
return false;
|
|
if (mIns[j].ChangesCarry())
|
|
return false;
|
|
|
|
j--;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mNDataSet = data;
|
|
|
|
if (mLoopHead)
|
|
{
|
|
mNDataSet.Reset();
|
|
}
|
|
#if 0
|
|
else if (mNumEntries != 1)
|
|
{
|
|
ndata.Reset();
|
|
}
|
|
#endif
|
|
else if (mNumEntries > 0)
|
|
{
|
|
if (mNumEntered > 0)
|
|
mNDataSet.Intersect(mDataSet);
|
|
|
|
mNumEntered++;
|
|
|
|
if (mNumEntered < mNumEntries)
|
|
{
|
|
mDataSet = mNDataSet;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mVisited = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
AsmInsType carryop;
|
|
|
|
// Check load and commutative with current accu value
|
|
|
|
if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress)
|
|
{
|
|
mIns[i].mType = mIns[i + 1].mType;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
}
|
|
|
|
if (mIns[i].ValueForwarding(mNDataSet, carryop))
|
|
changed = true;
|
|
if (carryop != ASMIT_NOP)
|
|
mIns.Insert(i + 1, NativeCodeInstruction(carryop));
|
|
}
|
|
|
|
#if 1
|
|
NativeCodeBasicBlock* fork = this;
|
|
if (!mFalseJump && mTrueJump && mTrueJump->mIns.Size() == 0)
|
|
fork = mTrueJump;
|
|
|
|
if (fork->mFalseJump)
|
|
{
|
|
switch (fork->mBranch)
|
|
{
|
|
case ASMIT_BCS:
|
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if (!mNDataSet.mRegs[CPU_REG_C].mValue)
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
case ASMIT_BCC:
|
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if (mNDataSet.mRegs[CPU_REG_C].mValue)
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
case ASMIT_BNE:
|
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if (!mNDataSet.mRegs[CPU_REG_Z].mValue)
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
case ASMIT_BEQ:
|
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if (mNDataSet.mRegs[CPU_REG_Z].mValue)
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
case ASMIT_BPL:
|
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if ((mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
case ASMIT_BMI:
|
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
|
{
|
|
mBranch = ASMIT_JMP;
|
|
if (!(mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
|
|
mTrueJump = fork->mFalseJump;
|
|
else
|
|
mTrueJump = fork->mTrueJump;
|
|
mFalseJump = nullptr;
|
|
changed = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
if (this->mTrueJump && this->mTrueJump->ValueForwarding(mNDataSet))
|
|
changed = true;
|
|
if (this->mFalseJump && this->mFalseJump->ValueForwarding(mNDataSet))
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
bool changed = false;
|
|
int sz = mIns.Size();
|
|
if (sz > 3 && sz < 200 && mNumEntries == 2 && mTrueJump == this)
|
|
{
|
|
bool simple = true;
|
|
|
|
for(int i=0; i<mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_JSR)
|
|
simple = false;
|
|
}
|
|
|
|
if (simple)
|
|
{
|
|
if (mIns[sz - 3].mType == ASMIT_INC && mIns[sz - 3].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && mIns[sz - 3].mAddress == mIns[sz - 2].mAddress &&
|
|
mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y)) &&
|
|
mBranch == ASMIT_BCC)
|
|
{
|
|
// check for usage of Y register
|
|
|
|
bool yother = false, yindex = false, xother = false, xindex = false;
|
|
int zreg = mIns[sz - 3].mAddress;
|
|
int limit = mIns[sz - 1].mAddress;
|
|
|
|
for (int i = 0; i < sz - 3; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY)
|
|
yother = true;
|
|
else if (mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yindex = true;
|
|
else
|
|
yother = true;
|
|
}
|
|
else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y))
|
|
yother = true;
|
|
else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yother = true;
|
|
|
|
if (mIns[i].mType == ASMIT_INX || mIns[i].mType == ASMIT_DEX || mIns[i].mType == ASMIT_TAX)
|
|
xother = true;
|
|
else if (mIns[i].mType == ASMIT_LDX)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
xindex = true;
|
|
else
|
|
xother = true;
|
|
}
|
|
else if (!xindex && (mIns[i].mType == ASMIT_STX || mIns[i].mType == ASMIT_TXA || mIns[i].mMode == ASMIM_ABSOLUTE_X || mIns[i].mMode == ASMIM_INDIRECT_X))
|
|
xother = true;
|
|
else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
xother = true;
|
|
}
|
|
|
|
if (!yother)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
for (int i = 0; i + 3 < sz; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
else if (mIns[i].mType != ASMIT_LDY)
|
|
lblock->mIns.Push(mIns[i]);
|
|
}
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_IMMEDIATE, limit));
|
|
lblock->mBranch = mBranch;
|
|
lblock->mTrueJump = lblock;
|
|
lblock->mFalseJump = eblock;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
|
|
mIns.Clear();
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
|
mBranch = ASMIT_JMP;
|
|
mTrueJump = lblock;
|
|
mFalseJump = nullptr;
|
|
|
|
changed = true;
|
|
}
|
|
else if (!xother)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
for (int i = 0; i + 3 < sz; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
else if (mIns[i].mType != ASMIT_LDX)
|
|
lblock->mIns.Push(mIns[i]);
|
|
}
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INX, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, limit));
|
|
lblock->mBranch = mBranch;
|
|
lblock->mTrueJump = lblock;
|
|
lblock->mFalseJump = eblock;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
mIns.SetSize(0);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, zreg));
|
|
mBranch = ASMIT_JMP;
|
|
mTrueJump = lblock;
|
|
mFalseJump = nullptr;
|
|
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (mIns[sz - 1].mType == ASMIT_DEC && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && mBranch == ASMIT_BNE)
|
|
{
|
|
// check for usage of Y register
|
|
|
|
bool yother = false, yindex = false;
|
|
int zreg = mIns[sz - 1].mAddress;
|
|
|
|
for (int i = 0; i < sz - 1; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY)
|
|
yother = true;
|
|
else if (mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yindex = true;
|
|
else
|
|
yother = true;
|
|
}
|
|
else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y))
|
|
yother = true;
|
|
else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yother = true;
|
|
}
|
|
|
|
if (!yother)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
for (int i = 0; i + 1 < sz; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
else if (mIns[i].mType != ASMIT_LDY)
|
|
lblock->mIns.Push(mIns[i]);
|
|
}
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
lblock->mBranch = mBranch;
|
|
lblock->mTrueJump = lblock;
|
|
lblock->mFalseJump = eblock;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
mIns.SetSize(0);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
|
mBranch = ASMIT_JMP;
|
|
mTrueJump = lblock;
|
|
mFalseJump = nullptr;
|
|
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (mIns[sz - 3].mType == ASMIT_INC && mIns[sz - 3].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && mIns[sz - 3].mAddress == mIns[sz - 2].mAddress &&
|
|
mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y)) &&
|
|
mBranch == ASMIT_BCC)
|
|
{
|
|
// check for usage of Y register
|
|
|
|
bool yother = false, yindex = false, lchanged = false, xother = false, xindex = false;
|
|
int lreg = mIns[sz - 1].mAddress;
|
|
int zreg = mIns[sz - 3].mAddress;
|
|
|
|
for (int i = 0; i < sz - 3; i++)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == lreg && mIns[i].ChangesAddress())
|
|
lchanged = true;
|
|
|
|
if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY)
|
|
yother = true;
|
|
else if (mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yindex = true;
|
|
else
|
|
yother = true;
|
|
}
|
|
else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y))
|
|
yother = true;
|
|
else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
yother = true;
|
|
|
|
if (mIns[i].mType == ASMIT_INX || mIns[i].mType == ASMIT_DEX || mIns[i].mType == ASMIT_TAX)
|
|
xother = true;
|
|
else if (mIns[i].mType == ASMIT_LDX)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
xindex = true;
|
|
else
|
|
xother = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
xother = true;
|
|
else if (!xindex && (mIns[i].mType == ASMIT_STX || mIns[i].mType == ASMIT_TXA || mIns[i].mMode == ASMIM_ABSOLUTE_X || mIns[i].mMode == ASMIM_INDIRECT_X))
|
|
xother = true;
|
|
else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
xother = true;
|
|
}
|
|
|
|
if (!yother && !lchanged)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
for (int i = 0; i + 3 < sz; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
else if (mIns[i].mType != ASMIT_LDY)
|
|
lblock->mIns.Push(mIns[i]);
|
|
}
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_ZERO_PAGE, lreg));
|
|
lblock->mBranch = mBranch;
|
|
lblock->mTrueJump = lblock;
|
|
lblock->mFalseJump = eblock;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
mIns.SetSize(0);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
|
mBranch = ASMIT_JMP;
|
|
mTrueJump = lblock;
|
|
mFalseJump = nullptr;
|
|
|
|
changed = true;
|
|
}
|
|
else if (!xother && !lchanged)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
for (int i = 0; i + 3 < sz; i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
else if (mIns[i].mType != ASMIT_LDX)
|
|
lblock->mIns.Push(mIns[i]);
|
|
}
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INX, ASMIM_IMPLIED));
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_ZERO_PAGE, lreg));
|
|
lblock->mBranch = mBranch;
|
|
lblock->mTrueJump = lblock;
|
|
lblock->mFalseJump = eblock;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
mIns.SetSize(0);
|
|
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, zreg));
|
|
mBranch = ASMIT_JMP;
|
|
mTrueJump = lblock;
|
|
mFalseJump = nullptr;
|
|
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump->OptimizeSimpleLoop(proc))
|
|
changed = true;
|
|
if (mFalseJump && mFalseJump->OptimizeSimpleLoop(proc))
|
|
changed = true;
|
|
|
|
return changed;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& lblocks)
|
|
{
|
|
bool simple = true;
|
|
|
|
for (int j = 0; j < lblocks.Size(); j++)
|
|
{
|
|
NativeCodeBasicBlock* block = lblocks[j];
|
|
for (int i = 0; i < block->mIns.Size(); i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_JSR)
|
|
simple = false;
|
|
}
|
|
}
|
|
|
|
int sz = tail->mIns.Size();
|
|
if (simple && sz >= 3)
|
|
{
|
|
if (tail->mIns[sz - 3].mType == ASMIT_INC && tail->mIns[sz - 3].mMode == ASMIM_ZERO_PAGE &&
|
|
tail->mIns[sz - 2].mType == ASMIT_LDA && tail->mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && tail->mIns[sz - 3].mAddress == tail->mIns[sz - 2].mAddress &&
|
|
tail->mIns[sz - 1].mType == ASMIT_CMP && tail->mIns[sz - 1].mMode == ASMIM_IMMEDIATE && !(tail->mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y)) &&
|
|
tail->mBranch == ASMIT_BCC && tail->mTrueJump == head)
|
|
{
|
|
// check for usage of Y register
|
|
|
|
bool yother = false, yindex = false, xother = false, xindex = false;
|
|
int zreg = tail->mIns[sz - 3].mAddress;
|
|
int limit = tail->mIns[sz - 1].mAddress;
|
|
|
|
for (int j = 0; j < lblocks.Size(); j++)
|
|
{
|
|
NativeCodeBasicBlock* block = lblocks[j];
|
|
|
|
int bz = block == tail ? block->mIns.Size() - 3 : block->mIns.Size();
|
|
|
|
for (int i = 0; i < bz; i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_INY || block->mIns[i].mType == ASMIT_DEY || block->mIns[i].mType == ASMIT_TAY)
|
|
yother = true;
|
|
else if (block->mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
if (block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
yindex = true;
|
|
else
|
|
yother = true;
|
|
}
|
|
else if (!yindex && (block->mIns[i].mType == ASMIT_STY || block->mIns[i].mType == ASMIT_TYA || block->mIns[i].mMode == ASMIM_ABSOLUTE_Y || block->mIns[i].mMode == ASMIM_INDIRECT_Y))
|
|
yother = true;
|
|
else if (block->mIns[i].mType != ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
yother = true;
|
|
|
|
if (block->mIns[i].mType == ASMIT_INX || block->mIns[i].mType == ASMIT_DEX || block->mIns[i].mType == ASMIT_TAX)
|
|
xother = true;
|
|
else if (block->mIns[i].mType == ASMIT_LDX)
|
|
{
|
|
if (block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
xindex = true;
|
|
else
|
|
xother = true;
|
|
}
|
|
else if (!xindex && (block->mIns[i].mType == ASMIT_STX || block->mIns[i].mType == ASMIT_TXA || block->mIns[i].mMode == ASMIM_ABSOLUTE_X || block->mIns[i].mMode == ASMIM_INDIRECT_X))
|
|
xother = true;
|
|
else if (block->mIns[i].mType != ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
xother = true;
|
|
}
|
|
}
|
|
#if 1
|
|
if (!yother)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
|
|
tail->mIns.Remove(sz - 3);
|
|
tail->mIns.Remove(sz - 3);
|
|
tail->mIns.Remove(sz - 3);
|
|
|
|
for (int j = 0; j < lblocks.Size(); j++)
|
|
{
|
|
NativeCodeBasicBlock* block = lblocks[j];
|
|
|
|
int bz = block->mIns.Size();
|
|
|
|
if (block == head)
|
|
{
|
|
for (int i = 0; i < bz; i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
|
else if (block->mIns[i].mType != ASMIT_LDY)
|
|
lblock->mIns.Push(block->mIns[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < bz; i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
{
|
|
block->mIns[i].mType = ASMIT_TYA;
|
|
block->mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else if (block->mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
block->mIns[i].mType = ASMIT_NOP;
|
|
block->mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tail->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
tail->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_IMMEDIATE, limit));
|
|
|
|
lblock->mBranch = head->mBranch;
|
|
lblock->mTrueJump = head->mTrueJump;
|
|
lblock->mFalseJump = head->mFalseJump;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = tail->mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
tail->mTrueJump = lblock;
|
|
tail->mFalseJump = eblock;
|
|
|
|
head->mIns.SetSize(0);
|
|
head->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
|
head->mBranch = ASMIT_JMP;
|
|
head->mTrueJump = lblock;
|
|
head->mFalseJump = nullptr;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
#endif
|
|
if (!xother)
|
|
{
|
|
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
|
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
|
|
|
tail->mIns.Remove(sz - 3);
|
|
tail->mIns.Remove(sz - 3);
|
|
tail->mIns.Remove(sz - 3);
|
|
|
|
for (int j = 0; j < lblocks.Size(); j++)
|
|
{
|
|
NativeCodeBasicBlock* block = lblocks[j];
|
|
|
|
int bz = block->mIns.Size();
|
|
|
|
if (block == head)
|
|
{
|
|
for (int i = 0; i < bz; i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
|
else if (block->mIns[i].mType != ASMIT_LDX)
|
|
lblock->mIns.Push(block->mIns[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < bz; i++)
|
|
{
|
|
if (block->mIns[i].mType == ASMIT_LDA && block->mIns[i].mMode == ASMIM_ZERO_PAGE && block->mIns[i].mAddress == zreg)
|
|
{
|
|
block->mIns[i].mType = ASMIT_TXA;
|
|
block->mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else if (block->mIns[i].mType == ASMIT_LDX)
|
|
{
|
|
block->mIns[i].mType = ASMIT_NOP;
|
|
block->mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tail->mIns.Push(NativeCodeInstruction(ASMIT_INX, ASMIM_IMPLIED));
|
|
tail->mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, limit));
|
|
|
|
lblock->mBranch = head->mBranch;
|
|
lblock->mTrueJump = head->mTrueJump;
|
|
lblock->mFalseJump = head->mFalseJump;
|
|
|
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, zreg));
|
|
eblock->mBranch = ASMIT_JMP;
|
|
eblock->mTrueJump = tail->mFalseJump;
|
|
eblock->mFalseJump = nullptr;
|
|
|
|
tail->mTrueJump = lblock;
|
|
tail->mFalseJump = eblock;
|
|
|
|
head->mIns.SetSize(0);
|
|
head->mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, zreg));
|
|
head->mBranch = ASMIT_JMP;
|
|
head->mTrueJump = lblock;
|
|
head->mFalseJump = nullptr;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::CheckInnerLoop(NativeCodeBasicBlock* head, GrowingArray<NativeCodeBasicBlock*>& blocks)
|
|
{
|
|
if (mVisited)
|
|
return this == head;
|
|
else if (mLoopHead)
|
|
return false;
|
|
else if (mLoopHeadBlock != head)
|
|
{
|
|
mVisiting = true;
|
|
|
|
if (mTrueJump && mTrueJump->CheckInnerLoop(head, blocks))
|
|
mLoopHeadBlock = head;
|
|
if (mFalseJump && mFalseJump->CheckInnerLoop(head, blocks))
|
|
mLoopHeadBlock = head;
|
|
|
|
mVisiting = false;
|
|
|
|
if (head == mLoopHeadBlock)
|
|
{
|
|
blocks.Push(this);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else
|
|
return true;
|
|
}
|
|
|
|
bool NativeCodeBasicBlock::OptimizeInnerLoops(NativeCodeProcedure* proc)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
GrowingArray<NativeCodeBasicBlock*> lblocks(nullptr);
|
|
|
|
if (mLoopHead)
|
|
{
|
|
lblocks.Push(this);
|
|
|
|
bool check = false;
|
|
|
|
if (mTrueJump && mTrueJump->CheckInnerLoop(this, lblocks))
|
|
check = true;
|
|
if (mFalseJump && mFalseJump->CheckInnerLoop(this, lblocks))
|
|
check = true;
|
|
|
|
if (check)
|
|
{
|
|
// Find tail block
|
|
|
|
int i = 0;
|
|
while (i < lblocks.Size() && !(lblocks[i]->mTrueJump == this || lblocks[i]->mFalseJump == this))
|
|
i++;
|
|
|
|
NativeCodeBasicBlock* tail = lblocks[i];
|
|
|
|
i++;
|
|
while (i < lblocks.Size() && !(lblocks[i]->mTrueJump == this || lblocks[i]->mFalseJump == this))
|
|
i++;
|
|
|
|
if (i < lblocks.Size())
|
|
{
|
|
// Multi tail block
|
|
|
|
}
|
|
else
|
|
{
|
|
changed = OptimizeInnerLoop(proc, this, tail, lblocks);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mTrueJump && mTrueJump->OptimizeInnerLoops(proc))
|
|
changed = true;
|
|
if (mFalseJump && mFalseJump->OptimizeInnerLoops(proc))
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
// Size reduction violating various assumptions such as no branches in basic blocks
|
|
// must be last step before actual assembly
|
|
|
|
void NativeCodeBasicBlock::BlockSizeReduction(void)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
mVisited = true;
|
|
|
|
int i = 0;
|
|
int j = 0;
|
|
while (i < mIns.Size())
|
|
{
|
|
if (i + 2 < mIns.Size() &&
|
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
|
|
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress &&
|
|
!(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
|
{
|
|
mIns[j + 0].mType = ASMIT_BCC; mIns[j + 0].mMode = ASMIM_RELATIVE; mIns[j + 0].mAddress = 2;
|
|
mIns[j + 1].mType = ASMIT_INC; mIns[j + 1].mMode = ASMIM_ZERO_PAGE; mIns[j + 1].mAddress = mIns[i + 2].mAddress;
|
|
j += 2;
|
|
i += 3;
|
|
}
|
|
else
|
|
mIns[j++] = mIns[i++];
|
|
}
|
|
mIns.SetSize(j);
|
|
#if 1
|
|
bool yimm = false, ximm = false;
|
|
int yval = 0, xval = 0;
|
|
for(int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDY)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (yimm && mIns[i].mAddress == ((yval + 1) & 0xff))
|
|
{
|
|
yval = mIns[i].mAddress;
|
|
mIns[i].mType = ASMIT_INY;
|
|
mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else if (yimm && mIns[i].mAddress == ((yval - 1) & 0xff))
|
|
{
|
|
yval = mIns[i].mAddress;
|
|
mIns[i].mType = ASMIT_DEY;
|
|
mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else
|
|
{
|
|
yimm = true;
|
|
yval = mIns[i].mAddress;
|
|
}
|
|
|
|
}
|
|
else
|
|
yimm = false;
|
|
}
|
|
else if (yimm && mIns[i].mType == ASMIT_INY)
|
|
{
|
|
yval = (yval + 1) & 0xff;
|
|
}
|
|
else if (yimm && mIns[i].mType == ASMIT_DEY)
|
|
{
|
|
yval = (yval - 1) & 0xff;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_TAY)
|
|
yimm = false;
|
|
else if (mIns[i].mType == ASMIT_LDX)
|
|
{
|
|
if (mIns[i].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (ximm && mIns[i].mAddress == ((xval + 1) & 0xff))
|
|
{
|
|
xval = mIns[i].mAddress;
|
|
mIns[i].mType = ASMIT_INX;
|
|
mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else if (ximm && mIns[i].mAddress == ((xval - 1) & 0xff))
|
|
{
|
|
xval = mIns[i].mAddress;
|
|
mIns[i].mType = ASMIT_DEX;
|
|
mIns[i].mMode = ASMIM_IMPLIED;
|
|
}
|
|
else
|
|
{
|
|
ximm = true;
|
|
xval = mIns[i].mAddress;
|
|
}
|
|
|
|
}
|
|
else
|
|
ximm = false;
|
|
}
|
|
else if (ximm && mIns[i].mType == ASMIT_INX)
|
|
{
|
|
xval = (xval + 1) & 0xff;
|
|
}
|
|
else if (ximm && mIns[i].mType == ASMIT_DEX)
|
|
{
|
|
xval = (xval - 1) & 0xff;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_TAX)
|
|
ximm = false;
|
|
else if (mIns[i].mType == ASMIT_JSR)
|
|
yimm = ximm = false;
|
|
}
|
|
#endif
|
|
if (mTrueJump)
|
|
mTrueJump->BlockSizeReduction();
|
|
if (mFalseJump)
|
|
mFalseJump->BlockSizeReduction();
|
|
}
|
|
}
|
|
|
|
|
|
bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
|
{
|
|
if (!mVisited)
|
|
{
|
|
bool changed = false;
|
|
|
|
mVisited = true;
|
|
|
|
#if 1
|
|
// move load store pairs up to initial store
|
|
|
|
for (int i = 2; i + 1 < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && (mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
|
|
{
|
|
if (MoveLoadStoreUp(i))
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
// move load - store (),y up to initial store
|
|
//
|
|
|
|
for (int i = 2; i + 2 < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y)
|
|
{
|
|
if (MoveIndirectLoadStoreUp(i))
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
// move load - store abs up to initial store
|
|
//
|
|
|
|
for (int i = 2; i + 1 < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE)
|
|
{
|
|
if (MoveAbsoluteLoadStoreUp(i))
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
// move load - add #- store up to initial store
|
|
//
|
|
|
|
for (int i = 2; i + 3 < mIns.Size(); i++)
|
|
{
|
|
if (
|
|
mIns[i + 0].mType == ASMIT_CLC &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && (mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
|
|
{
|
|
if (MoveLoadAddImmStoreUp(i))
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// shorten x/y register livetime
|
|
|
|
#if 1
|
|
//
|
|
// move ldy down
|
|
|
|
for (int i = 0; i + 1 < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
if (!mIns[i + 1].RequiresYReg() && !mIns[i + 1].ChangesYReg() && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
NativeCodeInstruction ins = mIns[i];
|
|
mIns[i] = mIns[i + 1];
|
|
mIns[i + 1] = ins;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
// move stx up
|
|
|
|
for (int i = 1; i + 1 < mIns.Size(); i++)
|
|
{
|
|
if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ZERO_PAGE)
|
|
{
|
|
if (MoveStoreXUp(i))
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool progress = false;
|
|
do {
|
|
progress = false;
|
|
|
|
int i = 0;
|
|
int j = 0;
|
|
while (i < mIns.Size())
|
|
{
|
|
if (mIns[i].mType == ASMIT_NOP)
|
|
;
|
|
else
|
|
{
|
|
if (i != j)
|
|
mIns[j] = mIns[i];
|
|
j++;
|
|
}
|
|
i++;
|
|
}
|
|
if (j != i)
|
|
changed = true;
|
|
mIns.SetSize(j);
|
|
|
|
// Replace (a & 0x80) != 0 with bpl/bmi
|
|
int sz = mIns.Size();
|
|
if (sz > 1 &&
|
|
mIns[sz - 2].ChangesAccuAndFlag() &&
|
|
mIns[sz - 1].mType == ASMIT_AND && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0x80 && !(mIns[i].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
if (mBranch == ASMIT_BEQ)
|
|
{
|
|
mBranch = ASMIT_BPL;
|
|
mIns[sz - 2].mLive |= LIVE_CPU_REG_Z;
|
|
mIns[sz - 1].mType = ASMIT_NOP;
|
|
changed = true;
|
|
}
|
|
else if (mBranch == ASMIT_BNE)
|
|
{
|
|
mBranch = ASMIT_BMI;
|
|
mIns[sz - 2].mLive |= LIVE_CPU_REG_Z;
|
|
mIns[sz - 1].mType = ASMIT_NOP;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
{
|
|
#if 1
|
|
#if 1
|
|
if (mIns[i].mType == ASMIT_AND && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0)
|
|
{
|
|
mIns[i].mType = ASMIT_LDA;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_AND && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0xff && (mIns[i].mLive & LIVE_CPU_REG_Z) == 0)
|
|
{
|
|
mIns[i].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_ORA && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0xff)
|
|
{
|
|
mIns[i].mType = ASMIT_LDA;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_ORA && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0x00 && (mIns[i].mLive & LIVE_CPU_REG_Z) == 0)
|
|
{
|
|
mIns[i].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (mIns[i].mType == ASMIT_ROR && mIns[i].mMode == ASMIM_IMPLIED && (mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
|
|
{
|
|
mIns[i].mType = ASMIT_LSR;
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (mIns[i].mType == ASMIT_ROL && mIns[i].mMode == ASMIM_IMPLIED && (mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
|
|
{
|
|
mIns[i].mType = ASMIT_ASL;
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
int apos;
|
|
if (mIns[i].mMode == ASMIM_INDIRECT_Y && FindGlobalAddress(i, mIns[i].mAddress, apos))
|
|
{
|
|
mIns[i].mMode = ASMIM_ABSOLUTE_Y;
|
|
mIns[i].mAddress = mIns[apos].mAddress;
|
|
mIns[i].mLinkerObject = mIns[apos].mLinkerObject;
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
if (mIns[i + 0].mMode == ASMIM_INDIRECT_Y && (mIns[i + 0].mFlags & NCIF_YZERO))
|
|
{
|
|
const NativeCodeInstruction* ains, * iins;
|
|
|
|
int sreg = mIns[i + 0].mAddress;
|
|
|
|
int apos, breg, ireg;
|
|
uint32 flags;
|
|
|
|
if (FindAddressSumY(i, sreg, apos, breg, ireg))
|
|
{
|
|
if (!(breg == sreg || ireg == sreg)|| !(mIns[i + 0].mLive & LIVE_MEM))
|
|
{
|
|
if (breg == sreg || ireg == sreg)
|
|
{
|
|
mIns[apos + 3].mType = ASMIT_NOP;
|
|
mIns[apos + 3].mMode = ASMIM_IMPLIED;
|
|
mIns[apos + 6].mType = ASMIT_NOP;
|
|
mIns[apos + 6].mMode = ASMIM_IMPLIED;
|
|
}
|
|
if (mIns[i + 0].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg));
|
|
mIns[i + 1].mAddress = breg;
|
|
mIns[i + 1].mFlags &= ~NCIF_YZERO;
|
|
progress = true;
|
|
}
|
|
}
|
|
else if (FindGlobalAddressSumY(i, sreg, true, apos, ains, iins, flags) && iins)
|
|
{
|
|
if (mIns[i + 0].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
|
|
mIns[i + 0].mMode = ASMIM_ABSOLUTE_Y;
|
|
mIns[i + 0].mLinkerObject = ains->mLinkerObject;
|
|
mIns[i + 0].mAddress = ains->mAddress;
|
|
mIns[i + 0].mFlags &= ~NCIF_YZERO;
|
|
|
|
if (iins->mMode != ASMIM_ZERO_PAGE)
|
|
mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, iins->mMode, iins->mAddress, iins->mLinkerObject, iins->mFlags));
|
|
else if (iins->mAddress == sreg)
|
|
mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress));
|
|
else
|
|
mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress));
|
|
|
|
progress = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
if (i + 1 < mIns.Size())
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_LDA)
|
|
{
|
|
mIns[i].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_STA && mIns[i + 1].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress && (mIns[i + 1].mLive & LIVE_CPU_REG_Z) == 0)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_AND && mIns[i + 1].mType == ASMIT_AND && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
mIns[i].mAddress &= mIns[i + 1].mAddress;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_ORA && mIns[i + 1].mType == ASMIT_ORA && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
mIns[i].mAddress |= mIns[i + 1].mAddress;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_EOR && mIns[i + 1].mType == ASMIT_EOR && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
mIns[i].mAddress ^= mIns[i + 1].mAddress;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_ORA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_EOR && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_AND && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_ROR)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 1].mType = ASMIT_LSR;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0 && mIns[i + 1].mType == ASMIT_LSR && mIns[i + 1].mMode == ASMIM_IMPLIED)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_CLC;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i].mType == ASMIT_SEC && mIns[i + 1].mType == ASMIT_SBC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].SameEffectiveAddress(mIns[i + 0]))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_ROL;
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 1].mType == ASMIT_ORA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && mIns[i].ChangesAccuAndFlag())
|
|
{
|
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 1].mType == ASMIT_CMP && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && mIns[i].ChangesAccuAndFlag() && !(mIns[i + 1].mLive & LIVE_CPU_REG_C))
|
|
{
|
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress &&
|
|
(mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR))
|
|
{
|
|
mIns[i + 0].mType = mIns[i + 1].mType;
|
|
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 1].mType = ASMIT_STA;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress && !(mIns[i + 0].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_STA;
|
|
mIns[i + 0].mType = ASMIT_ASL;
|
|
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TXA &&
|
|
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_STX;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TYA &&
|
|
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_STY;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TAX &&
|
|
mIns[i + 1].mType == ASMIT_STX && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_STA;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TAY &&
|
|
mIns[i + 1].mType == ASMIT_STY && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
|
|
{
|
|
mIns[i + 1].mType = ASMIT_STA;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TXA &&
|
|
mIns[i + 1].mType == ASMIT_TAX)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TYA &&
|
|
mIns[i + 1].mType == ASMIT_TAY)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TAX &&
|
|
mIns[i + 1].mType == ASMIT_TXA)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TAY &&
|
|
mIns[i + 1].mType == ASMIT_TYA)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
|
|
mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
|
|
mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
|
|
else if (
|
|
(mIns[i + 0].mType == ASMIT_ASL || mIns[i + 0].mType == ASMIT_LSR || mIns[i + 0].mType == ASMIT_ROL || mIns[i + 0].mType == ASMIT_ROR) && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 0].mAddress && !(mIns[i + 1].mLive & LIVE_MEM))
|
|
{
|
|
mIns[i + 1].mType = mIns[i + 0].mType;
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 0].mType = ASMIT_LDA;
|
|
progress = true;
|
|
}
|
|
#if 1
|
|
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
|
|
{
|
|
const NativeCodeInstruction* ains, *iins;
|
|
|
|
int sreg = mIns[i + 1].mAddress;
|
|
int apos;
|
|
uint32 flags;
|
|
|
|
if (FindGlobalAddressSumY(i, sreg, true, apos, ains, iins, flags))
|
|
{
|
|
if (iins || (flags & LIVE_CPU_REG_Y) || !(mIns[i + 1].mLive & LIVE_CPU_REG_X))
|
|
{
|
|
if (mIns[i + 1].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 2, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, mIns[i + 0].mAddress));
|
|
mIns[i + 2].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
|
|
if (iins || (flags & LIVE_CPU_REG_Y))
|
|
mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y;
|
|
else
|
|
mIns[i + 1].mMode = ASMIM_ABSOLUTE_X;
|
|
mIns[i + 1].mLinkerObject = ains->mLinkerObject;
|
|
mIns[i + 1].mAddress = ains->mAddress + mIns[i + 0].mAddress;
|
|
|
|
if (!iins)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
if (flags & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(apos, NativeCodeInstruction(ASMIT_TAY, ASMIM_IMPLIED));
|
|
mIns[apos].mLive = LIVE_CPU_REG_Y | LIVE_CPU_REG_A;
|
|
}
|
|
else
|
|
{
|
|
mIns.Insert(apos, NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
|
mIns[apos].mLive = LIVE_CPU_REG_X | LIVE_CPU_REG_A;
|
|
}
|
|
}
|
|
else if (iins->mMode != ASMIM_ZERO_PAGE)
|
|
{
|
|
mIns[i + 0].mMode = iins->mMode;
|
|
mIns[i + 0].mAddress = iins->mAddress;
|
|
mIns[i + 0].mLinkerObject = iins->mLinkerObject;
|
|
mIns[i + 0].mFlags = iins->mFlags;
|
|
}
|
|
else if (iins->mAddress == sreg)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns.Insert(apos, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, iins->mAddress));
|
|
mIns[apos].mLive = LIVE_CPU_REG_Y;
|
|
}
|
|
else
|
|
{
|
|
mIns[i + 0].mMode = ASMIM_ZERO_PAGE;
|
|
mIns[i + 0].mAddress = iins->mAddress;
|
|
}
|
|
|
|
progress = true;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
#if 1
|
|
if (i + 2 < mIns.Size())
|
|
{
|
|
if (mIns[i].mType == ASMIT_LDA && mIns[i + 2].mType == ASMIT_LDA && (mIns[i + 1].mType == ASMIT_CLC || mIns[i + 1].mType == ASMIT_SEC))
|
|
{
|
|
mIns[i].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 2].mAddress &&
|
|
mIns[i + 1].mType == ASMIT_INC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress && (mIns[i + 2].mLive & LIVE_CPU_REG_C) == 0)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_CLC;
|
|
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mType = ASMIT_ADC;
|
|
mIns[i + 1].mMode = ASMIM_IMMEDIATE;
|
|
mIns[i + 1].mAddress = 1;
|
|
mIns[i + 2].mType = ASMIT_STA;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode != ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 2].mAddress &&
|
|
mIns[i + 2].IsCommutative() && HasAsmInstructionMode(mIns[i + 2].mType, mIns[i + 1].mMode) &&
|
|
(mIns[i + 2].mLive & LIVE_MEM) == 0)
|
|
{
|
|
mIns[i + 1].mType = mIns[i + 2].mType;
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].ChangesAccuAndFlag() &&
|
|
mIns[i + 1].mType == ASMIT_STA && mIns[i + 2].mType == ASMIT_LDA &&
|
|
mIns[i + 1].SameEffectiveAddress(mIns[i + 2]))
|
|
{
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_LDY && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress &&
|
|
!mIns[i + 1].SameEffectiveAddress(mIns[i + 0]) && !mIns[i + 1].ChangesAccu())
|
|
{
|
|
mIns[i + 2].mType = ASMIT_TAY;
|
|
mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_TAY && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) &&
|
|
!mIns[i + 1].ChangesAccu() && !mIns[i + 1].RequiresAccu() && !(mIns[i + 1].mLive & LIVE_CPU_REG_Y))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_LDY;
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress &&
|
|
mIns[i + 1].mType == ASMIT_DEC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 0].mAddress &&
|
|
!(mIns[i + 2].mLive & LIVE_CPU_REG_C))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_SEC; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mType = ASMIT_SBC; mIns[i + 1].mMode = ASMIM_IMMEDIATE; mIns[i + 1].mAddress = 1;
|
|
mIns[i + 2].mType = ASMIT_STA;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
|
mIns[i + 1].mType == ASMIT_CMP && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 2].mType == ASMIT_ROR && mIns[i + 2].mMode == ASMIM_IMPLIED)
|
|
{
|
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 2].mType = ASMIT_CLC; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].ChangesAccuAndFlag() &&
|
|
mIns[i + 1].mType == ASMIT_STA &&
|
|
mIns[i + 2].mType == ASMIT_ORA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0)
|
|
{
|
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].ChangesAccuAndFlag() &&
|
|
mIns[i + 1].mType == ASMIT_STA &&
|
|
mIns[i + 2].mType == ASMIT_CMP && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0 && !(mIns[i + 2].mLive & LIVE_CPU_REG_C))
|
|
{
|
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 0].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
|
mIns[i + 1].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
(mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR) &&
|
|
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
mIns[i + 2].mType = mIns[i + 1].mType;
|
|
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
!mIns[i + 1].UsesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].UsesAccu() &&
|
|
mIns[i + 2].IsShift() && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
mIns[i + 0] = mIns[i + 1];
|
|
mIns[i + 1] = mIns[i + 2];
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 2].mType = ASMIT_STA;
|
|
mIns[i + 2].mLive |= mIns[i + 1].mLive & LIVE_CPU_REG_C;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 2].IsShift() && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress)
|
|
{
|
|
mIns[i + 0] = mIns[i + 2];
|
|
mIns[i + 2] = mIns[i + 1];
|
|
mIns[i + 1] = mIns[i + 0];
|
|
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 1].mType = ASMIT_STA;
|
|
mIns[i + 2].mLive |= mIns[i + 1].mLive & LIVE_CPU_REG_C;
|
|
progress = true;
|
|
}
|
|
#if 1
|
|
else if (
|
|
mIns[i + 0].mMode != ASMIM_RELATIVE &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & LIVE_CPU_REG_A) &&
|
|
mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 1].mAddress &&
|
|
(mIns[i + 1].mType == ASMIT_DEC || mIns[i + 1].mType == ASMIT_INC))
|
|
{
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_Z;
|
|
progress = true;
|
|
}
|
|
#endif
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_TAX &&
|
|
!mIns[i + 1].ChangesXReg() &&
|
|
mIns[i + 2].mType == ASMIT_TXA && !(mIns[i + 2].mLive & LIVE_CPU_REG_Z))
|
|
{
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_SEC &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
int t = (mIns[i + 2].mAddress ^ 0xff) + mIns[i + 1].mAddress + 1;
|
|
|
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 2].mType = ASMIT_LDA; mIns[i + 2].mAddress = t & 0xff;
|
|
if (t < 256)
|
|
mIns[i + 0].mType = ASMIT_CLC;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_CLC &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE)
|
|
{
|
|
int t = mIns[i + 2].mAddress + mIns[i + 1].mAddress;
|
|
|
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 2].mType = ASMIT_LDA; mIns[i + 2].mAddress = t & 0xff;
|
|
if (t >= 256)
|
|
mIns[i + 0].mType = ASMIT_SEC;
|
|
progress = true;
|
|
}
|
|
|
|
#if 1
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_ASL && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 0].mAddress &&
|
|
mIns[i + 2].mType == ASMIT_ASL && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress &&
|
|
!(mIns[i + 2].mLive & LIVE_CPU_REG_A))
|
|
{
|
|
int addr = mIns[i + 0].mAddress;
|
|
|
|
mIns.Insert(i, NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, addr));
|
|
mIns.Insert(i + 4, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, addr));
|
|
|
|
mIns[i + 0].mLive = mIns[i + 1].mLive | LIVE_CPU_REG_A;
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 2].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 3].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 3].mLive |= LIVE_CPU_REG_A;
|
|
mIns[i + 4].mLive = mIns[i + 3].mLive;
|
|
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
if (
|
|
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
|
mIns[i + 1].mType == ASMIT_LDA &&
|
|
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mLive & LIVE_MEM))
|
|
{
|
|
int apos, breg, ireg;
|
|
if (FindAddressSumY(i, mIns[i + 2].mAddress, apos, breg, ireg))
|
|
{
|
|
if (breg == mIns[i + 2].mAddress)
|
|
{
|
|
mIns[apos + 3].mType = ASMIT_NOP;
|
|
mIns[apos + 3].mMode = ASMIM_IMPLIED;
|
|
mIns[apos + 6].mType = ASMIT_NOP;
|
|
mIns[apos + 6].mMode = ASMIM_IMPLIED;
|
|
}
|
|
if (mIns[i + 2].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 3, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
|
mIns[i + 3].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
if (mIns[i + 1].mMode != ASMIM_INDIRECT_Y && mIns[i + 1].mMode != ASMIM_ABSOLUTE_Y)
|
|
{
|
|
mIns[i + 0].mMode = ASMIM_ZERO_PAGE;
|
|
mIns[i + 0].mAddress = ireg;
|
|
mIns[i + 2].mAddress = breg;
|
|
}
|
|
else
|
|
{
|
|
mIns.Insert(i + 2, NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, ireg));
|
|
mIns[i + 3].mAddress = breg;
|
|
}
|
|
progress = true;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
if (i + 3 < mIns.Size())
|
|
{
|
|
if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) &&
|
|
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 + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) &&
|
|
(mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
mIns[i + 3].mType = ASMIT_INC;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) &&
|
|
mIns[i + 1].mType == ASMIT_SEC && mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 &&
|
|
(mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) &&
|
|
(mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
mIns[i + 3].mType = ASMIT_DEC;
|
|
progress = true;
|
|
}
|
|
else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) &&
|
|
mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && (mIns[i + 2].mAddress & 0xff) == 0xff &&
|
|
(mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) &&
|
|
(mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0)
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
mIns[i + 3].mType = ASMIT_DEC;
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA &&
|
|
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 1].mAddress &&
|
|
mIns[i + 3].mType == ASMIT_CMP && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress && !(mIns[i + 3].mLive & LIVE_MEM))
|
|
{
|
|
mIns[i + 3].mMode = mIns[i + 0].mMode;
|
|
mIns[i + 3].mAddress = mIns[i + 0].mAddress;
|
|
mIns[i + 3].mLinkerObject = mIns[i + 0].mLinkerObject;
|
|
|
|
progress = true;
|
|
}
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_LDX && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress == mIns[i + 0].mAddress &&
|
|
mIns[i + 3].mType == ASMIT_STX && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
|
|
!mIns[i + 1].ChangesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].UsesZeroPage(mIns[i + 3].mAddress))
|
|
{
|
|
mIns.Insert(i + 1, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, mIns[i + 3].mAddress));
|
|
|
|
mIns[i + 4].mType = ASMIT_NOP;
|
|
mIns[i + 4].mMode = ASMIM_IMPLIED;
|
|
|
|
progress = true;
|
|
}
|
|
#if 1
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y &&
|
|
mIns[i + 3].mType == ASMIT_EOR && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 0].mAddress)
|
|
{
|
|
mIns[i + 2].mType = mIns[i + 3].mType;
|
|
mIns[i + 3].mType = ASMIT_NOP;
|
|
mIns[i + 3].mMode = ASMIM_IMPLIED;
|
|
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 1].mAddress &&
|
|
mIns[i + 2].mType == ASMIT_SEC &&
|
|
mIns[i + 3].mType == ASMIT_SBC && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 3].mAddress && !(mIns[i + 3].mLive & LIVE_MEM))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_EOR;
|
|
mIns[i + 0].mMode = ASMIM_IMMEDIATE;
|
|
mIns[i + 0].mAddress = 0xff;
|
|
|
|
mIns[i + 3].mType = ASMIT_ADC;
|
|
mIns[i + 3].mAddress = mIns[i + 1].mAddress;
|
|
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
|
|
|
progress = true;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 1].mType == ASMIT_SEC &&
|
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 2].mAddress &&
|
|
mIns[i + 3].mType == ASMIT_SBC && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 3].mAddress && !(mIns[i + 3].mLive & LIVE_MEM))
|
|
{
|
|
mIns[i + 0].mType = ASMIT_EOR;
|
|
mIns[i + 0].mMode = ASMIM_IMMEDIATE;
|
|
mIns[i + 0].mAddress = 0xff;
|
|
|
|
mIns[i + 3].mType = ASMIT_ADC;
|
|
mIns[i + 3].mAddress = mIns[i + 2].mAddress;
|
|
|
|
mIns[i + 2].mType = ASMIT_NOP;
|
|
mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
|
|
progress = true;
|
|
}
|
|
#endif
|
|
else if (
|
|
mIns[i + 0].mType == ASMIT_LDA &&
|
|
mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) &&
|
|
(mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) &&
|
|
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED &&
|
|
mIns[i + 2].mType == ASMIT_ORA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && !(mIns[i + 3].mLive & LIVE_CPU_REG_A))
|
|
|
|
{
|
|
mIns[i + 0].mType = ASMIT_NOP;
|
|
mIns[i + 1].mType = ASMIT_NOP;
|
|
mIns[i + 2].mType = ASMIT_SEC;
|
|
mIns[i + 2].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 2].mLive |= LIVE_CPU_REG_C;
|
|
mIns[i + 3].mType = ASMIT_ROL;
|
|
progress = true;
|
|
}
|
|
#if 0
|
|
if (
|
|
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y &&
|
|
!mIns[i + 2].ChangesYReg() && (mIns[i + 2].mMode == ASMIM_IMMEDIATE || mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 1].mAddress) &&
|
|
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mAddress == mIns[i + 3].mAddress && !(mIns[i + 3].mLive & LIVE_MEM))
|
|
{
|
|
int apos, breg, ireg;
|
|
if (FindAddressSumY(i, mIns[i + 1].mAddress, apos, breg, ireg))
|
|
{
|
|
if (breg == mIns[i + 1].mAddress)
|
|
{
|
|
mIns[apos + 3].mType = ASMIT_NOP;
|
|
mIns[apos + 3].mMode = ASMIM_IMPLIED;
|
|
mIns[apos + 6].mType = ASMIT_NOP;
|
|
mIns[apos + 6].mMode = ASMIM_IMPLIED;
|
|
}
|
|
if (mIns[i + 3].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 4, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
|
mIns[i + 4].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
mIns[i + 0].mMode = ASMIM_ZERO_PAGE;
|
|
mIns[i + 0].mAddress = ireg;
|
|
mIns[i + 1].mAddress = breg;
|
|
mIns[i + 3].mAddress = breg;
|
|
progress = true;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
if (i + 4 < mIns.Size())
|
|
{
|
|
if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 3].mAddress &&
|
|
mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_LDA)
|
|
{
|
|
// Flip arguments of ADC if second parameter in accu at entry
|
|
|
|
mIns[i + 3] = mIns[i + 2];
|
|
mIns[i + 3].mType = ASMIT_ADC;
|
|
mIns[i + 2].mMode = ASMIM_ZERO_PAGE;
|
|
mIns[i + 2].mAddress = mIns[i + 0].mAddress;
|
|
progress = true;
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
if (i + 9 < mIns.Size())
|
|
{
|
|
if (
|
|
mIns[i + 0].mType == ASMIT_CLC &&
|
|
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
|
|
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
|
|
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
|
|
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
|
|
|
|
mIns[i + 6].mType == ASMIT_LDY && mIns[i + 6].mMode == ASMIM_IMMEDIATE && mIns[i + 6].mAddress == 0 &&
|
|
mIns[i + 7].mType == ASMIT_LDA && mIns[i + 7].mMode == ASMIM_INDIRECT_Y && mIns[i + 7].mAddress == mIns[i + 2].mAddress &&
|
|
!mIns[i + 8].ChangesYReg() && (mIns[i + 8].mMode == ASMIM_IMMEDIATE || mIns[i + 8].mMode == ASMIM_ZERO_PAGE && mIns[i + 8].mAddress != mIns[i + 2].mAddress && mIns[i + 8].mAddress != mIns[i + 1].mAddress) &&
|
|
mIns[i + 9].mType == ASMIT_STA && mIns[i + 9].mMode == ASMIM_INDIRECT_Y && mIns[i + 9].mAddress == mIns[i + 2].mAddress && !(mIns[i + 9].mLive & LIVE_MEM)
|
|
)
|
|
{
|
|
for(int j=0; j<6; j++)
|
|
{
|
|
mIns[i + j].mType = ASMIT_NOP;
|
|
mIns[i + j].mMode = ASMIM_IMPLIED;
|
|
}
|
|
|
|
if (mIns[i + 9].mLive & LIVE_CPU_REG_Y)
|
|
{
|
|
mIns.Insert(i + 10, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
|
mIns[i + 10].mLive |= LIVE_CPU_REG_Y;
|
|
}
|
|
|
|
mIns[i + 6].mType = ASMIT_TAY;
|
|
mIns[i + 6].mMode = ASMIM_IMPLIED;
|
|
mIns[i + 7].mAddress = mIns[i + 1].mAddress;
|
|
mIns[i + 9].mAddress = mIns[i + 1].mAddress;
|
|
progress = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
if (progress)
|
|
changed = true;
|
|
|
|
} while (progress);
|
|
|
|
if (this->mTrueJump && this->mTrueJump->PeepHoleOptimizer())
|
|
changed = true;
|
|
if (this->mFalseJump && this->mFalseJump->PeepHoleOptimizer())
|
|
changed = true;
|
|
|
|
return changed;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void NativeCodeBasicBlock::Assemble(void)
|
|
{
|
|
if (!mAssembled)
|
|
{
|
|
mAssembled = true;
|
|
|
|
for (int i = 0; i < mIns.Size(); i++)
|
|
mIns[i].Assemble(this);
|
|
|
|
if (this->mTrueJump)
|
|
this->mTrueJump->Assemble();
|
|
if (this->mFalseJump)
|
|
this->mFalseJump->Assemble();
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch)
|
|
{
|
|
this->mTrueJump = trueJump;
|
|
this->mFalseJump = falseJump;
|
|
this->mBranch = branch;
|
|
}
|
|
|
|
|
|
static int BranchByteSize(int from, int to)
|
|
{
|
|
if (to - from >= -126 && to - from <= 129)
|
|
return 2;
|
|
else
|
|
return 5;
|
|
}
|
|
|
|
static int JumpByteSize(int from, int to)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
|
{
|
|
if (mBypassed)
|
|
return this;
|
|
else if (!mFalseJump && mCode.Size() == 0 && this != mTrueJump)
|
|
return mTrueJump->BypassEmptyBlocks();
|
|
else
|
|
{
|
|
mBypassed = true;
|
|
|
|
if (mFalseJump)
|
|
mFalseJump = mFalseJump->BypassEmptyBlocks();
|
|
if (mTrueJump)
|
|
mTrueJump = mTrueJump->BypassEmptyBlocks();
|
|
|
|
return this;
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
|
|
{
|
|
int i;
|
|
int next;
|
|
int pos, at;
|
|
uint8 b;
|
|
|
|
if (!mCopied)
|
|
{
|
|
mCopied = true;
|
|
|
|
|
|
next = mOffset + mCode.Size();
|
|
|
|
if (mFalseJump)
|
|
{
|
|
if (mFalseJump->mOffset <= mOffset)
|
|
{
|
|
if (mTrueJump->mOffset <= mOffset)
|
|
{
|
|
next += PutBranch(proc, mBranch, mTrueJump->mOffset - next);
|
|
next += PutJump(proc, mFalseJump->mOffset - next);
|
|
|
|
}
|
|
else
|
|
{
|
|
next += PutBranch(proc, InvertBranchCondition(mBranch), mFalseJump->mOffset - next);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
next += PutBranch(proc, mBranch, mTrueJump->mOffset - next);
|
|
}
|
|
}
|
|
else if (mTrueJump)
|
|
{
|
|
if (mTrueJump == this || mTrueJump->mOffset != next)
|
|
{
|
|
next += PutJump(proc, mTrueJump->mOffset - next);
|
|
}
|
|
}
|
|
|
|
assert(next - mOffset == mSize);
|
|
|
|
for (i = 0; i < mCode.Size(); i++)
|
|
{
|
|
target[i + mOffset] = mCode[i];
|
|
}
|
|
|
|
for (int i = 0; i < mRelocations.Size(); i++)
|
|
{
|
|
LinkerReference& rl(mRelocations[i]);
|
|
rl.mOffset += mOffset;
|
|
proc->mRelocations.Push(rl);
|
|
}
|
|
|
|
if (mTrueJump) mTrueJump->CopyCode(proc, target);
|
|
if (mFalseJump) mFalseJump->CopyCode(proc, target);
|
|
}
|
|
}
|
|
|
|
void NativeCodeBasicBlock::CalculateOffset(int& total)
|
|
{
|
|
int next;
|
|
|
|
if (mOffset > total)
|
|
{
|
|
mOffset = total;
|
|
next = total + mCode.Size();
|
|
|
|
if (mFalseJump)
|
|
{
|
|
if (mFalseJump->mOffset <= total)
|
|
{
|
|
// falseJump has been placed
|
|
|
|
if (mTrueJump->mOffset <= total)
|
|
{
|
|
// trueJump and falseJump have been placed, not much to do
|
|
|
|
next = next + BranchByteSize(next, mTrueJump->mOffset);
|
|
total = next + JumpByteSize(next, mFalseJump->mOffset);
|
|
mSize = total - mOffset;
|
|
}
|
|
else
|
|
{
|
|
// trueJump has not been placed, but falseJump has
|
|
|
|
total = next + BranchByteSize(next, mFalseJump->mOffset);
|
|
mSize = total - mOffset;
|
|
mTrueJump->CalculateOffset(total);
|
|
}
|
|
}
|
|
else if (mTrueJump->mOffset <= total)
|
|
{
|
|
// falseJump has not been placed, but trueJump has
|
|
|
|
total = next + BranchByteSize(next, mTrueJump->mOffset);
|
|
mSize = total - mOffset;
|
|
mFalseJump->CalculateOffset(total);
|
|
}
|
|
else if (mKnownShortBranch)
|
|
{
|
|
// neither falseJump nor trueJump have been placed,
|
|
// but we know from previous iteration that we can do
|
|
// a short branch
|
|
|
|
total = next + 2;
|
|
mSize = total - mOffset;
|
|
|
|
mFalseJump->CalculateOffset(total);
|
|
if (mTrueJump->mOffset > total)
|
|
{
|
|
// trueJump was not placed in the process, so lets place it now
|
|
mTrueJump->CalculateOffset(total);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// neither falseJump nor trueJump have been placed
|
|
//
|
|
|
|
if (mTrueJump->mFalseJump == mFalseJump || mTrueJump->mTrueJump == mFalseJump)
|
|
{
|
|
NativeCodeBasicBlock* block = mFalseJump;
|
|
mFalseJump = mTrueJump;
|
|
mTrueJump = block;
|
|
mBranch = InvertBranchCondition(mBranch);
|
|
}
|
|
|
|
// this may lead to some undo operation...
|
|
// first assume a full size branch:
|
|
|
|
total = next + 5;
|
|
mSize = total - mOffset;
|
|
|
|
mFalseJump->CalculateOffset(total);
|
|
if (mTrueJump->mOffset > total)
|
|
{
|
|
// trueJump was not placed in the process, so lets place it now
|
|
|
|
mTrueJump->CalculateOffset(total);
|
|
}
|
|
|
|
if (BranchByteSize(next, mTrueJump->mOffset) < 3)
|
|
{
|
|
// oh, we can replace by a short branch
|
|
|
|
mKnownShortBranch = true;
|
|
|
|
total = next + 2;
|
|
mSize = total - mOffset;
|
|
|
|
mFalseJump->CalculateOffset(total);
|
|
if (mTrueJump->mOffset > total)
|
|
{
|
|
// trueJump was not placed in the process, so lets place it now
|
|
|
|
mTrueJump->CalculateOffset(total);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (mTrueJump)
|
|
{
|
|
if (mTrueJump->mOffset <= total)
|
|
{
|
|
// trueJump has been placed, so append the branch size
|
|
|
|
total = next + JumpByteSize(next, mTrueJump->mOffset);
|
|
mSize = total - mOffset;
|
|
}
|
|
else
|
|
{
|
|
// we have to place trueJump, so just put it right behind us
|
|
|
|
total = next;
|
|
mSize = total - mOffset;
|
|
|
|
mTrueJump->CalculateOffset(total);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no exit from block
|
|
|
|
total += mCode.Size();
|
|
mSize = total - mOffset;
|
|
}
|
|
}
|
|
}
|
|
|
|
NativeCodeBasicBlock::NativeCodeBasicBlock(void)
|
|
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 }), mEntryBlocks(nullptr), mCode(0)
|
|
{
|
|
mTrueJump = mFalseJump = NULL;
|
|
mOffset = 0x7fffffff;
|
|
mCopied = false;
|
|
mKnownShortBranch = false;
|
|
mBypassed = false;
|
|
mAssembled = false;
|
|
mLocked = false;
|
|
mLoopHeadBlock = nullptr;
|
|
}
|
|
|
|
NativeCodeBasicBlock::~NativeCodeBasicBlock(void)
|
|
{
|
|
|
|
}
|
|
|
|
NativeCodeProcedure::NativeCodeProcedure(NativeCodeGenerator* generator)
|
|
: mGenerator(generator), mRelocations({ 0 }), mBlocks(nullptr)
|
|
{
|
|
mTempBlocks = 1000;
|
|
}
|
|
|
|
NativeCodeProcedure::~NativeCodeProcedure(void)
|
|
{
|
|
|
|
}
|
|
|
|
void NativeCodeProcedure::CompressTemporaries(void)
|
|
{
|
|
if (mInterProc->mTempSize > 16)
|
|
{
|
|
ResetVisited();
|
|
|
|
NumberSet used(256);
|
|
|
|
mEntryBlock->CollectZeroPageUsage(used);
|
|
|
|
uint8 remap[256];
|
|
for (int i = 0; i < 256; i++)
|
|
remap[i] = i;
|
|
|
|
int tpos = BC_REG_TMP_SAVED;
|
|
for (int i = 0; i < mInterProc->mTempOffset.Size(); i++)
|
|
{
|
|
bool tused = false;
|
|
|
|
int reg = BC_REG_TMP + mInterProc->mTempOffset[i];
|
|
if (reg >= BC_REG_TMP_SAVED)
|
|
{
|
|
int size = mInterProc->mTempSizes[i];
|
|
|
|
for (int j = 0; j < size; j++)
|
|
if (used[reg + j])
|
|
tused = true;
|
|
|
|
if (tused)
|
|
{
|
|
for (int j = 0; j < size; j++)
|
|
remap[reg + j] = tpos + j;
|
|
|
|
mInterProc->mTempOffset[i] = tpos - BC_REG_TMP;
|
|
tpos += size;
|
|
|
|
}
|
|
else
|
|
{
|
|
mInterProc->mTempOffset[i] = 0;
|
|
mInterProc->mTempSizes[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
ResetVisited();
|
|
mEntryBlock->RemapZeroPage(remap);
|
|
|
|
mInterProc->mTempSize = tpos - BC_REG_TMP;
|
|
}
|
|
}
|
|
|
|
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|
{
|
|
mInterProc = proc;
|
|
|
|
int nblocks = proc->mBlocks.Size();
|
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
|
for (int i = 0; i < nblocks; i++)
|
|
tblocks[i] = nullptr;
|
|
|
|
mIndex = proc->mID;
|
|
|
|
int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
|
|
int stackExpand = tempSave + proc->mLocalSize;
|
|
int commonFrameSize = proc->mCommonFrameSize;
|
|
|
|
if (proc->mCallsByteCode || commonFrameSize > 0)
|
|
commonFrameSize += 2;
|
|
|
|
mFrameOffset = 0;
|
|
mNoFrame = (stackExpand + proc->mCommonFrameSize) < 64 && !proc->mHasDynamicStack;// && !(proc->mHasInlineAssembler && !proc->mLeafProcedure);
|
|
|
|
if (mNoFrame)
|
|
proc->mLinkerObject->mFlags |= LOBJF_NO_FRAME;
|
|
|
|
if (mNoFrame)
|
|
{
|
|
if (stackExpand > 0)
|
|
mFrameOffset = tempSave;
|
|
}
|
|
else
|
|
{
|
|
stackExpand += 2;
|
|
}
|
|
|
|
if (!proc->mLeafProcedure)
|
|
{
|
|
if (mNoFrame)
|
|
mFrameOffset = commonFrameSize + tempSave;
|
|
}
|
|
|
|
mEntryBlock = AllocateBlock();
|
|
mEntryBlock->mLocked = true;
|
|
mBlocks.Push(mEntryBlock);
|
|
|
|
mExitBlock = AllocateBlock();
|
|
mExitBlock->mLocked = true;
|
|
mBlocks.Push(mExitBlock);
|
|
|
|
mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]);
|
|
mEntryBlock->mBranch = ASMIT_JMP;
|
|
|
|
// Place a temporary RTS
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
|
|
|
Optimize();
|
|
|
|
assert(mEntryBlock->mIns.Size() == 0);
|
|
|
|
// Remove temporary RTS
|
|
|
|
mExitBlock->mIns.Pop();
|
|
|
|
CompressTemporaries();
|
|
|
|
int frameSpace = tempSave;
|
|
|
|
tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
|
|
|
|
if (!(mGenerator->mCompilerOptions & COPT_NATIVE))
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));
|
|
|
|
if (mNoFrame)
|
|
{
|
|
if (stackExpand > 0)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
|
|
if (tempSave)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
if (tempSave > 1)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
|
|
if (tempSave)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
if (tempSave > 1)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
|
|
}
|
|
}
|
|
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, frameSpace + 2));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
|
|
}
|
|
|
|
if (!proc->mLeafProcedure)
|
|
{
|
|
if (commonFrameSize > 0)
|
|
{
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
}
|
|
}
|
|
|
|
if (!proc->mLeafProcedure && commonFrameSize > 0)
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
}
|
|
|
|
if (mNoFrame)
|
|
{
|
|
if (stackExpand > 0)
|
|
{
|
|
if (tempSave)
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave - 1));
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
|
|
if (tempSave > 1)
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
|
|
}
|
|
}
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
|
|
|
|
if (tempSave)
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
|
|
if (tempSave > 1)
|
|
{
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -8));
|
|
}
|
|
}
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
|
|
}
|
|
|
|
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
|
|
|
|
mEntryBlock->Assemble();
|
|
|
|
int total, base;
|
|
|
|
NativeCodeBasicBlock* lentryBlock = mEntryBlock->BypassEmptyBlocks();
|
|
|
|
total = 0;
|
|
lentryBlock->CalculateOffset(total);
|
|
|
|
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
|
|
lentryBlock->CopyCode(this, proc->mLinkerObject->AddSpace(total));
|
|
|
|
for (int i = 0; i < mRelocations.Size(); i++)
|
|
{
|
|
LinkerReference& rl(mRelocations[i]);
|
|
rl.mObject = proc->mLinkerObject;
|
|
if (!rl.mRefObject)
|
|
rl.mRefObject = proc->mLinkerObject;
|
|
proc->mLinkerObject->AddReference(rl);
|
|
}
|
|
}
|
|
|
|
void NativeCodeProcedure::Optimize(void)
|
|
{
|
|
#if 1
|
|
int step = 0;
|
|
|
|
bool changed;
|
|
do
|
|
{
|
|
changed = false;
|
|
|
|
ResetVisited();
|
|
for (int i = 0; i < mBlocks.Size(); i++)
|
|
{
|
|
mBlocks[i]->mNumEntries = 0;
|
|
mBlocks[i]->mVisiting = false;
|
|
mBlocks[i]->mLoopHead = false;
|
|
mBlocks[i]->mFromJump = nullptr;
|
|
}
|
|
mEntryBlock->CountEntries(nullptr);
|
|
|
|
#if 1
|
|
do
|
|
{
|
|
BuildDataFlowSets();
|
|
ResetVisited();
|
|
changed = mEntryBlock->RemoveUnusedResultInstructions();
|
|
|
|
ResetVisited();
|
|
NativeRegisterDataSet data;
|
|
if (mEntryBlock->ValueForwarding(data))
|
|
changed = true;
|
|
|
|
} while (changed);
|
|
#endif
|
|
ResetVisited();
|
|
if (mEntryBlock->PeepHoleOptimizer())
|
|
changed = true;
|
|
|
|
ResetVisited();
|
|
if (mEntryBlock->OptimizeSimpleLoop(this))
|
|
changed = true;
|
|
|
|
ResetVisited();
|
|
if (mEntryBlock->MergeBasicBlocks())
|
|
changed = true;
|
|
|
|
ResetVisited();
|
|
for (int i = 0; i < mBlocks.Size(); i++)
|
|
mBlocks[i]->mEntryBlocks.SetSize(0);
|
|
mEntryBlock->CollectEntryBlocks(nullptr);
|
|
|
|
if (step > 2)
|
|
{
|
|
ResetVisited();
|
|
if (mEntryBlock->JoinTailCodeSequences())
|
|
changed = true;
|
|
}
|
|
if (step == 3)
|
|
{
|
|
ResetVisited();
|
|
changed = mEntryBlock->OptimizeInnerLoops(this);
|
|
}
|
|
else if (step == 4)
|
|
{
|
|
#if 1
|
|
int xregs[256], yregs[256];
|
|
for (int i = 0; i < 256; i++)
|
|
xregs[i] = yregs[i] = 0;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
xregs[BC_REG_ACCU + i] = -1;
|
|
yregs[BC_REG_ACCU + i] = -1;
|
|
xregs[BC_REG_WORK + i] = -1;
|
|
yregs[BC_REG_WORK + i] = -1;
|
|
}
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
xregs[BC_REG_FPARAMS + i] = -1;
|
|
yregs[BC_REG_FPARAMS + i] = -1;
|
|
}
|
|
|
|
|
|
ResetVisited();
|
|
mEntryBlock->GlobalRegisterXYCheck(xregs, yregs);
|
|
if (xregs[0] >= 0)
|
|
{
|
|
int j = 1;
|
|
for (int i = 0; i < 256; i++)
|
|
if (xregs[i] > xregs[j])
|
|
j = i;
|
|
if (xregs[j] > 0)
|
|
{
|
|
ResetVisited();
|
|
mEntryBlock->GlobalRegisterXMap(j);
|
|
changed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!changed)
|
|
{
|
|
ResetVisited();
|
|
if (mEntryBlock->LocalRegisterXYMap())
|
|
changed = true;
|
|
}
|
|
}
|
|
#if 1
|
|
ResetVisited();
|
|
NativeRegisterDataSet data;
|
|
mEntryBlock->BuildEntryDataSet(data);
|
|
|
|
ResetVisited();
|
|
if (mEntryBlock->ApplyEntryDataSet())
|
|
changed = true;
|
|
#endif
|
|
if (!changed && step < 5)
|
|
{
|
|
step++;
|
|
changed = true;
|
|
}
|
|
} while (changed);
|
|
|
|
ResetVisited();
|
|
mEntryBlock->BlockSizeReduction();
|
|
#endif
|
|
}
|
|
|
|
void NativeCodeProcedure::BuildDataFlowSets(void)
|
|
{
|
|
//
|
|
// Build set with local provided/required temporaries
|
|
//
|
|
ResetVisited();
|
|
mBlocks[0]->BuildLocalRegSets();
|
|
|
|
//
|
|
// Build set of globaly provided temporaries
|
|
//
|
|
ResetVisited();
|
|
mBlocks[0]->BuildGlobalProvidedRegSet(NumberSet(NUM_REGS));
|
|
|
|
//
|
|
// Build set of globaly required temporaries, might need
|
|
// multiple iterations until it stabilizes
|
|
//
|
|
NumberSet totalRequired(NUM_REGS);
|
|
|
|
do {
|
|
ResetVisited();
|
|
} while (mBlocks[0]->BuildGlobalRequiredRegSet(totalRequired));
|
|
}
|
|
|
|
NativeCodeBasicBlock* NativeCodeProcedure::AllocateBlock(void)
|
|
{
|
|
NativeCodeBasicBlock* block = new NativeCodeBasicBlock();
|
|
block->mNoFrame = mNoFrame;
|
|
block->mFrameOffset = mFrameOffset;
|
|
block->mIndex = mTempBlocks++;
|
|
mBlocks.Push(block);
|
|
|
|
return block;
|
|
}
|
|
|
|
NativeCodeBasicBlock* NativeCodeProcedure::CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* sblock)
|
|
{
|
|
if (tblocks[sblock->mIndex])
|
|
return tblocks[sblock->mIndex];
|
|
|
|
NativeCodeBasicBlock* block = new NativeCodeBasicBlock();
|
|
block->mNoFrame = mNoFrame;
|
|
block->mFrameOffset = mFrameOffset;
|
|
mBlocks.Push(block);
|
|
|
|
tblocks[sblock->mIndex] = block;
|
|
block->mIndex = sblock->mIndex;
|
|
|
|
CompileInterBlock(iproc, sblock, block);
|
|
|
|
return block;
|
|
}
|
|
|
|
void NativeCodeProcedure::ResetVisited(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < mBlocks.Size(); i++)
|
|
{
|
|
mBlocks[i]->mVisited = false;
|
|
mBlocks[i]->mNumEntered = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* iblock, NativeCodeBasicBlock* block)
|
|
{
|
|
int i = 0;
|
|
while (i < iblock->mInstructions.Size())
|
|
{
|
|
const InterInstruction * ins = iblock->mInstructions[i];
|
|
|
|
switch (ins->mCode)
|
|
{
|
|
case IC_STORE:
|
|
block->StoreValue(iproc, ins);
|
|
break;
|
|
case IC_LOAD:
|
|
if (i + 1 < iblock->mInstructions.Size() &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_STORE &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mFinal &&
|
|
InterTypeSize[ins->mDst.mType] == 1)
|
|
{
|
|
block->LoadStoreValue(iproc, ins, iblock->mInstructions[i + 1]);
|
|
i++;
|
|
}
|
|
else if (i + 1 < iblock->mInstructions.Size() &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_STORE &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mFinal)
|
|
{
|
|
block->LoadStoreIndirectValue(iproc, ins, iblock->mInstructions[i + 1]);
|
|
i++;
|
|
}
|
|
else if (i + 2 < iblock->mInstructions.Size() &&
|
|
(ins->mDst.mType == IT_INT8 || ins->mDst.mType == IT_INT16 || ins->mDst.mType == IT_INT32) &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal &&
|
|
iblock->mInstructions[i + 2]->mCode == IC_STORE &&
|
|
iblock->mInstructions[i + 2]->mSrc[0].mTemp == iblock->mInstructions[i + 1]->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[0].mFinal &&
|
|
block->LoadOpStoreIndirectValue(iproc, ins, iblock->mInstructions[i + 1], 1, iblock->mInstructions[i + 2]))
|
|
{
|
|
i += 2;
|
|
}
|
|
else if (i + 2 < iblock->mInstructions.Size() &&
|
|
(ins->mDst.mType == IT_INT8 || ins->mDst.mType == IT_INT16 || ins->mDst.mType == IT_INT32) &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal &&
|
|
iblock->mInstructions[i + 2]->mCode == IC_STORE &&
|
|
iblock->mInstructions[i + 2]->mSrc[0].mTemp == iblock->mInstructions[i + 1]->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[0].mFinal &&
|
|
block->LoadOpStoreIndirectValue(iproc, ins, iblock->mInstructions[i + 1], 0, iblock->mInstructions[i + 2]))
|
|
{
|
|
i += 2;
|
|
}
|
|
else if (i + 1 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal &&
|
|
iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal)
|
|
{
|
|
block = block->BinaryOperator(iproc, this, iblock->mInstructions[i + 1], ins, ins);
|
|
i++;
|
|
}
|
|
else if (i + 1 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal)
|
|
{
|
|
block = block->BinaryOperator(iproc, this, iblock->mInstructions[i + 1], nullptr, ins);
|
|
i++;
|
|
}
|
|
else if (i + 1 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal)
|
|
{
|
|
block = block->BinaryOperator(iproc, this, iblock->mInstructions[i + 1], ins, nullptr);
|
|
i++;
|
|
}
|
|
else if (i + 2 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_LOAD && InterTypeSize[iblock->mInstructions[i + 1]->mDst.mType] == 2 &&
|
|
iblock->mInstructions[i + 1]->mDst.mTemp != ins->mDst.mTemp &&
|
|
iblock->mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 2]->mSrc[0].mTemp == iblock->mInstructions[i + 1]->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[0].mFinal &&
|
|
iblock->mInstructions[i + 2]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[1].mFinal)
|
|
{
|
|
block = block->BinaryOperator(iproc, this, iblock->mInstructions[i + 2], ins, iblock->mInstructions[i + 1]);
|
|
i += 2;
|
|
}
|
|
else if (i + 2 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_LOAD && InterTypeSize[iblock->mInstructions[i + 1]->mDst.mType] == 2 &&
|
|
iblock->mInstructions[i + 1]->mDst.mTemp != ins->mDst.mTemp &&
|
|
iblock->mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR &&
|
|
iblock->mInstructions[i + 2]->mSrc[1].mTemp == iblock->mInstructions[i + 1]->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[1].mFinal &&
|
|
iblock->mInstructions[i + 2]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 2]->mSrc[0].mFinal)
|
|
{
|
|
block = block->BinaryOperator(iproc, this, iblock->mInstructions[i + 2], iblock->mInstructions[i + 1], ins);
|
|
i += 2;
|
|
}
|
|
else if (i + 1 < iblock->mInstructions.Size() &&
|
|
InterTypeSize[ins->mDst.mType] >= 2 &&
|
|
iblock->mInstructions[i + 1]->mCode == IC_LEA &&
|
|
iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal)
|
|
{
|
|
block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], ins, nullptr);
|
|
i++;
|
|
}
|
|
else
|
|
block->LoadValue(iproc, ins);
|
|
break;
|
|
case IC_COPY:
|
|
block = block->CopyValue(iproc, ins, this);
|
|
break;
|
|
case IC_STRCPY:
|
|
block = block->StrcpyValue(iproc, ins, this);
|
|
break;
|
|
case IC_LOAD_TEMPORARY:
|
|
{
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
for (int i = 0; i < InterTypeSize[ins->mDst.mType]; i++)
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + i));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + i));
|
|
}
|
|
}
|
|
} break;
|
|
case IC_BINARY_OPERATOR:
|
|
block = block->BinaryOperator(iproc, this, ins, nullptr, nullptr);
|
|
break;
|
|
case IC_UNARY_OPERATOR:
|
|
block->UnaryOperator(iproc, this, ins);
|
|
break;
|
|
case IC_CONVERSION_OPERATOR:
|
|
block->NumericConversion(iproc, this, ins);
|
|
break;
|
|
case IC_LEA:
|
|
block->LoadEffectiveAddress(iproc, ins, nullptr, nullptr);
|
|
break;
|
|
case IC_CONSTANT:
|
|
block->LoadConstant(iproc, ins);
|
|
break;
|
|
case IC_CALL:
|
|
block->CallFunction(iproc, this, ins);
|
|
break;
|
|
case IC_CALL_NATIVE:
|
|
case IC_ASSEMBLER:
|
|
block->CallAssembler(iproc, ins);
|
|
break;
|
|
case IC_PUSH_FRAME:
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins->mConst.mIntConst + 2) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ((ins->mConst.mIntConst + 2) >> 8) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
} break;
|
|
case IC_POP_FRAME:
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mConst.mIntConst + 2) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ((ins->mConst.mIntConst + 2) >> 8) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
|
} break;
|
|
|
|
case IC_RELATIONAL_OPERATOR:
|
|
if (i + 1 < iblock->mInstructions.Size() && iblock->mInstructions[i + 1]->mCode == IC_BRANCH && iblock->mInstructions[i + 1]->mSrc[0].mFinal)
|
|
{
|
|
block->RelationalOperator(iproc, ins, this, CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
NativeCodeBasicBlock* tblock, * fblock, * rblock;
|
|
|
|
tblock = AllocateBlock();
|
|
fblock = AllocateBlock();
|
|
rblock = AllocateBlock();
|
|
|
|
block->RelationalOperator(iproc, ins, this, tblock, fblock);
|
|
|
|
tblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 1));
|
|
tblock->Close(rblock, nullptr, ASMIT_JMP);
|
|
fblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
fblock->Close(rblock, nullptr, ASMIT_JMP);
|
|
|
|
rblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp]));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
rblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
|
rblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
|
|
block = rblock;
|
|
}
|
|
break;
|
|
|
|
case IC_RETURN_VALUE:
|
|
{
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mType == IT_FLOAT)
|
|
{
|
|
union { float f; unsigned int v; } cc;
|
|
cc.f = ins->mSrc[0].mFloatConst;
|
|
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
else
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
if (ins->mSrc[0].mType == IT_INT32)
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
|
if (ins->mSrc[0].mType == IT_FLOAT || ins->mSrc[0].mType == IT_INT32)
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 2));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 3));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
|
|
}
|
|
}
|
|
|
|
block->Close(mExitBlock, nullptr, ASMIT_JMP);
|
|
return;
|
|
}
|
|
|
|
case IC_RETURN:
|
|
block->Close(mExitBlock, nullptr, ASMIT_JMP);
|
|
return;
|
|
|
|
case IC_TYPECAST:
|
|
if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp]));
|
|
if (InterTypeSize[ins->mDst.mType] > 1)
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + 1));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IC_BRANCH:
|
|
if (ins->mSrc[0].mTemp < 0)
|
|
{
|
|
if (ins->mSrc[0].mIntConst == 0)
|
|
block->Close(CompileBlock(iproc, iblock->mFalseJump), nullptr, ASMIT_JMP);
|
|
else
|
|
block->Close(CompileBlock(iproc, iblock->mTrueJump), nullptr, ASMIT_JMP);
|
|
}
|
|
else
|
|
{
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp]));
|
|
if (InterTypeSize[ins->mSrc[0].mType] > 1)
|
|
block->mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
|
|
|
block->Close(CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump), ASMIT_BNE);
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
block->Close(CompileBlock(iproc, iblock->mTrueJump), nullptr, ASMIT_JMP);
|
|
}
|
|
|
|
|
|
NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker)
|
|
: mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT), mRuntime({ 0 })
|
|
{
|
|
}
|
|
|
|
NativeCodeGenerator::~NativeCodeGenerator(void)
|
|
{
|
|
|
|
}
|
|
|
|
NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* ident)
|
|
{
|
|
int i = 0;
|
|
while (i < mRuntime.Size() && mRuntime[i].mIdent != ident)
|
|
i++;
|
|
Location loc;
|
|
if (i == mRuntime.Size() || !mRuntime[i].mLinkerObject)
|
|
mErrors->Error(loc, EERR_RUNTIME_CODE, "Undefied runtime function", ident->mString);
|
|
return mRuntime[i];
|
|
}
|
|
|
|
void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* object, int offset)
|
|
{
|
|
Runtime rt;
|
|
rt.mIdent = ident;
|
|
rt.mLinkerObject = object;
|
|
rt.mOffset = offset;
|
|
mRuntime.Push(rt);
|
|
}
|