oscar64/oscar64/NativeCodeGenerator.cpp

4872 lines
165 KiB
C++

#include "NativeCodeGenerator.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;
NativeRegisterData::NativeRegisterData(void)
: mImmediate(false), mZeroPage(false)
{
}
void NativeRegisterData::Reset(void)
{
mImmediate = false;
mZeroPage = false;
}
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].mZeroPage && mRegs[i].mValue == addr)
mRegs[i].mZeroPage = false;
}
}
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, int varIndex, bool lower, bool upper)
: mType(type), mMode(mode), mAddress(address), mVarIndex(varIndex), mLower(lower), mUpper(upper), mRuntime(nullptr), mFunction(false)
{}
NativeCodeInstruction::NativeCodeInstruction(const char* runtime)
: mType(ASMIT_JSR), mMode(ASMIM_ABSOLUTE), mAddress(0), mVarIndex(0), mLower(true), mUpper(true), mRuntime(runtime), mFunction(false)
{}
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, const char* runtime, int address, bool lower, bool upper)
: mType(type), mMode(mode), mAddress(address), mVarIndex(0), mLower(lower), mUpper(upper), mRuntime(runtime), mFunction(false)
{}
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)
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;
for (int i = 0; i < 4; i++)
{
requiredTemps += BC_REG_ACCU + i;
requiredTemps += BC_REG_WORK + i;
}
requiredTemps += BC_REG_LOCALS;
requiredTemps += BC_REG_LOCALS + 1;
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:
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_ADC:
case ASMIT_SBC:
case ASMIT_ORA:
case ASMIT_EOR:
case ASMIT_AND:
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:
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::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::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.mVarIndex == mVarIndex && ins.mAddress == mAddress && ins.mFunction == mFunction && ins.mRuntime == mRuntime);
default:
return false;
}
}
bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
{
bool changed = false;
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);
}
return false;
}
switch (mType)
{
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].mImmediate && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
changed = true;
}
else
{
data.mRegs[CPU_REG_A].mImmediate = true;
data.mRegs[CPU_REG_A].mZeroPage = false;
data.mRegs[CPU_REG_A].mValue = mAddress;
}
data.mRegs[CPU_REG_Z].mImmediate = true;
data.mRegs[CPU_REG_Z].mValue = mAddress;
}
else
{
if (mMode != ASMIM_ZERO_PAGE)
data.mRegs[CPU_REG_A].Reset();
data.mRegs[CPU_REG_Z].Reset();
}
break;
case ASMIT_ADC:
case ASMIT_SBC:
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_A].mImmediate - mAddress;
data.mRegs[CPU_REG_C].mImmediate = true;
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_A].mImmediate >= mAddress;
}
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_X].mImmediate - mAddress;
data.mRegs[CPU_REG_C].mImmediate = true;
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_X].mImmediate >= 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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[CPU_REG_Y].mImmediate - mAddress;
data.mRegs[CPU_REG_C].mImmediate = true;
data.mRegs[CPU_REG_C].mValue = data.mRegs[CPU_REG_Y].mImmediate >= 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].mImmediate)
{
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].mImmediate = true;
data.mRegs[CPU_REG_Z].mValue = mAddress;
}
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].mImmediate && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
changed = true;
}
else
{
data.mRegs[CPU_REG_X].mImmediate = true;
data.mRegs[CPU_REG_X].mZeroPage = false;
data.mRegs[CPU_REG_X].mValue = mAddress;
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mImmediate && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
changed = true;
}
else
{
data.mRegs[CPU_REG_Y].mImmediate = true;
data.mRegs[CPU_REG_Y].mZeroPage = false;
data.mRegs[CPU_REG_Y].mValue = mAddress;
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mImmediate)
{
data.mRegs[CPU_REG_Z].mImmediate = true;
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].mZeroPage && data.mRegs[CPU_REG_A].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
changed = true;
}
else if (data.mRegs[mAddress].mImmediate)
{
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].mZeroPage)
{
data.mRegs[CPU_REG_A] = data.mRegs[mAddress];
mAddress = data.mRegs[CPU_REG_A].mValue;
changed = true;
}
else
{
data.mRegs[CPU_REG_A].Reset();
if (data.mRegs[mAddress].mImmediate)
{
data.mRegs[CPU_REG_A].mImmediate = true;
data.mRegs[CPU_REG_A].mValue = data.mRegs[mAddress].mValue;
}
else
{
data.mRegs[CPU_REG_A].mZeroPage = true;
data.mRegs[CPU_REG_A].mValue = mAddress;
}
}
break;
case ASMIT_LDX:
if (data.mRegs[CPU_REG_X].mZeroPage && data.mRegs[CPU_REG_X].mValue == mAddress)
{
mType = ASMIT_NOP;
changed = true;
}
else if (data.mRegs[mAddress].mImmediate)
{
data.mRegs[CPU_REG_X] = data.mRegs[mAddress];
mAddress = data.mRegs[CPU_REG_X].mValue;
mMode = ASMIM_IMMEDIATE;
changed = true;
}
else
{
data.mRegs[CPU_REG_X].Reset();
if (data.mRegs[mAddress].mImmediate)
{
data.mRegs[CPU_REG_X].mImmediate = true;
data.mRegs[CPU_REG_X].mValue = data.mRegs[mAddress].mValue;
}
else
{
data.mRegs[CPU_REG_X].mZeroPage = true;
data.mRegs[CPU_REG_X].mValue = mAddress;
}
}
break;
case ASMIT_LDY:
if (data.mRegs[CPU_REG_Y].mZeroPage && data.mRegs[CPU_REG_Y].mValue == mAddress)
{
mType = ASMIT_NOP;
changed = true;
}
else if (data.mRegs[mAddress].mImmediate)
{
data.mRegs[CPU_REG_Y] = data.mRegs[mAddress];
mAddress = data.mRegs[CPU_REG_Y].mValue;
mMode = ASMIM_IMMEDIATE;
changed = true;
}
else
{
data.mRegs[CPU_REG_Y].Reset();
if (data.mRegs[mAddress].mImmediate)
{
data.mRegs[CPU_REG_Y].mImmediate = true;
data.mRegs[CPU_REG_Y].mValue = data.mRegs[mAddress].mValue;
}
else
{
data.mRegs[CPU_REG_Y].mZeroPage = true;
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].mImmediate)
{
mAddress = data.mRegs[mAddress].mValue;
mMode = ASMIM_IMMEDIATE;
changed = true;
}
else if (data.mRegs[mAddress].mZeroPage)
{
mAddress = data.mRegs[mAddress].mValue;
changed = true;
}
break;
case ASMIT_STA:
data.ResetZeroPage(mAddress);
if (data.mRegs[CPU_REG_A].mImmediate)
{
data.mRegs[mAddress].mImmediate = true;
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue;
}
else if (data.mRegs[CPU_REG_A].mZeroPage)
{
data.mRegs[mAddress].mZeroPage = true;
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue;
}
else
{
data.mRegs[CPU_REG_A].mZeroPage = true;
data.mRegs[CPU_REG_A].mValue = mAddress;
}
break;
case ASMIT_STX:
data.ResetZeroPage(mAddress);
if (data.mRegs[CPU_REG_X].mImmediate)
{
data.mRegs[mAddress].mImmediate = true;
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_X].mValue;
}
else
{
data.mRegs[CPU_REG_X].mZeroPage = true;
data.mRegs[CPU_REG_X].mValue = mAddress;
}
break;
case ASMIT_STY:
data.ResetZeroPage(mAddress);
if (data.mRegs[CPU_REG_Y].mImmediate)
{
data.mRegs[mAddress].mImmediate = true;
data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_Y].mValue;
}
else
{
data.mRegs[CPU_REG_Y].mZeroPage = true;
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;
}
}
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;
}
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 (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 (mVarIndex != -1)
{
ByteCodeRelocation rl;
rl.mAddr = block->mCode.Size();
rl.mFunction = mFunction;
rl.mLower = mLower;
rl.mUpper = mUpper;
rl.mIndex = mVarIndex;
rl.mOffset = mAddress;
rl.mRuntime = nullptr;
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 (mRuntime)
{
ByteCodeRelocation rl;
rl.mAddr = block->mCode.Size();
rl.mFunction = mFunction;
rl.mLower = true;
rl.mUpper = true;
rl.mIndex = -1;
rl.mOffset = mAddress;
rl.mRuntime = mRuntime;
block->mRelocations.Push(rl);
block->PutWord(0);
}
else if (mVarIndex != -1)
{
ByteCodeRelocation rl;
rl.mAddr = block->mCode.Size();
rl.mFunction = mFunction;;
rl.mLower = true;
rl.mUpper = true;
rl.mIndex = mVarIndex;
rl.mOffset = mAddress;
rl.mRuntime = nullptr;
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.Insert(code);
}
void NativeCodeBasicBlock::PutWord(uint16 code)
{
this->mCode.Insert((uint8)(code & 0xff));
this->mCode.Insert((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);
ByteCodeRelocation rl;
rl.mAddr = mCode.Size();
rl.mFunction = true;
rl.mLower = true;
rl.mUpper = true;
rl.mIndex = proc->mIndex;
rl.mOffset = mOffset + mCode.Size() + offset - 1;
rl.mRuntime = nullptr;
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);
ByteCodeRelocation rl;
rl.mAddr = mCode.Size();
rl.mFunction = true;
rl.mLower = true;
rl.mUpper = true;
rl.mIndex = proc->mIndex;
rl.mOffset = mOffset + mCode.Size() + offset - 3;
rl.mRuntime = nullptr;
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->mFloatValue;
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->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mIntValue, ins->mVarIndex, true, false));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mIntValue, ins->mVarIndex, false, true));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mIntValue & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mIntValue >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mIntValue;
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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->mMemory == IM_PROCEDURE)
{
NativeCodeInstruction lins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSIntConst[0], ins->mVarIndex, true, false);
lins.mFunction = ins->mMemory == IM_PROCEDURE;
NativeCodeInstruction hins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSIntConst[0], ins->mVarIndex, false, true);
hins.mFunction = ins->mMemory == IM_PROCEDURE;
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
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mIntValue & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
if (InterTypeSize[ins->mTType] > 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mIntValue >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
}
}
void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins)
{
LoadConstantToReg(proc, ins, ins->mTType, BC_REG_TMP + proc->mTempOffset[ins->mTTemp]);
}
void NativeCodeBasicBlock::CheckFrameIndex(int& reg, int& index, int size)
{
if (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;
reg = BC_REG_ADDR;
}
}
void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstruction * ins)
{
if (ins->mSType[0] == IT_FLOAT)
{
if (ins->mSTemp[1] < 0)
{
if (ins->mSTemp[0] < 0)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[0];
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 2, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 3, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 3));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 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_INY, ASMIM_IMPLIED));
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_INY, ASMIM_IMPLIED));
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_INY, ASMIM_IMPLIED));
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->mSTemp[0]];
if (ins->mSFinal[0] && 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->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 2, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 3, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 3));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 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_INY, ASMIM_IMPLIED));
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_INY, ASMIM_IMPLIED));
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_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
}
else
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
else
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
}
}
else if (ins->mSType[0] == IT_POINTER)
{
if (ins->mSTemp[1] < 0)
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
CheckFrameIndex(reg, index, 2);
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
else
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
}
else
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
else
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
}
}
else
{
if (ins->mSTemp[1] < 0)
{
if (ins->mSTemp[0] < 0)
{
if (ins->mOperandSize == 1)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
CheckFrameIndex(reg, index, 1);
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
else if (ins->mOperandSize == 2)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
CheckFrameIndex(reg, index, 2);
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
}
else
{
if (ins->mOperandSize == 1)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
else if (ins->mOperandSize == 2)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1, ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, ins->mSIntConst[1] + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[1];
int reg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, reg));
}
else if (ins->mMemory == IM_FRAME)
{
int index = ins->mVarIndex + ins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
}
}
else
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
if (ins->mOperandSize == 2)
{
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
}
else
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
if (ins->mOperandSize == 2)
{
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
}
}
}
}
}
}
void NativeCodeBasicBlock::LoadStoreValue(InterCodeProcedure* proc, const InterInstruction * rins, const InterInstruction * wins)
{
if (rins->mTType == IT_FLOAT)
{
}
else if (rins->mTType == IT_POINTER)
{
}
else
{
if (wins->mOperandSize == 1)
{
if (rins->mSTemp[0] < 0)
{
if (rins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins->mSIntConst[0], rins->mVarIndex));
}
else if (rins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, rins->mSIntConst[0]));
}
else if (rins->mMemory == IM_LOCAL || rins->mMemory == IM_PARAM)
{
int index = rins->mSIntConst[0];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (rins->mMemory == IM_LOCAL)
index += proc->mLocalVars[rins->mVarIndex].mOffset;
else
index += rins->mVarIndex + proc->mLocalSize + 2;
CheckFrameIndex(areg, index, 4);
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
}
}
else
{
if (rins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, rins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSTemp[0]]));
}
}
if (wins->mSTemp[1] < 0)
{
if (wins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins->mSIntConst[1], wins->mVarIndex));
}
else if (wins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE, wins->mSIntConst[1]));
}
else if (wins->mMemory == IM_LOCAL || wins->mMemory == IM_PARAM)
{
int index = wins->mSIntConst[1];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (wins->mMemory == IM_LOCAL)
index += proc->mLocalVars[wins->mVarIndex].mOffset;
else
index += wins->mVarIndex + proc->mLocalSize + 2;
CheckFrameIndex(areg, index, 1);
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, areg));
}
else if (wins->mMemory == IM_FRAME)
{
int index = wins->mVarIndex + wins->mSIntConst[1] + 2;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
}
}
else
{
if (wins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, wins->mSIntConst[1]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSTemp[1]]));
}
}
}
}
}
void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterInstruction * ins, int reg, const NativeCodeInstruction* ainsl, const NativeCodeInstruction* ainsh)
{
if (ins->mTType == IT_FLOAT)
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0], ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 1, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 2, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 3, ins->mVarIndex));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[0];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, areg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
}
}
else
{
if (ins->mMemory == IM_INDIRECT)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
}
}
}
else if (ins->mTType == IT_POINTER)
{
if (ins->mSTemp[0] < 0)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0], ins->mVarIndex));
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->mSIntConst[0] + 1, ins->mVarIndex));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0]));
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->mSIntConst[0] + 1));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[0];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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_INY, ASMIM_IMPLIED));
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->mMemory == IM_INDIRECT)
{
int src = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]];
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, src));
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 == src)
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
else
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, src));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
if (reg == src)
mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, reg));
}
}
}
else
{
if (ins->mSTemp[0] < 0)
{
if (ins->mOperandSize == 1)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0], ins->mVarIndex));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0]));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[0];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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));
if (InterTypeSize[ins->mTType] > 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 (ins->mOperandSize == 2)
{
if (ins->mMemory == IM_GLOBAL)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0], ins->mVarIndex));
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->mSIntConst[0] + 1, ins->mVarIndex));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_ABSOLUTE)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSIntConst[0]));
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->mSIntConst[0] + 1));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (ins->mMemory == IM_LOCAL || ins->mMemory == IM_PARAM)
{
int index = ins->mSIntConst[0];
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mVarIndex].mOffset;
else
index += ins->mVarIndex + proc->mLocalSize + 2;
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_INY, ASMIM_IMPLIED));
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->mMemory == IM_INDIRECT)
{
if (ins->mOperandSize == 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
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->mTType] > 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 (ins->mOperandSize == 2)
{
int src = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]];
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ins->mSIntConst[0]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, src));
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->mTType] > 1)
{
if (reg == src)
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
else
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, src));
if (ainsh) mIns.Push(*ainsh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
if (reg == src)
mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, reg));
}
else
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
}
}
}
}
}
void NativeCodeBasicBlock::LoadValue(InterCodeProcedure* proc, const InterInstruction * ins)
{
LoadValueToReg(proc, ins, BC_REG_TMP + proc->mTempOffset[ins->mTTemp], nullptr, nullptr);
}
void NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc)
{
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]];
int size = ins->mOperandSize;
if (size < 4)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
for (int i = 0; i < size; i++)
{
if (i > 0)
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
}
}
else if (size < 128)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, -7));
}
else if (size <= 256)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, size - 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -7));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, sreg));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, dreg));
}
}
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
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 0));
for (int i = 0; i < shift; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, reg + 1));
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0));
}
}
int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, 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->mSTemp[index]]));
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->mSTemp[index]] + 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)
{
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;
default:
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
mIns.Push(NativeCodeInstruction("mul16by8"));
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;
}
void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction * sins1, const InterInstruction * sins0)
{
int treg = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
if (ins->mTType == IT_FLOAT)
{
int sreg0 = ins->mSTemp[0] < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]];
if (ins->mSTemp[1] < 0)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[1];
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->mSFinal[1] && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]))
{
// cull previous store from accu to temp using direcrt forwarding
mIns.SetSize(mIns.Size() - 8);
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]])
sreg0 = BC_REG_ACCU;
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]] + 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->mSTemp[1]] + 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->mSTemp[1]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
if (ins->mSTemp[0] < 0)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[0];
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));
}
mIns.Push(NativeCodeInstruction("fsplitt"));
switch (ins->mOperator)
{
case IA_ADD:
mIns.Push(NativeCodeInstruction("faddsub"));
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));
mIns.Push(NativeCodeInstruction("faddsub"));
break;
case IA_MUL:
mIns.Push(NativeCodeInstruction("fmul"));
break;
case IA_DIVS:
case IA_DIVU:
mIns.Push(NativeCodeInstruction("fdiv"));
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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 3));
}
else
{
switch (ins->mOperator)
{
case IA_ADD:
case IA_OR:
case IA_AND:
case IA_XOR:
{
if (ins->mOperator == IA_ADD && (
ins->mSTemp[0] < 0 && ins->mSIntConst[0] == 1 && !sins1 && ins->mSTemp[1] == ins->mTTemp ||
ins->mSTemp[1] < 0 && ins->mSIntConst[1] == 1 && !sins0 && ins->mSTemp[0] == ins->mTTemp))
{
mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, 2));
mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, treg + 1));
}
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->mSTemp[1] < 0)
{
insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff);
insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 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->mSTemp[0]]));
mIns.Push(insl);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (ins->mSTemp[0] < 0)
{
insl = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff);
insh = NativeCodeInstruction(atype, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 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->mSTemp[1]]));
mIns.Push(insl);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else
{
if (sins1 && sins0)
{
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg);
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, treg + 1);
LoadValueToReg(proc, sins1, treg, nullptr, nullptr);
LoadValueToReg(proc, sins0, treg, &insl, &insh);
}
else if (sins1)
{
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]);
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1);
LoadValueToReg(proc, sins1, treg, &insl, &insh);
}
else if (sins0)
{
insl = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]);
insh = NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
}
} break;
case IA_SUB:
{
NativeCodeInstruction insl, insh;
if (ins->mSTemp[0] < 0)
{
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff);
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 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->mSTemp[1]]));
mIns.Push(insl);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(insh);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (ins->mSTemp[1] < 0)
{
if (sins0)
{
insl = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg);
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, treg + 1);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
LoadValueToReg(proc, sins0, treg, &insl, &insh);
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[0]]);
insh = NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[1]]));
mIns.Push(insl);
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1] < 0 && (ins->mSIntConst[1] & ~0xff) == 0)
{
reg = ShortMultiply(proc, ins, sins0, 0, ins->mSIntConst[1] & 0xff);
}
else if (ins->mOperator == IA_MUL && ins->mSTemp[0] < 0 && (ins->mSIntConst[0] & ~0xff) == 0)
{
reg = ShortMultiply(proc, ins, sins1, 1, ins->mSIntConst[0] & 0xff);
}
else
{
if (sins1)
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
else if (ins->mSTemp[1] < 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 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->mSTemp[1]]));
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->mSTemp[1]] + 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->mSTemp[0] < 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 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->mSTemp[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->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
}
switch (ins->mOperator)
{
case IA_MUL:
mIns.Push(NativeCodeInstruction("mul16"));
reg = BC_REG_WORK + 2;
break;
case IA_DIVS:
mIns.Push(NativeCodeInstruction("divs16"));
break;
case IA_MODS:
mIns.Push(NativeCodeInstruction("mods16"));
reg = BC_REG_WORK + 2;
break;
case IA_DIVU:
mIns.Push(NativeCodeInstruction("divu16"));
break;
case IA_MODU:
mIns.Push(NativeCodeInstruction("modu16"));
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->mTTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 1));
} break;
case IA_SHL:
{
if (sins1) LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]], nullptr, nullptr);
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]], nullptr, nullptr);
if (ins->mSTemp[0] < 0)
{
int shift = ins->mSIntConst[0] & 15;
if (shift == 0)
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (shift == 1)
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
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->mSTemp[1]] + 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 (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
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->mSTemp[1]] + 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->mSTemp[1] < 0 && IsPowerOf2(ins->mSIntConst[1] & 0xffff))
{
int l = Binlog(ins->mSIntConst[1] & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (l < 8)
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 8 + l));
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, "bitshift", l));
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSTemp[1] < 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
}
else if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]], nullptr, nullptr);
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]], nullptr, nullptr);
if (ins->mSTemp[0] < 0)
{
int shift = ins->mSIntConst[0] & 15;
if (shift == 0)
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else if (shift == 1)
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]]));
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 (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]]));
}
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_ROL, ASMIM_IMPLIED));
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg ));
}
}
else if (ins->mSTemp[1] < 0 && IsPowerOf2(ins->mSIntConst[1] & 0xffff))
{
int l = Binlog(ins->mSIntConst[1] & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 39 - l));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 47 - l));
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSTemp[1] < 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
}
else if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1]], nullptr, nullptr);
if (sins0) LoadValueToReg(proc, sins0, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]], nullptr, nullptr);
if (ins->mSTemp[0] < 0)
{
int shift = ins->mSIntConst[0] & 15;
if (shift == 0)
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
}
else
{
if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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->mSTemp[1] < 0 && IsPowerOf2(ins->mSIntConst[1] & 0xffff))
{
int l = Binlog(ins->mSIntConst[1] & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
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, "bitshift", 39 - l));
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, "bitshift", 47 - l));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 39 - l));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 47 - l));
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->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSTemp[1] < 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
}
else if (ins->mSTemp[1] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 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;
}
}
}
void NativeCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, const InterInstruction * ins)
{
int treg = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
if (ins->mTType == IT_FLOAT)
{
switch (ins->mOperator)
{
case IA_NEG:
case IA_ABS:
if (ins->mSTemp[0] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 3));
}
else
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 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->mTTemp] + 3));
break;
case IA_FLOOR:
case IA_CEIL:
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[0]] + 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->mSTemp[0]] + 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->mSTemp[0]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
if (ins->mOperator == IA_FLOOR)
mIns.Push(NativeCodeInstruction("ffloor"));
else
mIns.Push(NativeCodeInstruction("fceil"));
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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mSTemp[0]]));
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->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
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->mSTemp[0]]));
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->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
break;
}
}
}
void NativeCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const InterInstruction * ins)
{
switch (ins->mOperator)
{
case IA_FLOAT2INT:
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[0]] + 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->mSTemp[0]] + 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->mSTemp[0]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
mIns.Push(NativeCodeInstruction("ftoi"));
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->mTTemp] + 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->mTTemp] + 1));
} break;
case IA_INT2FLOAT:
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction("ffromi"));
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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 3));
} break;
case IA_EXT8TO16S:
mIns.Push(NativeCodeInstruction(ASMIT_LDX, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
if (ins->mSTemp[0] != ins->mTTemp)
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_BPL, ASMIM_RELATIVE, 1));
mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 1));
break;
case IA_EXT8TO16U:
if (ins->mSTemp[0] != ins->mTTemp)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp]));
}
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 1));
break;
}
}
void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump)
{
InterOperator op = ins->mOperator;
if (ins->mSType[0] == 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->mSTemp[li] < 0)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[li];
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->mSFinal[li] && CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSTemp[li]]))
{
// 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->mSTemp[li]] + 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->mSTemp[li]] + 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->mSTemp[li]] + 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->mSTemp[li]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
if (ins->mSTemp[ri] < 0)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[ri];
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->mSTemp[ri]] + 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->mSTemp[ri]] + 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->mSTemp[ri]] + 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->mSTemp[ri]] + 3));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
}
mIns.Push(NativeCodeInstruction("fcmp"));
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
{
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;
}
if (op >= IA_CMPGES && ins->mOperator <= IA_CMPLS)
{
if (ins->mSTemp[ri] >= 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[ri]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK));
}
if (ins->mSTemp[li] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ((ins->mSIntConst[li] >> 8) & 0xff) ^ 0x80));
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[li]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, 0x80));
}
if (ins->mSTemp[ri] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ((ins->mSIntConst[ri] >> 8) & 0xff) ^ 0x80));
else
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_WORK));
}
else
{
if (ins->mSTemp[li] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[li] >> 8) & 0xff));
else
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[li]] + 1));
if (ins->mSTemp[ri] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, (ins->mSIntConst[ri] >> 8) & 0xff));
else
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[ri]] + 1));
}
this->Close(nblock, eblock, ASMIT_BNE);
if (ins->mSTemp[li] < 0)
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[li] & 0xff));
else
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[li]]));
if (ins->mSTemp[ri] < 0)
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, ins->mSIntConst[ri] & 0xff));
else
eblock->mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[ri]]));
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->mSTemp[0] < 0 && ins->mSIntConst[0] == 0)
LoadValueToReg(proc, sins1, ins->mTTemp, nullptr, nullptr);
else
{
if (ins->mSTemp[0] < 0)
{
NativeCodeInstruction ainsl(ASMIT_ADC, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff);
NativeCodeInstruction ainsh(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff);
LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mTTemp], &ainsl, &ainsh);
}
else
{
NativeCodeInstruction ainsl(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]);
NativeCodeInstruction ainsh(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1);
LoadValueToReg(proc, sins1, BC_REG_TMP + proc->mTempOffset[ins->mTTemp], &ainsl, &ainsh);
}
}
}
else
{
if (ins->mSTemp[0] >= 0 || ins->mSIntConst[0] != 0)
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
if (ins->mSTemp[1] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSIntConst[1] & 0xff));
else
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]]));
if (ins->mSTemp[0] < 0)
{
if (ins->mSIntConst[0])
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ins->mSIntConst[0] & 0xff));
}
else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp]));
if (ins->mSTemp[1] < 0)
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[1] >> 8) & 0xff));
else
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]] + 1));
if (ins->mSTemp[0] < 0)
{
if (ins->mSIntConst[0])
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
}
else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mTTemp] + 1));
}
}
void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, const InterInstruction * ins)
{
if (ins->mSTemp[0] < 0)
{
NativeCodeInstruction lins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSIntConst[0], ins->mVarIndex, true, false);
lins.mFunction = ins->mMemory == IM_PROCEDURE;
NativeCodeInstruction hins(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSIntConst[0], ins->mVarIndex, false, true);
hins.mFunction = ins->mMemory == IM_PROCEDURE;
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->mSTemp[0]] + 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->mSTemp[0]] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
}
mIns.Push(NativeCodeInstruction("bcexec"));
if (ins->mTTemp >= 0)
{
if (ins->mTType == 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 1));
}
}
}
void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins)
{
NativeCodeInstruction ains(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSIntConst[0], ins->mVarIndex, true, true);
ains.mFunction = ins->mMemory == IM_PROCEDURE;
mIns.Push(ains);
if (ins->mTTemp >= 0)
{
if (ins->mTType == 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 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->mTTemp] + 1));
}
}
}
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].IsUsedResultInstructions(requiredRegs))
{
if (i > 0 && mIns[i - 1].mMode == ASMIM_RELATIVE && mIns[i - 1].mAddress > 0)
{
mIns[i - 1].mType = ASMIT_NOP;
}
mIns[i].mType = ASMIT_NOP;
changed = true;
}
}
if (mTrueJump)
{
if (mTrueJump->RemoveUnusedResultInstructions())
changed = true;
}
if (mFalseJump)
{
if (mFalseJump->RemoveUnusedResultInstructions())
changed = true;
}
}
return changed;
}
void NativeCodeBasicBlock::CountEntries(void)
{
mNumEntries++;
if (!mVisited)
{
mVisited = true;
if (mTrueJump)
mTrueJump->CountEntries();
if (mFalseJump)
mFalseJump->CountEntries();
}
}
bool NativeCodeBasicBlock::MergeBasicBlocks(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this)
{
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;
}
if (mTrueJump)
mTrueJump->MergeBasicBlocks();
if (mFalseJump)
mFalseJump->MergeBasicBlocks();
}
return changed;
}
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_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].mVarIndex < 0)
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] = mIns[at + 1];
mIns[at + 1].mType = ASMIT_NOP;
return true;
}
return false;
}
bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
{
if (!mVisited)
{
bool changed = false;
mVisited = true;
NativeRegisterDataSet data;
for (int i = 0; i < mIns.Size(); i++)
{
mIns[i].ValueForwarding(data);
}
if (mFalseJump)
{
switch (mBranch)
{
case ASMIT_BCS:
if (data.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (!data.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BCC:
if (data.mRegs[CPU_REG_C].mImmediate)
{
mBranch = ASMIT_JMP;
if (data.mRegs[CPU_REG_C].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BNE:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (data.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BEQ:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!data.mRegs[CPU_REG_Z].mValue)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BPL:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (!(data.mRegs[CPU_REG_Z].mValue & 0x80))
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
case ASMIT_BMI:
if (data.mRegs[CPU_REG_Z].mImmediate)
{
mBranch = ASMIT_JMP;
if (data.mRegs[CPU_REG_Z].mValue & 0x80)
mTrueJump = mFalseJump;
mFalseJump = nullptr;
changed = true;
}
break;
}
}
// move load store pairs 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_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;
}
}
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);
for (int i = 0; i < mIns.Size(); i++)
{
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;
}
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;
}
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;
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
}
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)
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->mOffset != next)
{
next += PutJump(proc, mTrueJump->mOffset - next);
}
}
assert(next - mOffset == mSize);
for (i = 0; i < mCode.Size(); i++)
{
mCode.Lookup(i, target[i + mOffset]);
}
for (int i = 0; i < mRelocations.Size(); i++)
{
ByteCodeRelocation& rl(mRelocations[i]);
rl.mAddr += 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
// 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 })
{
mTrueJump = mFalseJump = NULL;
mOffset = 0x7fffffff;
mCopied = false;
mKnownShortBranch = false;
mBypassed = false;
}
NativeCodeBasicBlock::~NativeCodeBasicBlock(void)
{
}
NativeCodeProcedure::NativeCodeProcedure(void)
: mRelocations({ 0 }), mBlocks(nullptr)
{
mTempBlocks = 1000;
}
NativeCodeProcedure::~NativeCodeProcedure(void)
{
}
void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure* 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 + 2;
mNoFrame = proc->mLocalSize == 0 && tempSave == 0 && proc->mLeafProcedure;
entryBlock = new NativeCodeBasicBlock();
mBlocks.Push(entryBlock);
entryBlock->mNoFrame = mNoFrame;
entryBlock->mIndex = 0;
generator->mByteCodeUsed[BC_NATIVE] = true;
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, BC_NATIVE * 2));
if (!mNoFrame)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, stackExpand & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, tempSave + 2));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
if (tempSave)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED - 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, - 8));
}
}
if (!proc->mLeafProcedure)
{
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (proc->mCommonFrameSize + 2) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ((proc->mCommonFrameSize + 2) >> 8) & 0xff));
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
tblocks[0] = entryBlock;
exitBlock = new NativeCodeBasicBlock();
exitBlock->mNoFrame = mNoFrame;
mBlocks.Push(exitBlock);
if (!proc->mLeafProcedure)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (proc->mCommonFrameSize + 2) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ((proc->mCommonFrameSize + 2) >> 8) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
if (!mNoFrame)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1));
if (tempSave)
{
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -8));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ABSOLUTE_Y, BC_REG_TMP_SAVED));
}
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, stackExpand & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
#if 1
bool changed;
do
{
BuildDataFlowSets();
ResetVisited();
changed = entryBlock->RemoveUnusedResultInstructions();
ResetVisited();
if (entryBlock->PeepHoleOptimizer())
changed = true;
ResetVisited();
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mNumEntries = 0;
entryBlock->CountEntries();
ResetVisited();
if (entryBlock->MergeBasicBlocks())
changed = true;
} while (changed);
#endif
entryBlock->Assemble();
int total, base;
NativeCodeBasicBlock* lentryBlock = entryBlock->BypassEmptyBlocks();
total = 0;
base = generator->mProgEnd;
lentryBlock->CalculateOffset(total);
generator->AddAddress(proc->mID, true, base, total, proc->mIdent, true);
lentryBlock->CopyCode(this, generator->mMemory + base);
generator->mProgEnd += total;
for (int i = 0; i < mRelocations.Size(); i++)
{
ByteCodeRelocation& rl(mRelocations[i]);
rl.mAddr += base;
generator->mRelocations.Push(rl);
}
}
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->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;
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;
}
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]->mSTemp[0] == ins->mTTemp &&
iblock->mInstructions[i + 1]->mSFinal[0] &&
iblock->mInstructions[i + 1]->mOperandSize == 1)
{
block->LoadStoreValue(iproc, ins, iblock->mInstructions[i + 1]);
i++;
}
else if (i + 1 < iblock->mInstructions.Size() &&
ins->mOperandSize >= 2 &&
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
iblock->mInstructions[i + 1]->mSTemp[0] == ins->mTTemp && iblock->mInstructions[i + 1]->mSFinal[0])
{
block->BinaryOperator(iproc, iblock->mInstructions[i + 1], nullptr, ins);
i++;
}
else if (i + 1 < iblock->mInstructions.Size() &&
ins->mOperandSize >= 2 &&
iblock->mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
iblock->mInstructions[i + 1]->mSTemp[1] == ins->mTTemp && iblock->mInstructions[i + 1]->mSFinal[1])
{
block->BinaryOperator(iproc, iblock->mInstructions[i + 1], ins, nullptr);
i++;
}
else if (i + 2 < iblock->mInstructions.Size() &&
ins->mOperandSize >= 2 &&
iblock->mInstructions[i + 1]->mCode == IC_LOAD && iblock->mInstructions[i + 1]->mOperandSize == 2 &&
iblock->mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR &&
iblock->mInstructions[i + 2]->mSTemp[0] == iblock->mInstructions[i + 1]->mTTemp && iblock->mInstructions[i + 2]->mSFinal[0] &&
iblock->mInstructions[i + 2]->mSTemp[1] == ins->mTTemp && iblock->mInstructions[i + 2]->mSFinal[1])
{
block->BinaryOperator(iproc, iblock->mInstructions[i + 2], ins, iblock->mInstructions[i + 1]);
i += 2;
}
else if (i + 2 < iblock->mInstructions.Size() &&
ins->mOperandSize >= 2 &&
iblock->mInstructions[i + 1]->mCode == IC_LOAD && iblock->mInstructions[i + 1]->mOperandSize == 2 &&
iblock->mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR &&
iblock->mInstructions[i + 2]->mSTemp[1] == iblock->mInstructions[i + 1]->mTTemp && iblock->mInstructions[i + 2]->mSFinal[1] &&
iblock->mInstructions[i + 2]->mSTemp[0] == ins->mTTemp && iblock->mInstructions[i + 2]->mSFinal[0])
{
block->BinaryOperator(iproc, iblock->mInstructions[i + 2], iblock->mInstructions[i + 1], ins);
i += 2;
}
else if (i + 1 < iblock->mInstructions.Size() &&
ins->mOperandSize >= 2 &&
iblock->mInstructions[i + 1]->mCode == IC_LEA &&
iblock->mInstructions[i + 1]->mSTemp[1] == ins->mTTemp && iblock->mInstructions[i + 1]->mSFinal[1])
{
block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], ins, nullptr);
i++;
}
else
block->LoadValue(iproc, ins);
break;
case IC_COPY:
block->CopyValue(iproc, ins, this);
break;
case IC_LOAD_TEMPORARY:
{
if (ins->mSTemp[0] != ins->mTTemp)
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]]));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mTTemp]));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]] + 1));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mTTemp] + 1));
}
} break;
case IC_BINARY_OPERATOR:
block->BinaryOperator(iproc, ins, nullptr, nullptr);
break;
case IC_UNARY_OPERATOR:
block->UnaryOperator(iproc, ins);
break;
case IC_CONVERSION_OPERATOR:
block->NumericConversion(iproc, 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, ins);
break;
case IC_JSR:
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->mIntValue + 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->mIntValue + 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->mIntValue + 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->mIntValue + 2) >> 8) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
} break;
case IC_RELATIONAL_OPERATOR:
if (iblock->mInstructions[i + 1]->mCode == IC_BRANCH)
{
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->mTTemp]));
if (InterTypeSize[ins->mTType] > 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->mTTemp] + 1));
}
block = rblock;
}
break;
case IC_RETURN_VALUE:
{
if (ins->mSTemp[0] < 0)
{
if (ins->mSType[0] == IT_FLOAT)
{
union { float f; unsigned int v; } cc;
cc.f = ins->mSFloatConst[0];
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->mSIntConst[0] & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSIntConst[0] >> 8) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
}
}
else
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]]));
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->mSTemp[0]] + 1));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
if (ins->mSType[0] == IT_FLOAT)
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]] + 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->mSTemp[0]] + 3));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
}
block->Close(exitBlock, nullptr, ASMIT_JMP);
return;
}
case IC_RETURN:
block->Close(exitBlock, nullptr, ASMIT_JMP);
return;
case IC_TYPECAST:
if (ins->mSTemp[0] != ins->mTTemp)
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]]));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mTTemp]));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]] + 1));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mTTemp] + 1));
}
break;
case IC_BRANCH:
if (ins->mSTemp[0] < 0)
{
if (ins->mSIntConst[0] == 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->mSTemp[0]]));
if (InterTypeSize[ins->mSType[0]] > 1)
block->mIns.Push(NativeCodeInstruction(ASMIT_ORA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSTemp[0]] + 1));
block->Close(CompileBlock(iproc, iblock->mTrueJump), CompileBlock(iproc, iblock->mFalseJump), ASMIT_BNE);
}
return;
}
i++;
}
block->Close(CompileBlock(iproc, iblock->mTrueJump), nullptr, ASMIT_JMP);
}