#include "ByteCodeGenerator.h"
#include "Assembler.h"

static const uint32 LIVE_ACCU = 0x00000001;


static const char* ByteCodeNames[] = {
	"NOP",
	"EXIT",

	"CONST_8",
	"CONST_P8",
	"CONST_N8",
	"CONST_16",
	"CONST_32",

	"LOAD_REG_8",
	"STORE_REG_8",
	"LOAD_REG_16",
	"STORE_REG_16",
	"ADDR_REG",
	"LOAD_REG_32",
	"STORE_REG_32",

	"LOAD_ABS_8",
	"LOAD_ABS_U8",
	"LOAD_ABS_16",
	"LOAD_ABS_32",
	"LOAD_ABS_ADDR", 

	"STORE_ABS_8",
	"STORE_ABS_16",
	"STORE_ABS_32",

	"LEA_ABS",
	"LEA_ABS_INDEX",
	"LEA_ABS_INDEX_U8",
	"LEA_ACCU_INDEX",

	"LOAD_LOCAL_8",
	"LOAD_LOCAL_U8",
	"LOAD_LOCAL_16",
	"LOAD_LOCAL_32",

	"STORE_LOCAL_8",
	"STORE_LOCAL_16",
	"STORE_LOCAL_32",

	"LEA_LOCAL",

	"STORE_FRAME_8",
	"STORE_FRAME_16",
	"STORE_FRAME_32",

	"LEA_FRAME",

	"LOAD_ADDR_8",
	"LOAD_ADDR_U8",
	"LOAD_ADDR_16",
	"LOAD_ADDR_32",

	"STORE_ADDR_8",
	"STORE_ADDR_16",
	"STORE_ADDR_32",

	"BINOP_ADDR_16",
	"BINOP_SUBR_16",
	"BINOP_ANDR_16",
	"BINOP_ORR_16",
	"BINOP_XORR_16",
	"BINOP_MULR_16",
	"BINOP_DIVR_U16",
	"BINOP_MODR_U16",
	"BINOP_DIVR_I16",
	"BINOP_MODR_I16",
	"BINOP_SHLR_16",
	"BINOP_SHRR_U16",
	"BINOP_SHRR_I16",

	"BINOP_ADDA_16",

	"BINOP_ADDI_16",
	"BINOP_SUBI_16",
	"BINOP_ANDI_16",
	"BINOP_ORI_16",
	"BINOP_MULI8_16",

	"BINOP_ADDI_8",
	"BINOP_ANDI_8",
	"BINOP_ORI_8",

	"BINOP_SHLI_16",
	"BINOP_SHRI_U16",
	"BINOP_SHRI_I16",

	"BINOP_CMPUR_16",
	"BINOP_CMPSR_16",

	"BINOP_CMPUI_16",
	"BINOP_CMPSI_16",

	"BINOP_CMPUR_8",
	"BINOP_CMPSR_8",

	"BINOP_CMPUI_8",
	"BINOP_CMPSI_8",

	"OP_NEGATE_16",
	"OP_INVERT_16",

	"BINOP_ADD_F32",
	"BINOP_SUB_F32",
	"BINOP_MUL_F32",
	"BINOP_DIV_F32",
	"BINOP_CMP_F32",
	"OP_NEGATE_F32",
	"OP_ABS_F32",
	"OP_FLOOR_F32",
	"OP_CEIL_F32",

	"CONV_U16_F32",
	"CONV_I16_F32",
	"CONV_F32_U16",
	"CONV_F32_I16",

	"CONV_I8_I16",

	"JUMPS",
	"BRANCHS_EQ",
	"BRANCHS_NE",
	"BRANCHS_GT",
	"BRANCHS_GE",
	"BRANCHS_LT",
	"BRANCHS_LE",

	"JUMPF",
	"BRANCHF_EQ",
	"BRANCHF_NE",
	"BRANCHF_GT",
	"BRANCHF_GE",
	"BRANCHF_LT",
	"BRANCHF_LE",

	"LOOP_U8",
	"MALLOC",
	"FREE",
	"FILL",
	"FILL_LONG",
	nullptr,

	"JSR",		//114

	nullptr,
	nullptr,

	"NATIVE",	//117

	"ENTER",
	"RETURN",
	"CALL_ADDR",
	"CALL_ABS",
	"PUSH_FRAME",
	"POP_FRAME",

	"COPY",
	"COPY_LONG",
	"STRCPY",

	"EXTRT"
};


static ByteCode		StoreTypedTmpCodes[] = {
	BC_NOP,
	BC_STORE_REG_8,
	BC_STORE_REG_8,
	BC_STORE_REG_16,
	BC_STORE_REG_32,
	BC_STORE_REG_32,
	BC_STORE_REG_16
};


static ByteCode InvertBranchCondition(ByteCode code)
{
	switch (code)
	{
	case BC_BRANCHS_EQ: return BC_BRANCHS_NE;
	case BC_BRANCHS_NE: return BC_BRANCHS_EQ;
	case BC_BRANCHS_GT: return BC_BRANCHS_LE;
	case BC_BRANCHS_GE: return BC_BRANCHS_LT;
	case BC_BRANCHS_LT: return BC_BRANCHS_GE;
	case BC_BRANCHS_LE: return BC_BRANCHS_GT;
	default:
		return code;
	}
}

static ByteCode TransposeBranchCondition(ByteCode code)
{
	switch (code)
	{
	case BC_BRANCHS_EQ: return BC_BRANCHS_EQ;
	case BC_BRANCHS_NE: return BC_BRANCHS_NE;
	case BC_BRANCHS_GT: return BC_BRANCHS_LT;
	case BC_BRANCHS_GE: return BC_BRANCHS_LE;
	case BC_BRANCHS_LT: return BC_BRANCHS_GT;
	case BC_BRANCHS_LE: return BC_BRANCHS_GE;
	default:
		return code;
	}
}

ByteCodeInstruction::ByteCodeInstruction(ByteCode code)
	: mCode(code), mRelocate(false), mRegisterFinal(false), mLinkerObject(nullptr), mValue(0), mRegister(0)
{
}


bool ByteCodeInstruction::IsStore(void) const
{
	return
		mCode == BC_STORE_ABS_8 ||
		mCode == BC_STORE_ABS_16 ||
		mCode == BC_STORE_ABS_32 ||
		mCode == BC_STORE_LOCAL_8 ||
		mCode == BC_STORE_LOCAL_16 ||
		mCode == BC_STORE_LOCAL_32 ||
		mCode == BC_STORE_FRAME_8 ||
		mCode == BC_STORE_FRAME_16 ||
		mCode == BC_STORE_FRAME_32 ||
		mCode == BC_STORE_ADDR_8 ||
		mCode == BC_STORE_ADDR_16 ||
		mCode == BC_STORE_ADDR_32;
}

bool ByteCodeInstruction::ChangesAccu(void) const
{
	return ChangesRegister(BC_REG_ACCU);
}

bool ByteCodeInstruction::UsesAccu(void) const
{
	return UsesRegister(BC_REG_ACCU);
}

bool ByteCodeInstruction::ChangesAddr(void) const
{
	return ChangesRegister(BC_REG_ADDR);
}

bool ByteCodeInstruction::UsesAddr(void) const
{
	return UsesRegister(BC_REG_ADDR);
}

bool ByteCodeInstruction::LoadsRegister(uint32 reg) const
{
	if (mRegister == reg)
	{
		if (mCode >= BC_LOAD_ABS_8 && mCode <= BC_LOAD_ABS_32)
			return true;
		if (mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32)
			return true;
		if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_LOAD_ADDR_32)
			return true;
		if (mCode >= BC_CONST_8 && mCode <= BC_CONST_32)
			return true;
		if (mCode == BC_LEA_ABS || mCode == BC_LEA_LOCAL || mCode == BC_LEA_FRAME)
			return true;
	}

	return false;
}

bool ByteCodeInstruction::IsCommutative(void) const
{
	if (mCode == BC_BINOP_ADDR_16 || mCode == BC_BINOP_ANDR_16 || mCode == BC_BINOP_ORR_16 || mCode == BC_BINOP_XORR_16 || mCode == BC_BINOP_MULR_16)
		return true;

	if (mCode == BC_BINOP_ADD_F32 || mCode == BC_BINOP_MUL_F32)
		return true;

	if (mCode == BC_BINOP_ADD_L32 || mCode == BC_BINOP_AND_L32 || mCode == BC_BINOP_OR_L32 || mCode == BC_BINOP_XOR_L32 || mCode == BC_BINOP_MUL_L32)
		return true;

	return false;
}

bool ByteCodeInstruction::IsLocalStore(void) const
{
	return mCode >= BC_STORE_LOCAL_8 && mCode <= BC_STORE_LOCAL_32;
}

bool ByteCodeInstruction::IsLocalLoad(void) const
{
	return mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32 || mCode == BC_COPY || mCode == BC_STRCPY;
}

bool ByteCodeInstruction::IsLocalAccess(void) const
{
	return IsLocalStore() || IsLocalLoad();
}

bool ByteCodeInstruction::IsShiftByRegister(void) const
{
	return
		mCode == BC_BINOP_SHLR_16 || mCode == BC_BINOP_SHRR_I16 || mCode == BC_BINOP_SHRR_U16 ||
		mCode == BC_BINOP_SHL_L32 || mCode == BC_BINOP_SHR_U32 || mCode == BC_BINOP_SHR_I32;
}


bool ByteCodeInstruction::IsIntegerConst(void) const
{
	return mCode >= BC_CONST_8 && mCode <= BC_CONST_32;
}

bool ByteCodeInstruction::IsCompare(void) const
{
	return mCode >= BC_BINOP_CMPUR_16 && mCode <= BC_BINOP_CMPSI_8 ||
		mCode == BC_BINOP_CMP_F32 || mCode == BC_BINOP_CMP_U32 || mCode == BC_BINOP_CMP_S32;
}


bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
{
	bool	changed = false;

	switch (mCode)
	{
	case BC_CONST_8:
	case BC_CONST_P8:
	case BC_CONST_N8:
	case BC_CONST_16:
	case BC_CONST_32:
		if (mRegister == BC_REG_ACCU)
			used = 0;
		break;

	case BC_LOAD_REG_8:
		if (mRegister != BC_REG_ACCU)
			used = 0;
		else if (!(used & 0xffffff00))
		{
			mCode = BC_NOP;
			changed = true;
		}
		else
			used = 0x000000ff;
		break;

	case BC_LOAD_REG_16:
		if (!(used & 0xffffff00))
		{
			mCode = BC_LOAD_REG_8;
			changed = true;
		}
		used = 0;
		break;

	case BC_LOAD_REG_32:
		if (!(used & 0xffffff00))
		{
			mCode = BC_LOAD_REG_8;
			changed = true;
		}
		else if (!(used & 0xffff0000))
		{
			mCode = BC_LOAD_REG_16;
			changed = true;
		}
		used = 0;
		break;

	case BC_STORE_REG_8:
		used |= 0x000000ff;
		break;

	case BC_STORE_ABS_8:
	case BC_STORE_LOCAL_8:
	case BC_STORE_FRAME_8:
	case BC_STORE_ADDR_8:
		if (mRegister == BC_REG_ACCU)
			used |= 0x000000ff;
		break;

	case BC_STORE_REG_16:
		used |= 0x0000ffff;
		break;

	case BC_STORE_ABS_16:
	case BC_STORE_LOCAL_16:
	case BC_STORE_FRAME_16:
	case BC_STORE_ADDR_16:
		if (mRegister == BC_REG_ACCU)
			used |= 0x0000ffff;
		break;

	case BC_STORE_REG_32:
		used = 0xffffffff;
		break;

	case BC_STORE_ABS_32:
	case BC_STORE_LOCAL_32:
	case BC_STORE_FRAME_32:
	case BC_STORE_ADDR_32:
		if (mRegister == BC_REG_ACCU)
			used = 0xffffffff;
		break;

	case BC_LOAD_ABS_8:
	case BC_LOAD_ABS_U8:
		if (mRegister == BC_REG_ACCU)
			used = 0;
		break;
	case BC_LOAD_ABS_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_ABS_8;
				changed = true;
			}
			used = 0;
		}
		break;
	case BC_LOAD_ABS_32:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_ABS_8;
				changed = true;
			}
			else if (!(used & 0xffff0000))
			{
				mCode = BC_LOAD_ABS_16;
				changed = true;
			}
			used = 0;
		}
		break;

	case BC_LOAD_ABS_ADDR:
		break;

	case BC_LEA_ABS:
	case BC_LEA_LOCAL:
	case BC_LEA_FRAME:
		if (mRegister == BC_REG_ACCU)
			used = 0;
		break;

	case BC_LEA_ABS_INDEX:
	case BC_LEA_ABS_INDEX_U8:
	case BC_ADDR_REG:
		if (mRegister == BC_REG_ACCU)
			used |= 0x0000ffff;
		break;

	case BC_LEA_ACCU_INDEX:
		used |= 0x0000ffff;
		break;

	case BC_LOAD_LOCAL_8:
	case BC_LOAD_LOCAL_U8:
		if (mRegister == BC_REG_ACCU)
			used = 0;
		break;
	case BC_LOAD_LOCAL_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_LOCAL_8;
				changed = true;
			}
			used = 0;
		}
		break;
	case BC_LOAD_LOCAL_32:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_LOCAL_8;
				changed = true;
			}
			else if (!(used & 0xffff0000))
			{
				mCode = BC_LOAD_LOCAL_16;
				changed = true;
			}
			used = 0;
		}
		break;

	case BC_LOAD_ADDR_8:
	case BC_LOAD_ADDR_U8:
		if (mRegister == BC_REG_ACCU)
			used = 0;
		break;
	case BC_LOAD_ADDR_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_ADDR_8;
				changed = true;
			}
			used = 0;
		}
		break;
	case BC_LOAD_ADDR_32:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_LOAD_ADDR_8;
				changed = true;
			}
			else if (!(used & 0xffff0000))
			{
				mCode = BC_LOAD_ADDR_16;
				changed = true;
			}
			used = 0;
		}
		break;

	case BC_BINOP_ADDR_16:
	case BC_BINOP_SUBR_16:
	case BC_BINOP_ANDR_16:
	case BC_BINOP_ORR_16:
	case BC_BINOP_XORR_16:
	case BC_BINOP_MULR_16:
	case BC_BINOP_SUBI_16:
	case BC_BINOP_MULI8_16:
	case BC_BINOP_SHLR_16:
	case BC_BINOP_ADDI_8:
	case BC_BINOP_ANDI_8:
	case BC_BINOP_ORI_8:
	case BC_BINOP_SHLI_16:
	case BC_OP_NEGATE_16:
	case BC_OP_INVERT_16:
		break;

	case BC_BINOP_CMPUR_16:
	case BC_BINOP_CMPSR_16:
	case BC_BINOP_CMPUI_16:
	case BC_BINOP_CMPSI_16:

	case BC_BINOP_DIVR_U16:
	case BC_BINOP_MODR_U16:
	case BC_BINOP_DIVR_I16:
	case BC_BINOP_MODR_I16:
	case BC_BINOP_SHRR_U16:
	case BC_BINOP_SHRR_I16:
	case BC_BINOP_SHRI_U16:
	case BC_BINOP_SHRI_I16:
		used |= 0x0000ffff;
		break;

	case BC_LOOP_U8:
		used = 0;
		break;

	case BC_MALLOC:
	case BC_FREE:
		used = 0x0000ffff;
		break;

	case BC_BINOP_ADDA_16:
		used |= 0x0000ffff;
		break;

	case BC_BINOP_ADDI_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_BINOP_ADDI_8;
				changed = true;
			}
		}
		break;
	case BC_BINOP_ANDI_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_BINOP_ANDI_8;
				changed = true;
			}
		}
		break;
	case BC_BINOP_ORI_16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_BINOP_ORI_8;
				changed = true;
			}
		}
		break;

	case BC_BINOP_CMPUR_8:
	case BC_BINOP_CMPSR_8:
	case BC_BINOP_CMPUI_8:
	case BC_BINOP_CMPSI_8:
		used = 0x000000ff;
		break;

	case BC_BINOP_ADD_F32:
	case BC_BINOP_SUB_F32:
	case BC_BINOP_MUL_F32:
	case BC_BINOP_DIV_F32:
	case BC_BINOP_CMP_F32:
	case BC_OP_NEGATE_F32:
	case BC_OP_ABS_F32:
	case BC_OP_FLOOR_F32:
	case BC_OP_CEIL_F32:
	case BC_CONV_F32_U16:
	case BC_CONV_F32_I16:
	case BC_CONV_U32_F32:
	case BC_CONV_I32_F32:
	case BC_CONV_F32_U32:
	case BC_CONV_F32_I32:
		used = 0xffffffff;
		break;

	case BC_CONV_U16_F32:
	case BC_CONV_I16_F32:
	case BC_BRANCHS_EQ:
	case BC_BRANCHS_NE:
	case BC_BRANCHS_GT:
	case BC_BRANCHS_GE:
	case BC_BRANCHS_LT:
	case BC_BRANCHS_LE:
	case BC_BRANCHF_EQ:
	case BC_BRANCHF_NE:
	case BC_BRANCHF_GT:
	case BC_BRANCHF_GE:
	case BC_BRANCHF_LT:
	case BC_BRANCHF_LE:
	case BC_CONV_I16_I32:
	case BC_CONV_U16_U32:
		used = 0x0000ffff;
		break;

	case BC_CONV_I8_I16:
		if (mRegister == BC_REG_ACCU)
		{
			if (!(used & 0xffffff00))
			{
				mCode = BC_NOP;
				changed = true;
			}
			else
				used = 0x000000ff;
		}
		break;

	case BC_BINOP_ADD_L32:
	case BC_BINOP_SUB_L32:
	case BC_BINOP_AND_L32:
	case BC_BINOP_OR_L32:
	case BC_BINOP_XOR_L32:
	case BC_BINOP_MUL_L32:
	case BC_BINOP_DIV_U32:
	case BC_BINOP_MOD_U32:
	case BC_BINOP_DIV_I32:
	case BC_BINOP_MOD_I32:
	case BC_BINOP_SHL_L32:
	case BC_BINOP_SHR_U32:
	case BC_BINOP_SHR_I32:
	case BC_BINOP_CMP_U32:
	case BC_BINOP_CMP_S32:
		used = 0xffffffff;
		break;
		
	case BC_RETURN:
		used = 0xffffffff;
		break;

	case BC_FILL:
	case BC_FILL_LONG:
	case BC_COPY:
	case BC_COPY_LONG:
	case BC_STRCPY:
		used = 0x0000ffff;
		break;

	default:
		break;
	}

	return changed;
}


bool ByteCodeInstruction::IsSame(const ByteCodeInstruction& ins) const
{
	if (mCode == ins.mCode && mValue == ins.mValue && mRegister == ins.mRegister && mLinkerObject == ins.mLinkerObject)
	{
		return true;
	}

	return false;
}

bool ByteCodeInstruction::StoresRegister(uint32 reg) const
{
	if (mRegister == reg)
	{
		if (mCode >= BC_STORE_ABS_8 && mCode <= BC_STORE_ABS_32)
			return true;
		if (mCode >= BC_STORE_LOCAL_8 && mCode <= BC_STORE_LOCAL_32)
			return true;
		if (mCode >= BC_STORE_FRAME_8 && mCode <= BC_STORE_FRAME_32)
			return true;
		if (mCode >= BC_STORE_ADDR_8 && mCode <= BC_STORE_ADDR_32)
			return true;
	}

	return false;

}

bool ByteCodeInstruction::UsesRegister(uint32 reg) const
{
	if (StoresRegister(reg))
		return true;

	if (mRegister == reg)
	{
		if (mCode == BC_LOAD_REG_8 || mCode == BC_LOAD_REG_16 || mCode == BC_LOAD_REG_32 || mCode == BC_ADDR_REG || mCode == BC_LEA_ABS_INDEX || mCode == BC_LEA_ABS_INDEX_U8 || mCode == BC_LEA_ACCU_INDEX)
			return true;

		if (mCode >= BC_BINOP_ADDI_16 && mCode <= BC_BINOP_ORI_8)
			return true;

		if (mCode >= BC_BINOP_ADDR_16 && mCode <= BC_BINOP_SHRR_I16)
			return true;

		if (mCode == BC_BINOP_CMPUR_16 || mCode == BC_BINOP_CMPSR_16)
			return true;

		if (mCode == BC_BINOP_CMPUR_8 || mCode == BC_BINOP_CMPSR_8)
			return true;

		if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_BINOP_CMP_F32)
			return true;

		if (mCode >= BC_BINOP_ADD_L32 && mCode <= BC_BINOP_CMP_S32)
			return true;

		if (mCode == BC_BINOP_ADDA_16)
			return true;

		if (mCode == BC_LOOP_U8)
			return true;
	}

	if (reg == BC_REG_ACCU)
	{
		if (mCode == BC_STORE_REG_8 || mCode == BC_STORE_REG_16 || mCode == BC_STORE_REG_32)
			return true;

		if (mCode >= BC_BINOP_ADDR_16 && mCode <= BC_BINOP_SHRR_I16)
			return true;
		if (mCode >= BC_BINOP_CMPUR_16 && mCode <= BC_BINOP_CMPSI_16)
			return true;
		if (mCode >= BC_BINOP_CMPUR_8 && mCode <= BC_BINOP_CMPSI_8)
			return true;
		if (mCode >= BC_OP_NEGATE_16 && mCode <= BC_OP_INVERT_16)
			return true;
		if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_OP_CEIL_F32)
			return true;
		if (mCode >= BC_CONV_U16_F32 && mCode <= BC_CONV_F32_I16)
			return true;
		if (mCode >= BC_BINOP_SHLI_16 && mCode <= BC_BINOP_SHRI_I16)
			return true;
		if (mCode >= BC_CONV_I16_I32 && mCode <= BC_BINOP_CMP_S32)
			return true;
		if (mCode == BC_LEA_ACCU_INDEX)
			return true;
		if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
			return true;
		if (mCode == BC_BINOP_ADDA_16)
			return true;
		if (mCode == BC_MALLOC || mCode == BC_FREE)
			return true;
	}

	if (reg == BC_REG_ADDR)
	{
		if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_STORE_ADDR_32)
			return true;

		if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
			return true;

		if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
			return true;
	}

	return false;
}


bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
{
	if (mRegister == reg)
	{
		if (mCode == BC_STORE_REG_8 || mCode == BC_STORE_REG_16 || mCode == BC_STORE_REG_32)
			return true;
		if (mCode >= BC_LOAD_ABS_8 && mCode <= BC_LOAD_ABS_32)
			return true;
		if (mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32)
			return true;
		if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_LOAD_ADDR_32)
			return true;
		if (mCode >= BC_CONST_8 && mCode <= BC_CONST_32)
			return true;
		if (mCode == BC_LEA_ABS || mCode == BC_LEA_LOCAL || mCode == BC_LEA_FRAME)
			return true;
		if (mCode >= BC_BINOP_ADDI_16 && mCode <= BC_BINOP_ORI_8)
			return true;
		if (mCode == BC_BINOP_ADDA_16)
			return true;
		if (mCode == BC_LOOP_U8)
			return true;
	}

	if (reg >= BC_REG_WORK && reg < BC_REG_FPARAMS_END || reg >= BC_REG_TMP && reg < BC_REG_TMP_SAVED)
	{
		if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
			return true;
	}

	if (reg == BC_REG_ACCU)
	{
		if (mCode == BC_LOAD_REG_8 || mCode == BC_LOAD_REG_16 || mCode == BC_LOAD_REG_32)
			return true;
		if (mCode >= BC_BINOP_ADDR_16 && mCode <= BC_BINOP_SHRR_I16)
			return true;
		if (mCode >= BC_BINOP_CMPUR_16 && mCode <= BC_BINOP_CMPSI_16)
			return true;
		if (mCode >= BC_BINOP_CMPUR_8 && mCode <= BC_BINOP_CMPSI_8)
			return true;
		if (mCode >= BC_OP_NEGATE_16 && mCode <= BC_OP_INVERT_16)
			return true;
		if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_OP_CEIL_F32)
			return true;
		if (mCode >= BC_CONV_U16_F32 && mCode <= BC_CONV_F32_I16)
			return true;
		if (mCode >= BC_BINOP_SHLI_16 && mCode <= BC_BINOP_SHRI_I16)
			return true;
		if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
			return true;
		if (mCode >= BC_CONV_I16_I32 && mCode <= BC_BINOP_CMP_S32)
			return true;
		if (mCode == BC_LOOP_U8)
			return true;
		if (mCode == BC_MALLOC || mCode == BC_FREE)
			return true;
	}

	if (reg == BC_REG_ADDR)
	{
		if (mCode == BC_ADDR_REG)
			return true;
		if (mCode >= BC_LOAD_ABS_8 && mCode <= BC_STORE_ABS_32)
			return true;
		if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
			return true;
		if (mCode == BC_LEA_ABS_INDEX || mCode == BC_LEA_ABS_INDEX_U8 || mCode == BC_LEA_ACCU_INDEX)
			return true;
	}

	if (reg == BC_REG_WORK)
	{
		if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
			return true;
		if (mCode == BC_MALLOC || mCode == BC_FREE)
			return true;

		if (mCode == BC_BINOP_DIVR_I16 || mCode == BC_BINOP_DIVR_U16 || mCode == BC_BINOP_MODR_I16 || mCode == BC_BINOP_MODR_U16 ||
			mCode == BC_BINOP_DIV_I32 || mCode == BC_BINOP_DIV_U32 || mCode == BC_BINOP_MOD_I32 || mCode == BC_BINOP_MOD_U32 ||
			mCode == BC_BINOP_MULR_16 || mCode == BC_BINOP_MULI8_16 || mCode == BC_BINOP_MUL_L32)
			return true;

		if (mCode >= BC_BINOP_ADD_F32 && mCode <= BC_OP_CEIL_F32)
			return true;
		if (mCode >= BC_CONV_U16_F32 && mCode <= BC_CONV_F32_I16)
			return true;
	}

	return false;
}

void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBlock* block)
{
	switch (mCode)
	{
	case BC_NOP:
		break;
	case BC_EXIT:
		block->PutCode(generator, mCode);
		break;

	case BC_CONST_8:
		block->PutCode(generator, BC_CONST_8); block->PutByte(mRegister); block->PutByte(uint8(mValue));
		break;
	case BC_CONST_P8:
	case BC_CONST_N8:
	case BC_CONST_16:
		if (mRelocate)
		{
			block->PutCode(generator, mCode);
			block->PutByte(mRegister);

			LinkerReference	rl;
			rl.mOffset = block->mCode.Size();
			rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
			rl.mRefObject = mLinkerObject;
			rl.mRefOffset = mValue;
			block->mRelocations.Push(rl);

			block->PutWord(0);
		}
		else if (mValue >= 0 && mValue < 256)
		{
			block->PutCode(generator, BC_CONST_P8); block->PutByte(mRegister); block->PutByte(uint8(mValue));
		}
		else if (mValue < 0 && mValue >= -256)
		{
			block->PutCode(generator, BC_CONST_N8); block->PutByte(mRegister); block->PutByte(uint8(mValue));
		}
		else
		{
			block->PutCode(generator, BC_CONST_16); block->PutByte(mRegister); block->PutWord(uint16(mValue));
		}
		break;
	case BC_CONST_32:
		block->PutCode(generator, BC_CONST_32); block->PutByte(mRegister); block->PutDWord(uint32(mValue));
		break;

	case BC_LOAD_REG_8:
	case BC_STORE_REG_8:
	case BC_LOAD_REG_16:
	case BC_STORE_REG_16:
	case BC_LOAD_REG_32:
	case BC_STORE_REG_32:
	case BC_ADDR_REG:
		block->PutCode(generator, mCode); 
		block->PutByte(mRegister);
		break;

	case BC_LOAD_ABS_8:
	case BC_LOAD_ABS_U8:
	case BC_LOAD_ABS_16:
	case BC_LOAD_ABS_32:
	case BC_STORE_ABS_8:
	case BC_STORE_ABS_16:
	case BC_STORE_ABS_32:
		block->PutCode(generator, mCode);
		if (mRelocate)
		{
			LinkerReference	rl;
			rl.mOffset = block->mCode.Size();
			rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
			rl.mRefObject = mLinkerObject;
			rl.mRefOffset = mValue;
			block->mRelocations.Push(rl);
			block->PutWord(0);
		}
		else
			block->PutWord(mValue);

		block->PutByte(mRegister);
		break;

	case BC_LOAD_ABS_ADDR:
		block->PutCode(generator, mCode);
		if (mRelocate)
		{
			LinkerReference	rl;
			rl.mOffset = block->mCode.Size();
			rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
			rl.mRefObject = mLinkerObject;
			rl.mRefOffset = mValue;
			block->mRelocations.Push(rl);
			block->PutWord(0);
		}
		else
			block->PutWord(mValue);
		break;

	case BC_LEA_ABS:
	case BC_LEA_ABS_INDEX:
	case BC_LEA_ABS_INDEX_U8:
		block->PutCode(generator, mCode); block->PutByte(mRegister);
		if (mRelocate)
		{
			LinkerReference	rl;
			rl.mOffset = block->mCode.Size();
			rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
			rl.mRefObject = mLinkerObject;
			rl.mRefOffset = mValue;
			block->mRelocations.Push(rl);
			block->PutWord(0);
		}
		else
			block->PutWord(uint16(mValue));
		break;

	case BC_LOAD_LOCAL_8:
	case BC_LOAD_LOCAL_U8:
	case BC_LOAD_LOCAL_16:
	case BC_LOAD_LOCAL_32:
	case BC_STORE_LOCAL_8:
	case BC_STORE_LOCAL_16:
	case BC_STORE_LOCAL_32:
	case BC_STORE_FRAME_8:
	case BC_STORE_FRAME_16:
	case BC_STORE_FRAME_32:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister); 
		block->PutByte(uint8(mValue));
		break;

	case BC_LEA_LOCAL:
	case BC_LEA_FRAME:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister); 
		block->PutWord(uint16(mValue));
		break;

	case BC_LEA_ACCU_INDEX:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		break;

	case BC_BINOP_ADDR_16:
	case BC_BINOP_SUBR_16:
	case BC_BINOP_ANDR_16:
	case BC_BINOP_ORR_16:
	case BC_BINOP_XORR_16:
	case BC_BINOP_MULR_16:
	case BC_BINOP_DIVR_U16:
	case BC_BINOP_MODR_U16:
	case BC_BINOP_DIVR_I16:
	case BC_BINOP_MODR_I16:
	case BC_BINOP_SHLR_16:
	case BC_BINOP_SHRR_U16:
	case BC_BINOP_SHRR_I16:
	case BC_BINOP_ADDA_16:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		break;

	case BC_BINOP_ADDI_16:
	case BC_BINOP_SUBI_16:
	case BC_BINOP_ANDI_16:
	case BC_BINOP_ORI_16:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister); 
		block->PutWord(uint16(mValue));
		break;
	case BC_BINOP_MULI8_16:
	case BC_BINOP_ADDI_8:
	case BC_BINOP_ANDI_8:
	case BC_BINOP_ORI_8:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		block->PutByte(mValue);
		break;
	case BC_BINOP_SHLI_16:
	case BC_BINOP_SHRI_U16:
	case BC_BINOP_SHRI_I16:
		block->PutCode(generator, mCode);
		block->PutByte(uint8(mValue));
		break;

	case BC_BINOP_CMPUR_16:
	case BC_BINOP_CMPSR_16:
	case BC_BINOP_CMPUR_8:
	case BC_BINOP_CMPSR_8:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		break;

	case BC_BINOP_CMPUI_16:
	case BC_BINOP_CMPSI_16:
		block->PutCode(generator, mCode);
		block->PutWord(uint16(mValue));
		break;

	case BC_BINOP_CMPUI_8:
	case BC_BINOP_CMPSI_8:
		block->PutCode(generator, mCode);
		block->PutByte(uint8(mValue));
		break;

	case BC_LOOP_U8:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		block->PutByte(uint8(mValue));
		break;

	case BC_OP_NEGATE_16:
	case BC_OP_INVERT_16:
		block->PutCode(generator, mCode);
		break;

	case BC_BINOP_ADD_F32:
	case BC_BINOP_SUB_F32:
	case BC_BINOP_MUL_F32:
	case BC_BINOP_DIV_F32:
	case BC_BINOP_CMP_F32:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		break;

	case BC_OP_NEGATE_F32:
	case BC_OP_ABS_F32:
	case BC_OP_FLOOR_F32:
	case BC_OP_CEIL_F32:
	case BC_CONV_U16_F32:
	case BC_CONV_I16_F32:
	case BC_CONV_F32_U16:
	case BC_CONV_F32_I16:
		block->PutCode(generator, mCode);
		break;

	case BC_CONV_I8_I16:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		break;

	case BC_JUMPS:
	case BC_BRANCHS_EQ:
	case BC_BRANCHS_NE:
	case BC_BRANCHS_GT:
	case BC_BRANCHS_GE:
	case BC_BRANCHS_LT:
	case BC_BRANCHS_LE:
		assert(false);
		break;

	case BC_JUMPF:
	case BC_BRANCHF_EQ:
	case BC_BRANCHF_NE:
	case BC_BRANCHF_GT:
	case BC_BRANCHF_GE:
	case BC_BRANCHF_LT:
	case BC_BRANCHF_LE:
		assert(false);
		break;

	case BC_ENTER:
	case BC_RETURN:
		assert(false);
		break;

	case BC_MALLOC:
	case BC_FREE:
	case BC_CALL_ADDR:
		block->PutCode(generator, mCode);
		break;

	case BC_CALL_ABS:
	{
		block->PutCode(generator, mCode);
		
		LinkerReference	rl;
		rl.mOffset = block->mCode.Size();
		rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
		rl.mRefObject = mLinkerObject;
		rl.mRefOffset = 0;
		block->mRelocations.Push(rl);

		block->PutWord(0);
	}	break;

	case BC_PUSH_FRAME:
	case BC_POP_FRAME:
		block->PutCode(generator, mCode);
		block->PutWord(uint16(mValue + 2));
		break;

	case BC_JSR:
	{
		block->PutCode(generator, mCode);

		LinkerReference	rl;
		rl.mOffset = block->mCode.Size();
		rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
		rl.mRefObject = mLinkerObject;
		rl.mRefOffset = 0;
		block->mRelocations.Push(rl);

		block->PutWord(0);
	}	break;

	case BC_LOAD_ADDR_8:
	case BC_LOAD_ADDR_U8:
	case BC_LOAD_ADDR_16:
	case BC_LOAD_ADDR_32:
	case BC_STORE_ADDR_8:
	case BC_STORE_ADDR_16:
	case BC_STORE_ADDR_32:
		block->PutCode(generator, mCode);
		block->PutByte(mRegister);
		block->PutByte(mValue);
		break;

	case BC_FILL:
	case BC_FILL_LONG:
		if (mValue < 256)
		{
			block->PutCode(generator, BC_FILL);
			block->PutByte(uint8(mValue));
		}
		else
		{
			block->PutCode(generator, BC_FILL_LONG);
			block->PutWord(uint16(mValue));
		}
		break;

	case BC_COPY:
	case BC_COPY_LONG:
		if (mValue < 256)
		{
			block->PutCode(generator, BC_COPY);
			block->PutByte(uint8(mValue));
		}
		else
		{
			block->PutCode(generator, BC_COPY_LONG);
			block->PutWord(uint16(mValue));
		}
		break;

	case BC_STRCPY:
		block->PutCode(generator, BC_STRCPY);
		break;

	case BC_CONV_I16_I32:
	case BC_CONV_U16_U32:
	case BC_OP_NEGATE_32:
	case BC_OP_INVERT_32:
	case BC_BINOP_ADD_L32:
	case BC_BINOP_SUB_L32:
	case BC_BINOP_AND_L32:
	case BC_BINOP_OR_L32:
	case BC_BINOP_XOR_L32:
	case BC_BINOP_MUL_L32:
	case BC_BINOP_DIV_U32:
	case BC_BINOP_MOD_U32:
	case BC_BINOP_DIV_I32:
	case BC_BINOP_MOD_I32:
	case BC_BINOP_SHL_L32:
	case BC_BINOP_SHR_U32:
	case BC_BINOP_SHR_I32:
	case BC_BINOP_CMP_U32:
	case BC_BINOP_CMP_S32:
		{
		block->PutCode(generator, BC_EXTRT);

		LinkerReference	rl;
		rl.mOffset = block->mCode.Size();
		rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
		rl.mRefObject = generator->mExtByteCodes[mCode - 128];
		rl.mRefOffset = 0;
		block->mRelocations.Push(rl);
		block->PutWord(0);
		block->PutByte(mRegister);
		break;
	}
	case BC_CONV_U32_F32:
	case BC_CONV_I32_F32:
	case BC_CONV_F32_U32:
	case BC_CONV_F32_I32:
	{
		block->PutCode(generator, BC_EXTRT);

		LinkerReference	rl;
		rl.mOffset = block->mCode.Size();
		rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
		rl.mRefObject = generator->mExtByteCodes[mCode - 128];
		rl.mRefOffset = 0;
		block->mRelocations.Push(rl);
		block->PutWord(0);
		block->PutByte(mRegister);
		break;
	}

	default:
		assert(false);
	}
}


void ByteCodeBasicBlock::PutByte(uint8 code)
{
	this->mCode.Insert(code);
}

void ByteCodeBasicBlock::PutWord(uint16 code)
{
	this->mCode.Insert((uint8)(code & 0xff));
	this->mCode.Insert((uint8)(code >> 8));
}

void ByteCodeBasicBlock::PutDWord(uint32 code)
{
	this->mCode.Insert((uint8)(code & 0xff));
	this->mCode.Insert((uint8)((code >> 8) & 0xff));
	this->mCode.Insert((uint8)((code >> 16) & 0xff));
	this->mCode.Insert((uint8)((code >> 24) & 0xff));
}

void ByteCodeBasicBlock::PutBytes(const uint8* code, int num)
{
	while (num--)
	{
		this->mCode.Insert(*code++);
	}
}

void ByteCodeBasicBlock::PutCode(ByteCodeGenerator* generator, ByteCode code)
{
	PutByte(uint8(code) * 2);
	generator->mByteCodeUsed[code]++;
}

int ByteCodeBasicBlock::PutBranch(ByteCodeGenerator* generator, ByteCode code, int offset)
{
	if (offset >= -126 && offset <= 129)
	{
		PutCode(generator, code);
		PutByte(offset - 2);
		return 2;
	}
	else
	{
		PutCode(generator, ByteCode(code + (BC_JUMPF - BC_JUMPS)));
		PutWord(offset - 3);
		return 3;
	}
}

ByteCodeBasicBlock::ByteCodeBasicBlock(void)
	: mRelocations({ 0 }), mIns(ByteCodeInstruction(BC_NOP)), mEntryBlocks(nullptr)
{
	mTrueJump = mFalseJump = NULL;
	mTrueLink = mFalseLink = NULL;
	mOffset = -1;
	mPlaced = false;
	mAssembled = false;
	mBypassed = false;
	mExitLive = 0;
}

void ByteCodeBasicBlock::IntConstToAccu(int64 val)
{
	ByteCodeInstruction	ins(BC_CONST_16);
	ins.mRegister = BC_REG_ACCU;
	ins.mValue = int(val);
	mIns.Push(ins);
}

void ByteCodeBasicBlock::LongConstToAccu(int64 val)
{
	ByteCodeInstruction	bins(BC_CONST_32);
	bins.mRegister = BC_REG_ACCU;
	bins.mValue = int(val);
	mIns.Push(bins);
}

void ByteCodeBasicBlock::LongConstToWork(int64 val)
{
	ByteCodeInstruction	bins(BC_CONST_32);
	bins.mRegister = BC_REG_WORK;
	bins.mValue = int(val);
	mIns.Push(bins);
}

void ByteCodeBasicBlock::FloatConstToAccu(double val)
{
	union { float f; int v; } cc;
	cc.f = float(val);
	ByteCodeInstruction	bins(BC_CONST_32);
	bins.mRegister = BC_REG_ACCU;
	bins.mValue = cc.v;
	mIns.Push(bins);
}

void ByteCodeBasicBlock::FloatConstToWork(double val)
{
	union { float f; int v; } cc;
	cc.f = float(val);
	ByteCodeInstruction	bins(BC_CONST_32);
	bins.mRegister = BC_REG_WORK;
	bins.mValue = cc.v;
	mIns.Push(bins);
}


void ByteCodeBasicBlock::IntConstToAddr(int64 val)
{
	ByteCodeInstruction	ins(BC_CONST_16);
	ins.mRegister = BC_REG_ADDR;
	ins.mValue = int(val);
	mIns.Push(ins);
}

void ByteCodeBasicBlock::LoadOperandAddress(InterCodeProcedure* proc, const InterOperand& op, int reg)
{
	if (op.mTemp < 0)
	{
		if (op.mMemory == IM_GLOBAL)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = reg;
			bins.mLinkerObject = op.mLinkerObject;
			bins.mValue = int(op.mIntConst);
			bins.mRelocate = true;
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_ABSOLUTE)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = reg;
			bins.mValue = int(op.mIntConst);
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_LOCAL)
		{
			ByteCodeInstruction	bins(BC_LEA_LOCAL);
			bins.mRegister = reg;
			bins.mValue = int(op.mIntConst + proc->mLocalVars[op.mVarIndex]->mOffset);
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_PARAM)
		{
			ByteCodeInstruction	bins(BC_LEA_LOCAL);
			bins.mRegister = reg;
			bins.mValue = int(op.mIntConst + op.mVarIndex + proc->mLocalSize + 2);
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_FPARAM || op.mMemory == IM_FFRAME)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = reg;
			bins.mValue = int(BC_REG_FPARAMS + op.mIntConst + op.mVarIndex);
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_FRAME)
		{
			ByteCodeInstruction	bins(BC_LEA_FRAME);
			bins.mRegister = reg;
			bins.mValue = int(op.mVarIndex + op.mIntConst + 2);
			mIns.Push(bins);
		}
		else if (op.mMemory == IM_PROCEDURE)
		{
			ByteCodeInstruction	bins(BC_CONST_16);
			bins.mRegister = reg;
			bins.mLinkerObject = op.mLinkerObject;
			bins.mValue = 0;
			bins.mRelocate = true;
			mIns.Push(bins);
		}
	}
	else if (reg == BC_REG_ADDR)
	{
		if (op.mIntConst == 0)
		{
			ByteCodeInstruction	sins(BC_ADDR_REG);
			sins.mRegister = BC_REG_TMP + proc->mTempOffset[op.mTemp];
			sins.mRegisterFinal = op.mFinal;
			mIns.Push(sins);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[op.mTemp];
			lins.mRegisterFinal = op.mFinal;
			lins.mValue = int(op.mIntConst);
			mIns.Push(lins);
		}
	}
	else if (reg == BC_REG_ACCU)
	{
		ByteCodeInstruction	dins(BC_LOAD_REG_16);
		dins.mRegister = BC_REG_TMP + proc->mTempOffset[op.mTemp];
		dins.mRegisterFinal = op.mFinal;
		mIns.Push(dins);
		if (op.mIntConst)
		{
			ByteCodeInstruction	iins(BC_BINOP_ADDI_16);
			iins.mRegister = BC_REG_ACCU;
			iins.mValue = int(op.mIntConst);
			mIns.Push(iins);
		}

	}
}

void ByteCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mDst.mType == IT_FLOAT)
	{
		union { float f; int v; } cc;
		cc.f = float(ins->mConst.mFloatConst);
		ByteCodeInstruction	bins(BC_CONST_32);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		bins.mValue = cc.v;
		mIns.Push(bins);
	}
	else if (ins->mDst.mType == IT_POINTER)
	{
		if (ins->mConst.mMemory == IM_GLOBAL)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mLinkerObject = ins->mConst.mLinkerObject;
			bins.mValue = int(ins->mConst.mIntConst);
			bins.mRelocate = true;
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_ABSOLUTE)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(ins->mConst.mIntConst);
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_LOCAL)
		{
			ByteCodeInstruction	bins(BC_LEA_LOCAL);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(ins->mConst.mIntConst + proc->mLocalVars[ins->mConst.mVarIndex]->mOffset);
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_PARAM)
		{
			ByteCodeInstruction	bins(BC_LEA_LOCAL);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(ins->mConst.mIntConst + ins->mConst.mVarIndex + proc->mLocalSize + 2);
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_FFRAME)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(BC_REG_FPARAMS + ins->mConst.mIntConst + ins->mConst.mVarIndex);
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_FRAME)
		{
			ByteCodeInstruction	bins(BC_LEA_FRAME);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(ins->mConst.mVarIndex + ins->mSrc[1].mIntConst + 2);
			mIns.Push(bins);
		}
		else if (ins->mConst.mMemory == IM_PROCEDURE)
		{
			ByteCodeInstruction	bins(BC_CONST_16);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mLinkerObject = ins->mConst.mLinkerObject;
			bins.mValue = 0;
			bins.mRelocate = true;
			mIns.Push(bins);
		}
	}
	else if (ins->mDst.mType == IT_BOOL || ins->mDst.mType == IT_INT8)
	{
		ByteCodeInstruction	bins(BC_CONST_8);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		bins.mValue = int(ins->mConst.mIntConst);
		mIns.Push(bins);
	}
	else if (ins->mDst.mType == IT_INT32)
	{
		ByteCodeInstruction	bins(BC_CONST_32);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		bins.mValue = int(ins->mConst.mIntConst);
		mIns.Push(bins);
	}
	else
	{
		ByteCodeInstruction	bins(BC_CONST_16);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		bins.mValue = int(ins->mConst.mIntConst);
		mIns.Push(bins);
	}

}

void ByteCodeBasicBlock::FillValue(InterCodeProcedure* proc, const InterInstruction* ins)
{
	LoadOperandAddress(proc, ins->mSrc[1], BC_REG_ADDR);

	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	cins(BC_CONST_8);
		cins.mRegister = BC_REG_ACCU;
		cins.mValue = int(ins->mSrc[0].mIntConst);
		mIns.Push(cins);
	}
	else
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_8);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);
	}

	ByteCodeInstruction	cins(BC_FILL);
	cins.mValue = ins->mConst.mOperandSize;
	mIns.Push(cins);
}

void ByteCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction * ins)
{
	LoadOperandAddress(proc, ins->mSrc[0], BC_REG_ACCU);
	LoadOperandAddress(proc, ins->mSrc[1], BC_REG_ADDR);

	ByteCodeInstruction	cins(BC_COPY);
	cins.mValue = ins->mConst.mOperandSize;
	mIns.Push(cins);
}

void ByteCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins)
{
	ByteCodeInstruction	sins(BC_ADDR_REG);
	sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
	sins.mRegisterFinal = ins->mSrc[1].mFinal;
	mIns.Push(sins);
	ByteCodeInstruction	dins(BC_LOAD_REG_16);
	dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
	dins.mRegisterFinal = ins->mSrc[0].mFinal;
	mIns.Push(dins);
	ByteCodeInstruction	cins(BC_STRCPY);
	mIns.Push(cins);
}

void ByteCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	dins(BC_CONST_16);
		dins.mRegister = BC_REG_ACCU;
		dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff);
		mIns.Push(dins);
	}
	else
	{
		ByteCodeInstruction	dins(BC_LOAD_REG_16);
		dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		dins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(dins);
	}
	ByteCodeInstruction	cins(BC_MALLOC);
	mIns.Push(cins);

	if (ins->mDst.mTemp >= 0)
	{
		ByteCodeInstruction	bins(BC_STORE_REG_16);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(bins);
	}
}

void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	dins(BC_CONST_16);
		dins.mRegister = BC_REG_ACCU;
		dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff);
		mIns.Push(dins);
	}
	else
	{
		ByteCodeInstruction	dins(BC_LOAD_REG_16);
		dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		dins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(dins);
	}
	ByteCodeInstruction	cins(BC_FREE);
	mIns.Push(cins);
}

void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mSrc[0].mType == IT_FLOAT)
	{
		if (ins->mSrc[1].mTemp < 0)
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				FloatConstToAccu(ins->mSrc[0].mFloatConst);

				if (ins->mSrc[1].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_32);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_ACCU;
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_32);
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_ACCU;
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_REG_32);
					bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (ins->mSrc[1].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
					else
						index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

					if (index <= 252)
					{
						ByteCodeInstruction	bins(BC_STORE_LOCAL_32);
						bins.mRegister = BC_REG_ACCU;
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_STORE_ADDR_32);
						bins.mRegister = BC_REG_ACCU;
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
				else if (ins->mSrc[1].mMemory == IM_FRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_FRAME_32);
					bins.mRegister = BC_REG_ACCU;
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
					mIns.Push(bins);
				}
			}
			else
			{
				if (ins->mSrc[1].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_32);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_32);
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	ains(BC_LOAD_REG_32);
					ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					mIns.Push(ains);

					ByteCodeInstruction	bins(BC_STORE_REG_32);
					bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (ins->mSrc[1].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
					else
						index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

					if (index <= 252)
					{
						ByteCodeInstruction	bins(BC_STORE_LOCAL_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_STORE_ADDR_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
				else if (ins->mSrc[1].mMemory == IM_FRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_FRAME_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
					mIns.Push(bins);
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				FloatConstToAccu(ins->mSrc[0].mFloatConst);

				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + 4 <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					ByteCodeInstruction	bins(BC_STORE_ADDR_32);
					bins.mRegister = BC_REG_ACCU;
					bins.mValue = index;
					mIns.Push(bins);
				}
			}
			else
			{
				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + 4 <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					ByteCodeInstruction	bins(BC_STORE_ADDR_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					bins.mValue = index;
					mIns.Push(bins);
				}
			}
		}
	}
	else if (ins->mSrc[0].mType == IT_POINTER)
	{
		if (ins->mSrc[1].mTemp < 0)
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[0].mIntConst);

				if (ins->mSrc[1].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_16);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_ACCU;
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_16);
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_ACCU;
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_REG_16);
					bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (ins->mSrc[1].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
					else
						index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

					if (index <= 254)
					{
						ByteCodeInstruction	bins(BC_STORE_LOCAL_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_STORE_ADDR_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
				else if (ins->mSrc[1].mMemory == IM_FRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_FRAME_16);
					bins.mRegister = BC_REG_ACCU;
					bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
					mIns.Push(bins);
				}
			}
			else
			{
				if (ins->mSrc[1].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_16);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_STORE_ABS_16);
					bins.mValue = int(ins->mSrc[1].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	ains(BC_LOAD_REG_16);
					ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					ains.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(ains);

					ByteCodeInstruction	bins(BC_STORE_REG_16);
					bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
					mIns.Push(bins);
				}
				else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (ins->mSrc[1].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
					else
						index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

					if (index <= 254)
					{
						ByteCodeInstruction	bins(BC_STORE_LOCAL_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_STORE_ADDR_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
				else if (ins->mSrc[1].mMemory == IM_FRAME)
				{
					ByteCodeInstruction	bins(BC_STORE_FRAME_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
					mIns.Push(bins);
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[0].mIntConst);

				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + 2 <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					ByteCodeInstruction	bins(BC_STORE_ADDR_16);
					bins.mRegister = BC_REG_ACCU;
					bins.mValue = index;
					mIns.Push(bins);
				}
			}
			else
			{
				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + 2 <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					ByteCodeInstruction	bins(BC_STORE_ADDR_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					bins.mValue = index;
					mIns.Push(bins);
				}
			}
		}
	}
	else
	{
		if (ins->mSrc[1].mTemp < 0)
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				if (InterTypeSize[ins->mSrc[0].mType] <= 2)
					IntConstToAccu(ins->mSrc[0].mIntConst);
				else
					LongConstToAccu(ins->mSrc[0].mIntConst);

				if (InterTypeSize[ins->mSrc[0].mType] == 1)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_8);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_8);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_REG_8);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 255)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_8);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_8);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_8);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
				else if (InterTypeSize[ins->mSrc[0].mType] == 2)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_16);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_16);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_REG_16);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 254)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_16);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_16);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
				else if (InterTypeSize[ins->mSrc[0].mType] == 4)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_32);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_32);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_ACCU;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_REG_32);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 252)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_32);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_32);
							bins.mRegister = BC_REG_ACCU;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_32);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
			}
			else
			{
				if (InterTypeSize[ins->mSrc[0].mType] == 1)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_8);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_8);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	ains(BC_LOAD_REG_8);
						ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						ains.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(ains);

						ByteCodeInstruction	bins(BC_STORE_REG_8);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 255)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_8);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_8);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_8);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
				else if (InterTypeSize[ins->mSrc[0].mType] == 2)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_16);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_16);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	ains(BC_LOAD_REG_16);
						ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						ains.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(ains);

						ByteCodeInstruction	bins(BC_STORE_REG_16);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 254)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_16);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_16);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
				else if (InterTypeSize[ins->mSrc[0].mType] == 4)
				{
					if (ins->mSrc[1].mMemory == IM_GLOBAL)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_32);
						bins.mRelocate = true;
						bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
					{
						ByteCodeInstruction	bins(BC_STORE_ABS_32);
						bins.mValue = int(ins->mSrc[1].mIntConst);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
					{
						ByteCodeInstruction	ains(BC_LOAD_REG_32);
						ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						ains.mRegisterFinal = ins->mSrc[0].mFinal;
						mIns.Push(ains);

						ByteCodeInstruction	bins(BC_STORE_REG_32);
						bins.mRegister = int(BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst);
						mIns.Push(bins);
					}
					else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
					{
						int	index = int(ins->mSrc[1].mIntConst);
						if (ins->mSrc[1].mMemory == IM_LOCAL)
							index += proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset;
						else
							index += ins->mSrc[1].mVarIndex + proc->mLocalSize + 2;

						if (index <= 252)
						{
							ByteCodeInstruction	bins(BC_STORE_LOCAL_32);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = index;
							mIns.Push(bins);
						}
						else
						{
							ByteCodeInstruction	lins(BC_LEA_LOCAL);
							lins.mRegister = BC_REG_ADDR;
							lins.mValue = index;
							mIns.Push(lins);
							ByteCodeInstruction	bins(BC_STORE_ADDR_32);
							bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
							bins.mRegisterFinal = ins->mSrc[0].mFinal;
							bins.mValue = 0;
							mIns.Push(bins);
						}
					}
					else if (ins->mSrc[1].mMemory == IM_FRAME)
					{
						ByteCodeInstruction	bins(BC_STORE_FRAME_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = int(ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + 2);
						mIns.Push(bins);
					}
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mTemp < 0)
			{
				if (InterTypeSize[ins->mSrc[0].mType] <= 2)
					IntConstToAccu(ins->mSrc[0].mIntConst);
				else
					LongConstToAccu(ins->mSrc[0].mIntConst);

				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + InterTypeSize[ins->mSrc[0].mType] <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					if (InterTypeSize[ins->mSrc[0].mType] == 1)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_8);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else if (InterTypeSize[ins->mSrc[0].mType] == 2)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else if (InterTypeSize[ins->mSrc[0].mType] == 4)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_32);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = index;
						mIns.Push(bins);
					}
				}
			}
			else
			{
				if (ins->mSrc[1].mMemory == IM_INDIRECT)
				{
					int	index = int(ins->mSrc[1].mIntConst);
					if (index >= 0 && index + InterTypeSize[ins->mSrc[0].mType] <= 256)
					{
						ByteCodeInstruction	lins(BC_ADDR_REG);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						mIns.Push(lins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
						lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						lins.mRegisterFinal = ins->mSrc[1].mFinal;
						lins.mValue = index;
						index = 0;
						mIns.Push(lins);
					}

					if (InterTypeSize[ins->mSrc[0].mType] == 1)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_8);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else if (InterTypeSize[ins->mSrc[0].mType] == 2)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
					else if (InterTypeSize[ins->mSrc[0].mType] == 4)
					{
						ByteCodeInstruction	bins(BC_STORE_ADDR_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = index;
						mIns.Push(bins);
					}
				}
			}
		}
	}
}

void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mDst.mType == IT_FLOAT)
	{
		if (ins->mSrc[0].mTemp < 0)
		{
			if (ins->mSrc[0].mMemory == IM_GLOBAL)
			{
				ByteCodeInstruction	bins(BC_LOAD_ABS_32);
				bins.mRelocate = true;
				bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
				bins.mValue = int(ins->mSrc[0].mIntConst);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
			{
				ByteCodeInstruction	bins(BC_LOAD_ABS_32);
				bins.mValue = int(ins->mSrc[0].mIntConst);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_FFRAME)
			{
				ByteCodeInstruction	ains(BC_LOAD_REG_32);
				ains.mRegister = int(BC_REG_FPARAMS + ins->mSrc[0].mIntConst + ins->mSrc[0].mVarIndex);
				mIns.Push(ains);

				ByteCodeInstruction	bins(BC_STORE_REG_32);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
			{
				int	index = int(ins->mSrc[0].mIntConst);
				if (ins->mSrc[0].mMemory == IM_LOCAL)
					index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
				else
					index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;

				if (index <= 254)
				{
					ByteCodeInstruction	bins(BC_LOAD_LOCAL_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = index;
					mIns.Push(bins);
				}
				else
				{
					ByteCodeInstruction	lins(BC_LEA_LOCAL);
					lins.mRegister = BC_REG_ADDR;
					lins.mValue = index;
					mIns.Push(lins);
					ByteCodeInstruction	bins(BC_LOAD_ADDR_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = 0;
					mIns.Push(bins);
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mMemory == IM_INDIRECT)
			{
				int	index = int(ins->mSrc[0].mIntConst);
				if (index >= 0 && index + 4 <= 256)
				{
					ByteCodeInstruction	lins(BC_ADDR_REG);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
				}
				else
				{
					ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					lins.mValue = index;
					index = 0;
					mIns.Push(lins);
				}

				ByteCodeInstruction	bins(BC_LOAD_ADDR_32);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				bins.mValue = index;
				mIns.Push(bins);
			}
		}
	}
	else if (ins->mDst.mType == IT_POINTER)
	{
		if (ins->mSrc[0].mTemp < 0)
		{
			if (ins->mSrc[0].mMemory == IM_GLOBAL)
			{
				ByteCodeInstruction	bins(BC_LOAD_ABS_16);
				bins.mRelocate = true;
				bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
				bins.mValue = int(ins->mSrc[0].mIntConst);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
			{
				ByteCodeInstruction	bins(BC_LOAD_ABS_16);
				bins.mValue = int(ins->mSrc[0].mIntConst);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_FFRAME)
			{
				ByteCodeInstruction	ains(BC_LOAD_REG_16);
				ains.mRegister = int(BC_REG_FPARAMS + ins->mSrc[0].mIntConst + ins->mSrc[0].mVarIndex);
				mIns.Push(ains);

				ByteCodeInstruction	bins(BC_STORE_REG_16);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
			{
				int	index = int(ins->mSrc[0].mIntConst);
				if (ins->mSrc[0].mMemory == IM_LOCAL)
					index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
				else
					index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;

				if (index <= 254)
				{
					ByteCodeInstruction	bins(BC_LOAD_LOCAL_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = index;
					mIns.Push(bins);
				}
				else
				{
					ByteCodeInstruction	lins(BC_LEA_LOCAL);
					lins.mRegister = BC_REG_ADDR;
					lins.mValue = index;
					mIns.Push(lins);
					ByteCodeInstruction	bins(BC_LOAD_ADDR_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = 0;
					mIns.Push(bins);
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mMemory == IM_INDIRECT)
			{
				int	index = int(ins->mSrc[0].mIntConst);
				if (index >= 0 && index + 2 <= 256)
				{
					ByteCodeInstruction	lins(BC_ADDR_REG);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
				}
				else
				{
					ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					lins.mValue = index;
					index = 0;
					mIns.Push(lins);
				}

				ByteCodeInstruction	bins(BC_LOAD_ADDR_16);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
				bins.mValue = index;
				mIns.Push(bins);
			}
		}
	}
	else
	{
		if (ins->mSrc[0].mTemp < 0)
		{ 
			if (InterTypeSize[ins->mDst.mType] == 1)
			{
				if (ins->mSrc[0].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_8);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_8);
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	ains(BC_LOAD_REG_8);
					ains.mRegister = int(BC_REG_FPARAMS + ins->mSrc[0].mIntConst + ins->mSrc[0].mVarIndex);
					mIns.Push(ains);

					ByteCodeInstruction	bins(BC_STORE_REG_8);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[0].mIntConst);
					if (ins->mSrc[0].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
					else
						index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;

					if (index <= 255)
					{
						ByteCodeInstruction	bins(BC_LOAD_LOCAL_8);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_LOAD_ADDR_8);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
			}
			else if (InterTypeSize[ins->mDst.mType] == 2)
			{
				if (ins->mSrc[0].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_16);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_16);
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	ains(BC_LOAD_REG_16);
					ains.mRegister = int(BC_REG_FPARAMS + ins->mSrc[0].mIntConst + ins->mSrc[0].mVarIndex);
					mIns.Push(ains);

					ByteCodeInstruction	bins(BC_STORE_REG_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[0].mIntConst);
					if (ins->mSrc[0].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
					else
						index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;

					if (index <= 254)
					{
						ByteCodeInstruction	bins(BC_LOAD_LOCAL_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_LOAD_ADDR_16);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
			}
			else if (InterTypeSize[ins->mDst.mType] == 4)
			{
				if (ins->mSrc[0].mMemory == IM_GLOBAL)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_32);
					bins.mRelocate = true;
					bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
				{
					ByteCodeInstruction	bins(BC_LOAD_ABS_32);
					bins.mValue = int(ins->mSrc[0].mIntConst);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_FFRAME)
				{
					ByteCodeInstruction	ains(BC_LOAD_REG_32);
					ains.mRegister = int(BC_REG_FPARAMS + ins->mSrc[0].mIntConst + ins->mSrc[0].mVarIndex);
					mIns.Push(ains);

					ByteCodeInstruction	bins(BC_STORE_REG_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(bins);
				}
				else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
				{
					int	index = int(ins->mSrc[0].mIntConst);
					if (ins->mSrc[0].mMemory == IM_LOCAL)
						index += proc->mLocalVars[ins->mSrc[0].mVarIndex]->mOffset;
					else
						index += ins->mSrc[0].mVarIndex + proc->mLocalSize + 2;

					if (index <= 252)
					{
						ByteCodeInstruction	bins(BC_LOAD_LOCAL_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = index;
						mIns.Push(bins);
					}
					else
					{
						ByteCodeInstruction	lins(BC_LEA_LOCAL);
						lins.mRegister = BC_REG_ADDR;
						lins.mValue = index;
						mIns.Push(lins);
						ByteCodeInstruction	bins(BC_LOAD_ADDR_32);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
						bins.mValue = 0;
						mIns.Push(bins);
					}
				}
			}
		}
		else
		{
			if (ins->mSrc[0].mMemory == IM_INDIRECT)
			{
				int	index = int(ins->mSrc[0].mIntConst);
				if (index >= 0 && index + InterTypeSize[ins->mDst.mType] <= 256)
				{
					ByteCodeInstruction	lins(BC_ADDR_REG);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
				}
				else
				{
					ByteCodeInstruction	lins(BC_LEA_ABS_INDEX);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					lins.mValue = index;
					index = 0;
					mIns.Push(lins);
				}

				if (InterTypeSize[ins->mDst.mType] == 1)
				{
					ByteCodeInstruction	bins(BC_LOAD_ADDR_8);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = index;
					mIns.Push(bins);
				}
				else if (InterTypeSize[ins->mDst.mType] == 2)
				{
					ByteCodeInstruction	bins(BC_LOAD_ADDR_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = index;
					mIns.Push(bins);
				}
				else if (InterTypeSize[ins->mDst.mType] == 4)
				{
					ByteCodeInstruction	bins(BC_LOAD_ADDR_32);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = index;
					mIns.Push(bins);
				}
			}
		}
	}
}

void ByteCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins)
{
	int	ri = int(rins->mSrc[0].mIntConst), wi = int(wins->mSrc[1].mIntConst);

	if (ri < 252 && wi < 252 && rins->mSrc[0].mTemp == wins->mSrc[1].mTemp && rins->mSrc[0].mMemory == IM_INDIRECT && wins->mSrc[1].mMemory == IM_INDIRECT)
	{
		ByteCodeInstruction	lins(BC_ADDR_REG);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp];
		lins.mRegisterFinal = wins->mSrc[1].mFinal;
		mIns.Push(lins);

		if (InterTypeSize[rins->mDst.mType] == 1)
		{
			ByteCodeInstruction	bins(BC_LOAD_ADDR_8);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
			bins.mValue = ri;
			mIns.Push(bins);
		}
		else if (InterTypeSize[rins->mDst.mType] == 2)
		{
			ByteCodeInstruction	bins(BC_LOAD_ADDR_16);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
			bins.mValue = ri;
			mIns.Push(bins);
		}
		else if (InterTypeSize[rins->mDst.mType] == 4)
		{
			ByteCodeInstruction	bins(BC_LOAD_ADDR_32);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
			bins.mValue = ri;
			mIns.Push(bins);
		}

		if (InterTypeSize[wins->mSrc[0].mType] == 1)
		{
			ByteCodeInstruction	bins(BC_STORE_ADDR_8);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
			bins.mValue = wi;
			mIns.Push(bins);
		}
		else if (InterTypeSize[wins->mSrc[0].mType] == 2)
		{
			ByteCodeInstruction	bins(BC_STORE_ADDR_16);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
			bins.mValue = wi;
			mIns.Push(bins);
		}
		else if (InterTypeSize[wins->mSrc[0].mType] == 4)
		{
			ByteCodeInstruction	bins(BC_STORE_ADDR_32);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
			bins.mValue = wi;
			mIns.Push(bins);
		}
	}
	else
	{
		LoadDirectValue(proc, rins);
		StoreDirectValue(proc, wins);
	}
}

void ByteCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		if (ins->mSrc[1].mTemp == ins->mDst.mTemp)
		{
			ByteCodeInstruction	bins(BC_BINOP_ADDI_16);
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			bins.mValue = int(ins->mSrc[0].mIntConst);
			mIns.Push(bins);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_16);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
			lins.mRegisterFinal = ins->mSrc[1].mFinal;
			mIns.Push(lins);
			ByteCodeInstruction	ains(BC_BINOP_ADDI_16);
			ains.mRegister = BC_REG_ACCU;
			ains.mValue = int(ins->mSrc[0].mIntConst);
			mIns.Push(ains);
			ByteCodeInstruction	sins(BC_STORE_REG_16);
			sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			mIns.Push(sins);
		}
	}
	else if (ins->mSrc[1].mTemp < 0)
	{
		if (ins->mSrc[1].mMemory == IM_GLOBAL)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = BC_REG_ACCU;
			bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
			bins.mValue = int(ins->mSrc[1].mIntConst);
			bins.mRelocate = true;
			mIns.Push(bins);
		}
		else if (ins->mSrc[1].mMemory == IM_ABSOLUTE)
		{
			ByteCodeInstruction	bins(BC_LEA_ABS);
			bins.mRegister = BC_REG_ACCU;
			bins.mValue = int(ins->mSrc[1].mIntConst);
			mIns.Push(bins);
		}
		else if (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)
		{
			ByteCodeInstruction	bins(BC_CONST_16);
			bins.mRegister = BC_REG_ACCU;
			bins.mValue = int(BC_REG_FPARAMS + ins->mSrc[1].mIntConst + ins->mSrc[1].mVarIndex);
			mIns.Push(bins);
		}
		else if (ins->mSrc[1].mMemory == IM_PROCEDURE)
		{
			ByteCodeInstruction	bins(BC_CONST_16);
			bins.mRegister = BC_REG_ACCU;
			bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
			bins.mValue = 0;
			bins.mRelocate = true;
			mIns.Push(bins);
		}
		else if (ins->mSrc[1].mMemory == IM_LOCAL || ins->mSrc[1].mMemory == IM_PARAM)
		{
			ByteCodeInstruction	bins(BC_LEA_LOCAL);
			bins.mRegister = BC_REG_ACCU;
			bins.mValue = int(ins->mSrc[1].mIntConst + proc->mLocalVars[ins->mSrc[1].mVarIndex]->mOffset);
			mIns.Push(bins);
		}

		ByteCodeInstruction	ains(BC_BINOP_ADDR_16);
		ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		ains.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(ains);
		ByteCodeInstruction	sins(BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
	else
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
		lins.mRegisterFinal = ins->mSrc[1].mFinal;
		mIns.Push(lins);
		ByteCodeInstruction	ains(BC_BINOP_ADDR_16);
		ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		ains.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(ains);
		ByteCodeInstruction	sins(BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
}
void ByteCodeBasicBlock::CallFunction(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	bins(BC_CALL_ABS);
		bins.mRelocate = true;
		bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
		bins.mValue = 0;
		mIns.Push(bins);
	}
	else
	{
		ByteCodeInstruction	bins(BC_ADDR_REG);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		bins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(bins);
		ByteCodeInstruction	cins(BC_CALL_ADDR);
		mIns.Push(cins);
	}

	if (ins->mDst.mTemp >= 0)
	{
		ByteCodeInstruction	bins(StoreTypedTmpCodes[ins->mDst.mType]);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(bins);
	}
}

void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	bins(BC_JSR);
		bins.mRelocate = true;
		bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
		bins.mValue = int(ins->mSrc[0].mIntConst);
		for (int i = 1; i < ins->mNumOperands; i++)
		{
			if (ins->mSrc[i].mTemp < 0)
			{
				if (ins->mSrc[i].mMemory == IM_FPARAM || ins->mSrc[i].mMemory == IM_FFRAME)
					ins->mSrc[0].mLinkerObject->mTemporaries[i - 1] = int(BC_REG_FPARAMS + ins->mSrc[i].mVarIndex + ins->mSrc[i].mIntConst);
			}
			else
				ins->mSrc[0].mLinkerObject->mTemporaries[i - 1] = BC_REG_TMP + proc->mTempOffset[ins->mSrc[i].mTemp];
		}
		mIns.Push(bins);
	}

	if (ins->mDst.mTemp >= 0)
	{
		ByteCodeInstruction	bins(StoreTypedTmpCodes[ins->mDst.mType]);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(bins);
	}
}

void ByteCodeBasicBlock::CallNative(InterCodeProcedure* proc, const InterInstruction* ins)
{
	if (ins->mSrc[0].mTemp < 0)
	{
		ByteCodeInstruction	bins(BC_JSR);
		bins.mRelocate = true;
		bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
		bins.mValue = int(ins->mSrc[0].mIntConst);
		mIns.Push(bins);
	}

	if (ins->mDst.mTemp >= 0)
	{
		ByteCodeInstruction	bins(StoreTypedTmpCodes[ins->mDst.mType]);
		bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(bins);
	}
}

ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, bool optzero)
{
	ByteCode	code;
	bool		csigned = false;

	switch (ins->mOperator)
	{
	default:
	case IA_CMPEQ:
		code = BC_BRANCHS_EQ;
		break;
	case IA_CMPNE:
		code = BC_BRANCHS_NE;
		break;

	case IA_CMPGES:
		csigned = true;
		code = BC_BRANCHS_GE;
		break;
	case IA_CMPGEU:
		code = BC_BRANCHS_GE;
		break;
	case IA_CMPGS:
		csigned = true;
		code = BC_BRANCHS_GT;
		break;
	case IA_CMPGU:
		code = BC_BRANCHS_GT;
		break;
	case IA_CMPLES:
		csigned = true;
		code = BC_BRANCHS_LE;
		break;
	case IA_CMPLEU:
		code = BC_BRANCHS_LE;
		break;
	case IA_CMPLS:
		csigned = true;
		code = BC_BRANCHS_LT;
		break;
	case IA_CMPLU:
		code = BC_BRANCHS_LT;
		break;
	}

	if (ins->mSrc[0].mType == IT_FLOAT)
	{
		if (ins->mSrc[0].mTemp < 0)
		{
			FloatConstToAccu(ins->mSrc[0].mFloatConst);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_32);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);
		}

		ByteCodeInstruction	cins(BC_BINOP_CMP_F32);

		if (ins->mSrc[1].mTemp < 0)
		{
			FloatConstToWork(ins->mSrc[1].mFloatConst);
			cins.mRegister = BC_REG_WORK;
		}
		else
		{
			cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
		}

		cins.mRegisterFinal = ins->mSrc[1].mFinal;
		mIns.Push(cins);
	}
	else if (ins->mSrc[0].mType == IT_INT32)
	{
		if (ins->mSrc[0].mTemp < 0)
		{
			LongConstToAccu(ins->mSrc[0].mIntConst);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_32);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);
		}


		ByteCodeInstruction	cins(BC_BINOP_CMP_U32);
		if (csigned)
			cins.mCode = BC_BINOP_CMP_S32;

		if (ins->mSrc[1].mTemp < 0)
		{
			LongConstToWork(ins->mSrc[1].mIntConst);
			cins.mRegister = BC_REG_WORK;
		}
		else
		{
			cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
		}

		cins.mRegisterFinal = ins->mSrc[1].mFinal;
		mIns.Push(cins);
	}
	else if (ins->mSrc[0].mType == IT_INT8 || ins->mSrc[0].mType == IT_BOOL)
	{
		if (ins->mSrc[1].mTemp < 0)
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_8);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);
			if (csigned)
			{
				ByteCodeInstruction	cins(BC_BINOP_CMPSI_8);
				cins.mValue = int(ins->mSrc[1].mIntConst);
				mIns.Push(cins);
			}
			else
			{
				if (optzero && ins->mSrc[1].mIntConst == 0)
				{
					switch (ins->mOperator)
					{
					case IA_CMPEQ:
					case IA_CMPGEU:
						return BC_BRANCHS_EQ;
					case IA_CMPNE:
					case IA_CMPLU:
						return BC_BRANCHS_NE;
					case IA_CMPLEU:
						return BC_JUMPS;
					case IA_CMPGU:
						return BC_NOP;
					}
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPUI_8);
					cins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(cins);
				}
			}
		}
		else if (ins->mSrc[0].mTemp < 0)
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_8);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
			lins.mRegisterFinal = ins->mSrc[1].mFinal;
			mIns.Push(lins);
			if (csigned)
			{
				if (optzero && ins->mSrc[0].mIntConst == 0)
				{
					ByteCodeInstruction	cins(BC_CONV_I8_I16);
					cins.mRegister = BC_REG_ACCU;
					mIns.Push(cins);

					switch (ins->mOperator)
					{
					case IA_CMPEQ:
						return BC_BRANCHS_EQ;
					case IA_CMPNE:
						return BC_BRANCHS_NE;
					case IA_CMPLES:
						return BC_BRANCHS_LE;
					case IA_CMPGS:
						return BC_BRANCHS_GT;
					case IA_CMPGES:
						return BC_BRANCHS_GE;
					case IA_CMPLS:
						return BC_BRANCHS_LT;
					}
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPSI_8);
					cins.mValue = int(ins->mSrc[0].mIntConst);
					mIns.Push(cins);
				}
			}
			else
			{
				if (optzero && ins->mSrc[0].mIntConst == 0)
				{
					switch (ins->mOperator)
					{
					case IA_CMPEQ:
					case IA_CMPLEU:
						return BC_BRANCHS_EQ;
					case IA_CMPNE:
					case IA_CMPGU:
						return BC_BRANCHS_NE;
					case IA_CMPGEU:
						return BC_JUMPS;
					case IA_CMPLU:
						return BC_NOP;
					}
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPUI_8);
					cins.mValue = int(ins->mSrc[0].mIntConst);
					mIns.Push(cins);
				}
			}
			code = TransposeBranchCondition(code);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_8);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);
			if (csigned)
			{
				ByteCodeInstruction	cins(BC_BINOP_CMPSR_8);
				cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				cins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(cins);
			}
			else
			{
				ByteCodeInstruction	cins(BC_BINOP_CMPUR_8);
				cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				cins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(cins);
			}
		}
	}
	else
	{
		if (ins->mSrc[1].mTemp < 0)
		{
			if (ins->mSrc[1].mType == IT_INT16 || ins->mSrc[1].mMemory == IM_ABSOLUTE)
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);

				if (csigned)
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPSI_16);
					cins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(cins);
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPUI_16);
					cins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(cins);
				}
			}
			else
			{
				ByteCodeInstruction	bins(BC_LEA_ABS);
				bins.mRegister = BC_REG_ACCU;
				bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
				bins.mValue = int(ins->mSrc[1].mIntConst);
				bins.mRelocate = true;
				mIns.Push(bins);

				if (csigned)
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPSR_16);
					cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					cins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(cins);
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPUR_16);
					cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					cins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(cins);
				}

				code = TransposeBranchCondition(code);
			}
		}
		else if (ins->mSrc[0].mTemp < 0)
		{
			if (ins->mSrc[0].mType == IT_INT16 || ins->mSrc[0].mMemory == IM_ABSOLUTE)
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(lins);
				if (csigned)
				{
					if (optzero && ins->mSrc[0].mIntConst == 0)
					{
						switch (ins->mOperator)
						{
						case IA_CMPEQ:
							return BC_BRANCHS_EQ;
						case IA_CMPNE:
							return BC_BRANCHS_NE;
						case IA_CMPLES:
							return BC_BRANCHS_LE;
						case IA_CMPGS:
							return BC_BRANCHS_GT;
						case IA_CMPGES:
							return BC_BRANCHS_GE;
						case IA_CMPLS:
							return BC_BRANCHS_LT;
						}
					}
					else if (ins->mSrc[1].IsUByte())
					{
						ByteCodeInstruction	cins(BC_BINOP_CMPUI_8);
						cins.mValue = int(ins->mSrc[0].mIntConst);
						mIns.Push(cins);
					}
					else
					{
						ByteCodeInstruction	cins(BC_BINOP_CMPSI_16);
						cins.mValue = int(ins->mSrc[0].mIntConst);
						mIns.Push(cins);
					}
				}
				else
				{
					if (optzero && ins->mSrc[0].mIntConst == 0)
					{
						switch (ins->mOperator)
						{
						case IA_CMPEQ:
						case IA_CMPLEU:
							return BC_BRANCHS_EQ;
						case IA_CMPNE:
						case IA_CMPGU:
							return BC_BRANCHS_NE;
						case IA_CMPGEU:
							return BC_JUMPS;
						case IA_CMPLU:
							return BC_NOP;
						}
					}
					else if (ins->mSrc[1].IsUByte())
					{
						ByteCodeInstruction	cins(BC_BINOP_CMPUI_8);
						cins.mValue = int(ins->mSrc[0].mIntConst);
						mIns.Push(cins);
					}
					else
					{
						ByteCodeInstruction	cins(BC_BINOP_CMPUI_16);
						cins.mValue = int(ins->mSrc[0].mIntConst);
						mIns.Push(cins);
					}
				}
				code = TransposeBranchCondition(code);
			}
			else
			{
				ByteCodeInstruction	bins(BC_LEA_ABS);
				bins.mRegister = BC_REG_ACCU;
				bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
				bins.mValue = int(ins->mSrc[0].mIntConst);
				bins.mRelocate = true;
				mIns.Push(bins);

				if (csigned)
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPSR_16);
					cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
					cins.mRegisterFinal = ins->mSrc[1].mFinal;
					mIns.Push(cins);
				}
				else
				{
					ByteCodeInstruction	cins(BC_BINOP_CMPUR_16);
					cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
					cins.mRegisterFinal = ins->mSrc[1].mFinal;
					mIns.Push(cins);
				}
			}
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_16);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);
			if (csigned)
			{
				ByteCodeInstruction	cins(BC_BINOP_CMPSR_16);
				cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				cins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(cins);
			}
			else
			{
				ByteCodeInstruction	cins(BC_BINOP_CMPUR_16);
				cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				cins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(cins);
			}
		}
	}

	return code;
}

static ByteCode ByteCodeBinRegOperator(const InterInstruction * ins)
{
	if (ins->mDst.mType == IT_FLOAT)
	{
		switch (ins->mOperator)
		{
		case IA_ADD: return BC_BINOP_ADD_F32;
		case IA_SUB: return BC_BINOP_SUB_F32;
		case IA_MUL: return BC_BINOP_MUL_F32;
		case IA_DIVU: return BC_BINOP_DIV_F32;
		case IA_DIVS: return BC_BINOP_DIV_F32;

		default:
			return BC_EXIT;
		}
	}
	else if (ins->mDst.mType == IT_INT32)
	{
		switch (ins->mOperator)
		{
		case IA_ADD: return BC_BINOP_ADD_L32;
		case IA_SUB: return BC_BINOP_SUB_L32;
		case IA_MUL: return BC_BINOP_MUL_L32;
		case IA_DIVU: return BC_BINOP_DIV_U32;
		case IA_MODU: return BC_BINOP_MOD_U32;
		case IA_DIVS: return BC_BINOP_DIV_I32;
		case IA_MODS: return BC_BINOP_MOD_I32;
		case IA_AND: return BC_BINOP_AND_L32;
		case IA_OR: return BC_BINOP_OR_L32;
		case IA_XOR: return BC_BINOP_XOR_L32;

		case IA_SHL: return BC_BINOP_SHL_L32;
		case IA_SHR: return BC_BINOP_SHR_U32;
		case IA_SAR: return BC_BINOP_SHR_I32;

		default:
			return BC_EXIT;
		}
	}
	else
	{
		switch (ins->mOperator)
		{
		case IA_ADD: return BC_BINOP_ADDR_16;
		case IA_SUB: return BC_BINOP_SUBR_16;
		case IA_MUL: return BC_BINOP_MULR_16;
		case IA_DIVU: return BC_BINOP_DIVR_U16;
		case IA_MODU: return BC_BINOP_MODR_U16;
		case IA_DIVS: return BC_BINOP_DIVR_I16;
		case IA_MODS: return BC_BINOP_MODR_I16;
		case IA_AND: return BC_BINOP_ANDR_16;
		case IA_OR: return BC_BINOP_ORR_16;
		case IA_XOR: return BC_BINOP_XORR_16;

		case IA_SHL: return BC_BINOP_SHLR_16;
		case IA_SHR: return BC_BINOP_SHRR_U16;
		case IA_SAR: return BC_BINOP_SHRR_I16;

		default:
			return BC_EXIT;
		}
	}
}

static ByteCode ByteCodeBinImmOperator(const InterInstruction * ins)
{
	switch (ins->mOperator)
	{
	case IA_ADD: return BC_BINOP_ADDI_16;
	case IA_SUB: return BC_BINOP_SUBI_16;
	case IA_AND: return BC_BINOP_ANDI_16;
	case IA_OR:  return BC_BINOP_ORI_16;
	case IA_SHL: return BC_BINOP_SHLI_16;
	case IA_SHR: return BC_BINOP_SHRI_U16;
	case IA_SAR: return BC_BINOP_SHRI_I16;
	case IA_MUL: return BC_BINOP_MULI8_16;

	default:
		return BC_EXIT;
	}
}

static ByteCode ByteCodeBinSizeImmOperator(const InterInstruction* ins)
{
	switch (ins->mOperator)
	{
	case IA_ADD: return InterTypeSize[ins->mDst.mType] == 1 ? BC_BINOP_ADDI_8 : BC_BINOP_ADDI_16;
	case IA_SUB: return BC_BINOP_SUBI_16;
	case IA_AND: return InterTypeSize[ins->mDst.mType] == 1 ? BC_BINOP_ANDI_8 : BC_BINOP_ANDI_16;
	case IA_OR:  return InterTypeSize[ins->mDst.mType] == 1 ? BC_BINOP_ORI_8 : BC_BINOP_ORI_16;
	case IA_SHL: return BC_BINOP_SHLI_16;
	case IA_SHR: return BC_BINOP_SHRI_U16;
	case IA_SAR: return BC_BINOP_SHRI_I16;
	case IA_MUL: return BC_BINOP_MULI8_16;

	default:
		return BC_EXIT;
	}
}

void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const InterInstruction * ins)
{
	switch (ins->mOperator)
	{
	case IA_FLOAT2INT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_F32_I16);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	}	break;
	case IA_INT2FLOAT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_I16_F32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	} break;
	case IA_FLOAT2UINT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_F32_U16);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	}	break;
	case IA_UINT2FLOAT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_U16_F32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	} break;

	case IA_FLOAT2LINT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_F32_I32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	}	break;
	case IA_LINT2FLOAT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_I32_F32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	} break;
	case IA_FLOAT2LUINT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_F32_U32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	}	break;
	case IA_LUINT2FLOAT:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	bins(BC_CONV_U32_F32);
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);

	} break;

	case IA_EXT8TO16S:
	{
		if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
		{
			ByteCodeInstruction	cins(BC_CONV_I8_I16);
			cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			cins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(cins);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_8);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);

			ByteCodeInstruction	cins(BC_CONV_I8_I16);
			cins.mRegister = BC_REG_ACCU;
			mIns.Push(cins);

			ByteCodeInstruction	sins(BC_STORE_REG_16);
			sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			mIns.Push(sins);
		}
	}	break;
	case IA_EXT8TO16U:
	{
		if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
		{
			ByteCodeInstruction	cins(BC_BINOP_ANDI_16);
			cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			cins.mRegisterFinal = ins->mSrc[0].mFinal;
			cins.mValue = 0x00ff;
			mIns.Push(cins);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_8);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
			lins.mRegisterFinal = ins->mSrc[0].mFinal;
			mIns.Push(lins);

			ByteCodeInstruction	sins(BC_STORE_REG_16);
			sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
			mIns.Push(sins);
		}
	}	break;
	case IA_EXT16TO32S:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	cins(BC_CONV_I16_I32);
		cins.mRegister = 0;
		mIns.Push(cins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}	break;

	case IA_EXT16TO32U:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	cins(BC_CONV_U16_U32);
		cins.mRuntime = "lextu16";
		cins.mRegister = 0;
		mIns.Push(cins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}	break;


	case IA_EXT8TO32S:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_8);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	cins0(BC_CONV_I8_I16);
		cins0.mRegister = BC_REG_ACCU;
		mIns.Push(cins0);

		ByteCodeInstruction	cins1(BC_CONV_I16_I32);
		cins1.mRegister = 0;
		mIns.Push(cins1);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}	break;

	case IA_EXT8TO32U:
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_8);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		ByteCodeInstruction	cins(BC_CONV_U16_U32);
		cins.mRuntime = "lextu16";
		cins.mRegister = 0;
		mIns.Push(cins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}	break;
	}
}

void ByteCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mDst.mType == IT_FLOAT)
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		switch (ins->mOperator)
		{
		case IA_NEG:
		{
			ByteCodeInstruction	oins(BC_OP_NEGATE_F32);
			mIns.Push(oins);
		}	break;
		case IA_ABS:
		{
			ByteCodeInstruction	oins(BC_OP_ABS_F32);
			mIns.Push(oins);
		}	break;
		case IA_FLOOR:
		{
			ByteCodeInstruction	oins(BC_OP_FLOOR_F32);
			mIns.Push(oins);
		}	break;
		case IA_CEIL:
		{
			ByteCodeInstruction	oins(BC_OP_CEIL_F32);
			mIns.Push(oins);
		}	break;
		}

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
	else if (ins->mDst.mType == IT_INT32)
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_32);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		switch (ins->mOperator)
		{
		case IA_NEG:
		{
			ByteCodeInstruction	oins(BC_OP_NEGATE_32);
			mIns.Push(oins);
		}	break;
		case IA_NOT:
		{
			ByteCodeInstruction	oins(BC_OP_INVERT_32);
			mIns.Push(oins);
		}	break;
		}

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
	else
	{
		ByteCodeInstruction	lins(BC_LOAD_REG_16);
		lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
		lins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(lins);

		switch (ins->mOperator)
		{
		case IA_NEG:
		{
			ByteCodeInstruction	oins(BC_OP_NEGATE_16);
			mIns.Push(oins);
		}	break;

		case IA_NOT:
		{
			ByteCodeInstruction	oins(BC_OP_INVERT_16);
			mIns.Push(oins);
		}	break;
		}

		ByteCodeInstruction	sins(BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
}

void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction * ins)
{
	if (ins->mDst.mType == IT_FLOAT)
	{
		ByteCode	bc = ByteCodeBinRegOperator(ins);

		if (ins->mSrc[1].mTemp < 0)
		{
			FloatConstToAccu(ins->mSrc[1].mFloatConst);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_32);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
			lins.mRegisterFinal = ins->mSrc[1].mFinal;
			mIns.Push(lins);
		}

		ByteCodeInstruction	bins(bc);

		if (ins->mSrc[0].mTemp < 0)
		{
			FloatConstToWork(ins->mSrc[0].mFloatConst);
			bins.mRegister = BC_REG_WORK;
		}
		else if (ins->mSrc[1].mTemp == ins->mSrc[0].mTemp)
			bins.mRegister = BC_REG_ACCU;
		else
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];

		bins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
	else if (ins->mDst.mType == IT_INT32)
	{
		ByteCode	bc = ByteCodeBinRegOperator(ins);

		if (ins->mSrc[1].mTemp < 0)
		{
			LongConstToAccu(ins->mSrc[1].mIntConst);
		}
		else
		{
			ByteCodeInstruction	lins(BC_LOAD_REG_32);
			lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
			lins.mRegisterFinal = ins->mSrc[1].mFinal;
			mIns.Push(lins);
		}

		ByteCodeInstruction	bins(bc);

		if (ins->mSrc[0].mTemp < 0)
		{
			LongConstToWork(ins->mSrc[0].mIntConst);
			bins.mRegister = BC_REG_WORK;
		}
		else if (ins->mSrc[1].mTemp == ins->mSrc[0].mTemp)
			bins.mRegister = BC_REG_ACCU;
		else
			bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];

		bins.mRegisterFinal = ins->mSrc[0].mFinal;
		mIns.Push(bins);

		ByteCodeInstruction	sins(BC_STORE_REG_32);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
	else
	{
		switch (ins->mOperator)
		{
		case IA_ADD:
		case IA_OR:
		case IA_AND:
		{
			ByteCode	bc = ByteCodeBinRegOperator(ins);
			ByteCode	bci = ByteCodeBinImmOperator(ins);
			ByteCode	bcis = ByteCodeBinSizeImmOperator(ins);

			if (ins->mSrc[1].mTemp < 0)
			{
				if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
				{
					ByteCodeInstruction	bins(bcis);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(bins);
					return;
				}

				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[0].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);

				ByteCodeInstruction	bins(bci);
				bins.mRegister = BC_REG_ACCU;
				bins.mValue = int(ins->mSrc[1].mIntConst);
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				if (ins->mSrc[1].mTemp == ins->mDst.mTemp)
				{
					ByteCodeInstruction	bins(bcis);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = int(ins->mSrc[0].mIntConst);
					mIns.Push(bins);
					return;
				}

				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(lins);

				ByteCodeInstruction	bins(bci);
				bins.mRegister = BC_REG_ACCU;
				bins.mValue = int(ins->mSrc[0].mIntConst);
				mIns.Push(bins);
			}
			else
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);
				mIns.Push(lins);

				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
		}
			break;
		case IA_SUB:
			if (ins->mSrc[1].mTemp < 0)
			{
				if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
				{
					ByteCodeInstruction	bins(BC_BINOP_SUBI_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(bins);
					return;
				}
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);

				ByteCodeInstruction	bins(BC_BINOP_SUBI_16);
				bins.mRegister = BC_REG_ACCU;
				bins.mValue = int(ins->mSrc[1].mIntConst);
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				if (ins->mSrc[1].mTemp == ins->mDst.mTemp)
				{
					ByteCodeInstruction	bins(InterTypeSize[ins->mSrc[0].mType] == 1 ? BC_BINOP_ADDI_8 : BC_BINOP_ADDI_16);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
					bins.mValue = - int(ins->mSrc[0].mIntConst);
					mIns.Push(bins);
					return;
				}
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[0].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(lins);

				ByteCodeInstruction	bins(BC_BINOP_ADDI_16);
				bins.mRegister = BC_REG_ACCU;
				bins.mValue = - int(ins->mSrc[0].mIntConst);
				mIns.Push(bins);
			}
			else
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
				mIns.Push(lins);

				ByteCodeInstruction	bins(BC_BINOP_SUBR_16);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
			break;
		case IA_MUL:
		{
			ByteCode	bc = ByteCodeBinRegOperator(ins);
			ByteCode	bci = ByteCodeBinImmOperator(ins);
			if (ins->mSrc[1].mTemp < 0)
			{
				if (ins->mSrc[1].mIntConst >= 0 && ins->mSrc[1].mIntConst <= 255)
				{
					if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
					{
						ByteCodeInstruction	bins(bci);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
						bins.mRegisterFinal = ins->mSrc[0].mFinal;
						bins.mValue = int(ins->mSrc[1].mIntConst);
						mIns.Push(bins);
						return;
					}

					ByteCodeInstruction	lins(BC_LOAD_REG_16);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);

					ByteCodeInstruction	bins(bci);
					bins.mRegister = BC_REG_ACCU;
					bins.mValue = int(ins->mSrc[1].mIntConst);
					mIns.Push(bins);
				}
				else
				{
					IntConstToAccu(ins->mSrc[1].mIntConst);
					ByteCodeInstruction	bins(bc);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
					bins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(bins);
				}
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				if (ins->mSrc[0].mIntConst >= 0 && ins->mSrc[0].mIntConst <= 255)
				{
					if (ins->mSrc[1].mTemp == ins->mDst.mTemp)
					{
						ByteCodeInstruction	bins(bci);
						bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
						bins.mRegisterFinal = ins->mSrc[1].mFinal;
						bins.mValue = int(ins->mSrc[0].mIntConst);
						mIns.Push(bins);
						return;
					}

					ByteCodeInstruction	lins(BC_LOAD_REG_16);
					lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
					lins.mRegisterFinal = ins->mSrc[1].mFinal;
					mIns.Push(lins);

					ByteCodeInstruction	bins(bci);
					bins.mRegister = BC_REG_ACCU;
					bins.mValue = int(ins->mSrc[0].mIntConst);
					mIns.Push(bins);
				}
				else
				{
					IntConstToAccu(ins->mSrc[0].mIntConst);
					ByteCodeInstruction	bins(bc);
					bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
					bins.mRegisterFinal = ins->mSrc[1].mFinal;
					mIns.Push(bins);
				}
			}
			else
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
				mIns.Push(lins);

				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
		} break;
		case IA_XOR:
		{
			ByteCode	bc = ByteCodeBinRegOperator(ins);
			if (ins->mSrc[1].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[1].mIntConst);
				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[0].mIntConst);
				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				bins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(bins);
			}
			else
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
				mIns.Push(lins);

				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
		} break;
		case IA_DIVS:
		case IA_MODS:
		case IA_DIVU:
		case IA_MODU:
		{
			ByteCode	bc = ByteCodeBinRegOperator(ins);
			if (ins->mSrc[1].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[1].mIntConst);
				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(lins);

				IntConstToAddr(ins->mSrc[0].mIntConst);

				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_ADDR;
				mIns.Push(bins);
			}
			else
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
				mIns.Push(lins);

				ByteCodeInstruction	bins(bc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
		} break;

		case IA_SHL:
		case IA_SHR:
		case IA_SAR:
		{
			ByteCode	rbc = ByteCodeBinRegOperator(ins);
			ByteCode	ibc = ByteCodeBinImmOperator(ins);

			if (ins->mSrc[1].mTemp < 0)
			{
				IntConstToAccu(ins->mSrc[1].mIntConst);

				ByteCodeInstruction	bins(rbc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}
			else if (ins->mSrc[0].mTemp < 0)
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal;
				mIns.Push(lins);

				if (ins->mOperator == IA_SAR && InterTypeSize[ins->mSrc[1].mType] == 1)
				{
					ByteCodeInstruction	xins(BC_CONV_I8_I16);
					xins.mRegister = BC_REG_ACCU;
					mIns.Push(xins);
				}

				ByteCodeInstruction	bins(ibc);
				bins.mValue = int(ins->mSrc[0].mIntConst);
				mIns.Push(bins);
			}
			else
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
				lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
				mIns.Push(lins);

				ByteCodeInstruction	bins(rbc);
				bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
				bins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(bins);
			}

		} break;
		}

		ByteCodeInstruction	sins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_STORE_REG_8 : BC_STORE_REG_16);
		sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
		mIns.Push(sins);
	}
}

void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* proc, InterCodeBasicBlock* sblock)
{
	mIndex = sblock->mIndex;

	int	i = 0;
	while (i < sblock->mInstructions.Size())
	{
		const InterInstruction	* ins = sblock->mInstructions[i];

		switch (ins->mCode)
		{
		case IC_STORE:
			StoreDirectValue(iproc, ins);
			break;
		case IC_LOAD:
			if (i + 1 < sblock->mInstructions.Size() && sblock->mInstructions[i + 1]->mCode == IC_STORE && ins->mDst.mTemp == sblock->mInstructions[i + 1]->mSrc[0].mTemp)
			{
				LoadStoreIndirectValue(iproc, ins, sblock->mInstructions[i + 1]);
				i++;
			}
			else
				LoadDirectValue(iproc, ins);
			break;
		case IC_FILL:
			FillValue(iproc, ins);
			break;
		case IC_COPY:
			CopyValue(iproc, ins);
			break;
		case IC_STRCPY:
			StrcpyValue(iproc, ins);
			break;
		case IC_MALLOC:
			CallMalloc(iproc, ins);
			break;
		case IC_FREE:
			CallFree(iproc, ins);
			break;
		case IC_LOAD_TEMPORARY:
		{
			if (ins->mSrc[0].mTemp != ins->mDst.mTemp)
			{
				switch (ins->mDst.mType)
				{
				case IT_BOOL:
				case IT_INT8:
				{
					ByteCodeInstruction	lins(BC_LOAD_REG_8);
					lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
					ByteCodeInstruction	sins(BC_STORE_REG_8);
					sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(sins);
				} break;
				case IT_INT16:
				case IT_POINTER:
				{
					ByteCodeInstruction	lins(BC_LOAD_REG_16);
					lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
					ByteCodeInstruction	sins(BC_STORE_REG_16);
					sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(sins);
				} break;
				case IT_INT32:
				case IT_FLOAT:
				{
					ByteCodeInstruction	lins(BC_LOAD_REG_32);
					lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
					lins.mRegisterFinal = ins->mSrc[0].mFinal;
					mIns.Push(lins);
					ByteCodeInstruction	sins(BC_STORE_REG_32);
					sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp];
					mIns.Push(sins);
				} break;

				}
			}
		}	break;
		case IC_BINARY_OPERATOR:
			BinaryOperator(iproc, ins);
			break;
		case IC_UNARY_OPERATOR:
			UnaryOperator(iproc, ins);
			break;
		case IC_CONVERSION_OPERATOR:
			NumericConversion(iproc, ins);
			break;
		case IC_LEA:
			LoadEffectiveAddress(iproc, ins);
			break;
		case IC_CONSTANT:
			LoadConstant(iproc, ins);
			break;
		case IC_CALL:
		case IC_DISPATCH:
			CallFunction(iproc, ins);
			break;
		case IC_CALL_NATIVE:
			CallNative(iproc, ins);
			break;
		case IC_ASSEMBLER:
			CallAssembler(iproc, ins);
			break;
		case IC_PUSH_FRAME: 
		{
			ByteCodeInstruction	bins(BC_PUSH_FRAME);
			bins.mValue = int(ins->mConst.mIntConst + 2);
			mIns.Push(bins);

		}	break;
		case IC_POP_FRAME:
		{
			ByteCodeInstruction	bins(BC_POP_FRAME);
			bins.mValue = int(ins->mConst.mIntConst + 2);
			mIns.Push(bins);

		}	break;

		case IC_RELATIONAL_OPERATOR:
			if (i + 1 < sblock->mInstructions.Size() && sblock->mInstructions[i + 1]->mCode == IC_BRANCH && sblock->mInstructions[i + 1]->mSrc[0].mFinal)
			{
				ByteCode code = RelationalOperator(iproc, ins, true);
				this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), code);
				i++;
				return;
			}
			else
			{
				ByteCode code = RelationalOperator(iproc, ins, false);
				if (code == BC_JUMPS)
				{
					IntConstToAccu(1);
				}
				else if (code == BC_NOP)
				{
					IntConstToAccu(0);
				}
				else
				{
					switch (code)
					{
					case BC_BRANCHS_EQ:
					{
						ByteCodeInstruction	iins(BC_OP_INVERT_16);
						mIns.Push(iins);
						ByteCodeInstruction	bins(BC_BINOP_ANDI_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = 1;
						mIns.Push(bins);
					} break;
					case BC_BRANCHS_NE:
					{
						ByteCodeInstruction	bins(BC_BINOP_ANDI_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = 1;
						mIns.Push(bins);
					} break;
					case BC_BRANCHS_GT:
					{
						ByteCodeInstruction	ains(BC_BINOP_ADDI_16);
						ains.mRegister = BC_REG_ACCU;
						ains.mValue = 1;
						mIns.Push(ains);
						ByteCodeInstruction	sins(BC_BINOP_SHRI_U16);
						sins.mValue = 1;
						mIns.Push(sins);
					} break;
					case BC_BRANCHS_GE:
					{
						ByteCodeInstruction	sins(BC_BINOP_CMPUI_8);
						sins.mValue = 0xff;
						mIns.Push(sins);
					} break;
					case BC_BRANCHS_LT:
					{
						ByteCodeInstruction	sins(BC_BINOP_SHRI_U16);
						sins.mValue = 1;
						mIns.Push(sins);
						ByteCodeInstruction	bins(BC_BINOP_ANDI_16);
						bins.mRegister = BC_REG_ACCU;
						bins.mValue = 1;
						mIns.Push(bins);
					} break;
					case BC_BRANCHS_LE:
					{
						ByteCodeInstruction	sins(BC_BINOP_CMPSI_8);
						sins.mValue = 1;
						mIns.Push(sins);
					} break;
					}
				}
				ByteCodeInstruction	sins(StoreTypedTmpCodes[ins->mDst.mType]);
				sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(sins);
			}
			break;

		case IC_RETURN_VALUE:
			if (ins->mSrc[0].mTemp < 0)
				IntConstToAccu(ins->mSrc[0].mIntConst);
			else if (ins->mSrc[0].mType == IT_FLOAT || ins->mSrc[0].mType == IT_INT32)
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_32);
				lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);
			}
			else
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[0].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);
			}

			mExitLive = LIVE_ACCU;

			this->Close(proc->exitBlock, nullptr, BC_JUMPS);
			return;

		case IC_RETURN:
			this->Close(proc->exitBlock, nullptr, BC_JUMPS);
			return;

		case IC_TYPECAST:
			if (ins->mSrc[0].mTemp >= 0 && ins->mDst.mTemp != ins->mSrc[0].mTemp)
			{
				ByteCodeInstruction	lins(BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);
				ByteCodeInstruction	sins(InterTypeSize[ins->mDst.mType] == 1 ? BC_STORE_REG_8 : BC_STORE_REG_16);
				sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp];
				mIns.Push(sins);
			}
			break;

		case IC_BRANCH:
			if (ins->mSrc[0].mTemp < 0)
			{
				if (ins->mSrc[0].mIntConst == 0)
					this->Close(proc->CompileBlock(iproc, sblock->mFalseJump), nullptr, BC_JUMPS);
				else
					this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, BC_JUMPS);
			}
			else
			{
				ByteCodeInstruction	lins(InterTypeSize[ins->mSrc[0].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
				lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp];
				lins.mRegisterFinal = ins->mSrc[0].mFinal;
				mIns.Push(lins);

				this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), BC_BRANCHS_NE);
			}
			return;

		case IC_UNREACHABLE:
			this->Close(proc->exitBlock, nullptr, BC_JUMPS);
			return;
		}

		i++;
	}

	this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, BC_JUMPS);
}

void ByteCodeBasicBlock::CountEntries(ByteCodeBasicBlock* fromJump)
{
	mNumEntries++;

	if (!mVisited)
	{
		mVisited = true;

		if (mTrueJump)
			mTrueJump->CountEntries(this);
		if (mFalseJump)
			mFalseJump->CountEntries(this);
	}
}

void ByteCodeBasicBlock::CollectEntryBlocks(ByteCodeBasicBlock* block)
{
	if (block)
		mEntryBlocks.Push(block);

	if (!mVisited)
	{
		mVisited = true;

		if (mTrueJump)
			mTrueJump->CollectEntryBlocks(this);
		if (mFalseJump)
			mFalseJump->CollectEntryBlocks(this);
	}
}

bool ByteCodeBasicBlock::SameTail(ByteCodeInstruction& ins)
{
	if (mIns.Size() > 0)
		return mIns[mIns.Size() - 1].IsSame(ins);
	else
		return false;
}

bool ByteCodeBasicBlock::MergeBasicBlocks(void)
{
	bool	changed = false;

	if (!mVisited)
	{
		mVisited = true;

		if (!mLocked)
		{
			while (mTrueJump && !mFalseJump && mTrueJump->mNumEntries == 1 && mTrueJump != this && !mTrueJump->mLocked)
			{
				for (int i = 0; i < mTrueJump->mIns.Size(); i++)
					mIns.Push(mTrueJump->mIns[i]);
				mBranch = mTrueJump->mBranch;
				mFalseJump = mTrueJump->mFalseJump;
				mTrueJump = mTrueJump->mTrueJump;
				changed = true;
			}

			while (mTrueJump && mTrueJump->mIns.Size() == 0 && !mTrueJump->mFalseJump && !mTrueJump->mLocked && mTrueJump != this && mTrueJump->mTrueJump != mTrueJump)
			{
				mTrueJump->mNumEntries--;
				mTrueJump = mTrueJump->mTrueJump;
				mTrueJump->mNumEntries++;
				changed = true;
			}

			while (mFalseJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this && mFalseJump->mTrueJump != mFalseJump)
			{
				mFalseJump->mNumEntries--;
				mFalseJump = mFalseJump->mTrueJump;
				mFalseJump->mNumEntries++;
				changed = true;
			}

			if (mTrueJump && mTrueJump == mFalseJump)
			{
				mBranch = BC_JUMPS;
				mFalseJump = nullptr;
				changed = true;
			}
		}

		if (mTrueJump)
			mTrueJump->MergeBasicBlocks();
		if (mFalseJump)
			mFalseJump->MergeBasicBlocks();
	}
	return changed;
}


bool ByteCodeBasicBlock::JoinTailCodeSequences(void)
{
	bool	changed = false;

	if (!mVisited)
	{
		mVisited = true;

		if (mEntryBlocks.Size() > 1)
		{
			int i = 0;
			while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mBranch == BC_JUMPS)
				i++;
			if (i == mEntryBlocks.Size())
			{
				ByteCodeBasicBlock* eb = mEntryBlocks[0];

				while (eb->mIns.Size() > 0)
				{
					ByteCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
					i = 1;
					while (i < mEntryBlocks.Size() && mEntryBlocks[i]->SameTail(ins))
						i++;
					if (i == mEntryBlocks.Size())
					{
						mIns.Insert(0, ins);
						for (int i = 0; i < mEntryBlocks.Size(); i++)
						{
							ByteCodeBasicBlock* b = mEntryBlocks[i];
							b->mIns.SetSize(b->mIns.Size() - 1);
							if (mIns.Size() == 1)
								mExitLive |= b->mExitLive;
							b->mExitLive = LIVE_ACCU;
						}
						changed = true;
					}
					else
						break;
				}
			}
		}

		if (mTrueJump && mFalseJump && mTrueJump->mEntryBlocks.Size() == 1 && mFalseJump->mEntryBlocks.Size() == 1)
		{
			while (mTrueJump->mIns.Size() > 0 && mFalseJump->mIns.Size() > 0 && !mTrueJump->mIns[0].ChangesAccu() && mTrueJump->mIns[0].IsSame(mFalseJump->mIns[0]))
			{
				mIns.Push(mTrueJump->mIns[0]);
				mTrueJump->mIns.Remove(0);
				mFalseJump->mIns.Remove(0);
			}
		}

		if (mTrueJump && mTrueJump->JoinTailCodeSequences())
			changed = true;
		if (mFalseJump && mFalseJump->JoinTailCodeSequences())
			changed = true;
	}

	return changed;
}

bool ByteCodeBasicBlock::PropagateAccuCrossBorder(int accu, int addr)
{
	bool	changed = false;

	if (!mVisited)
	{
		mVisited = true;
		if (mEntryBlocks.Size() != 1)
			accu = addr = -1;
		else
		{
			ByteCodeBasicBlock* p = mEntryBlocks[0];

			int	s = p->mIns.Size();

			if (p->mIns.Size() >= 2 && mIns.Size() == 2 && 
				mIns[1].IsCompare() && p->mIns[s - 1].IsSame(mIns[1]) &&
				((mIns[0].mCode == BC_LOAD_REG_16 && (p->mIns[s - 2].mCode == BC_LOAD_REG_16 || p->mIns[s - 2].mCode == BC_STORE_REG_16)) ||
				 (mIns[0].mCode == BC_LOAD_REG_8  && (p->mIns[s - 2].mCode == BC_LOAD_REG_8  || p->mIns[s - 2].mCode == BC_STORE_REG_8))) && 
				p->mIns[s - 2].mRegister == mIns[0].mRegister)
			{
				mIns.SetSize(0);
			}
		}

		int j = 0;
		for (int i = 0; i < mIns.Size(); i++)
		{
			if (mIns[i].mCode == BC_ADDR_REG && addr == mIns[i].mRegister ||
				mIns[i].mCode == BC_LOAD_REG_16 && accu == mIns[i].mRegister ||
				mIns[i].mCode == BC_STORE_REG_16 && accu == mIns[i].mRegister)
			{
				changed = true;
			}
			else
			{
				if (mIns[i].mCode == BC_ADDR_REG)
					addr = mIns[i].mRegister;
				else if (mIns[i].mCode == BC_LOAD_REG_16)
					accu = mIns[i].mRegister;
				else if (mIns[i].mCode == BC_STORE_REG_16)
				{
					accu = mIns[i].mRegister;
					if (addr == mIns[i].mRegister)
						addr = -1;
				}
				else
				{
					if (accu >= 0 && mIns[i].ChangesRegister(accu))
						accu = -1;
					if (addr >= 0 && mIns[i].ChangesRegister(addr))
						addr = -1;

					if (accu >= 0 && mIns[i].ChangesAccu())
						accu = -1;
					if (addr >= 0 && mIns[i].ChangesAddr())
						addr = -1;
				}

				if (i != j)
				{
					mIns[j] = mIns[i];
				}
				j++;
			}
		}
		mIns.SetSize(j);

		if (mTrueJump && mTrueJump->PropagateAccuCrossBorder(accu, addr))
			changed = true;
		if (mFalseJump && mFalseJump->PropagateAccuCrossBorder(accu, addr))
			changed = true;
	}

	return changed;
}


bool ByteCodeBasicBlock::PeepHoleOptimizer(int phase)
{
	bool	changed = false;

	if (!mVisited)
	{
		mVisited = true;

		int	accuReg = -1;

		bool	progress = false;
		do {
			progress = false;

			int i = 0;
			int j = 0;
			while (i < mIns.Size())
			{
				if (mIns[i].mCode == BC_NOP)
					;
				else
				{
					if (i != j)
						mIns[j] = mIns[i];
					j++;
				}
				i++;
			}
			mIns.SetSize(j);

			// check reg addr up
			// 
#if 1
			for (int i = 2; i < mIns.Size(); i++)
			{
				if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister != BC_REG_ACCU && mIns[i].mRegisterFinal)
				{
					int j = i;
					while (j > 0 && !mIns[j - 1].ChangesAddr() && !mIns[j - 1].UsesAddr() && !mIns[j - 1].ChangesRegister(mIns[j].mRegister) && !mIns[j - 1].UsesRegister(mIns[j].mRegister))
					{
						ByteCodeInstruction	bins = mIns[j - 1];
						mIns[j - 1] = mIns[j];
						mIns[j] = bins;
						j--;
					}
				}
			}
#endif
#if 1
			if (phase == 2)
			{
				for (int i = 2; i < mIns.Size(); i++)
				{
					if (mIns[i].mCode >= BC_LOAD_ADDR_8 && mIns[i].mCode <= BC_STORE_ADDR_32)
					{
						int j = i;
						while (j > 0 && !mIns[j - 1].ChangesAddr() && !mIns[j - 1].UsesAddr() && !mIns[j - 1].ChangesRegister(mIns[j].mRegister) && !mIns[j - 1].UsesRegister(mIns[j].mRegister))
						{
							ByteCodeInstruction	bins = mIns[j - 1];
							mIns[j - 1] = mIns[j];
							mIns[j] = bins;
							j--;
						}
					}
				}
			}
#endif

			// mark accu live

			uint32	live = mExitLive;
			uint32	aused = mExitLive ? 0xffffffff : 0x00000000;

			if (mBranch != BC_JUMPS && mBranch != BC_NOP)
			{
				live |= LIVE_ACCU;
				aused = 0x0000ffff;
			}

			for (int i = mIns.Size() - 1; i >= 0; i--)
			{
				mIns[i].mLive = live;

				if (mIns[i].ChangesAccu())
					live &= ~LIVE_ACCU;
				if (mIns[i].UsesAccu())
					live |= LIVE_ACCU;
			}

//			assert(!(live & LIVE_ACCU));

			int	accuTemp = -1, addrTemp = -1, accuVal = 0, accuTempByte = -1;
			bool	accuConst = false, accuLong = false;

			for (int i = 0; i < mIns.Size(); i++)
			{
				if (i + 4 < mIns.Size())
				{
#if 1
					if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 &&
						(mIns[i + 3].mCode == BC_BINOP_ADDR_16 || mIns[i + 3].mCode == BC_BINOP_SUBR_16) && mIns[i + 3].mRegister == mIns[i + 1].mRegister && mIns[i + 3].mRegisterFinal &&
						mIns[i + 4].mCode == BC_STORE_REG_8 && !(mIns[i + 4].mLive & LIVE_ACCU))
					{
						mIns[i + 3].mRegister = mIns[i + 0].mRegister;
						mIns[i + 3].mRegisterFinal = mIns[i + 0].mRegisterFinal;
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
#if 1
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						!mIns[i + 2].ChangesAccu() && !mIns[i + 2].UsesAccu() && !mIns[i + 2].UsesRegister(mIns[i + 1].mRegister) && !mIns[i + 2].ChangesRegister(mIns[i + 0].mRegister) && !mIns[i + 2].ChangesRegister(mIns[i + 1].mRegister) &&
						!mIns[i + 3].ChangesAccu() && !mIns[i + 3].UsesAccu() && !mIns[i + 3].UsesRegister(mIns[i + 1].mRegister) && !mIns[i + 3].ChangesRegister(mIns[i + 0].mRegister) && !mIns[i + 3].ChangesRegister(mIns[i + 1].mRegister) &&
						mIns[i + 4].mCode == BC_ADDR_REG && mIns[i + 4].mRegister == mIns[i + 1].mRegister && mIns[i + 4].mRegisterFinal)
					{
						mIns[i + 4].mCode = BC_LEA_ACCU_INDEX;
						mIns[i + 4].mRegister = mIns[i + 0].mRegister;
						mIns[i + 4].mRegisterFinal = mIns[i + 0].mRegisterFinal;
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mLive |= LIVE_ACCU;
						mIns[i + 3].mLive |= LIVE_ACCU;
						progress = true;
					}
#endif
				}

#if 1
				if (i + 3 < mIns.Size())
				{
					if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].IsIntegerConst() && mIns[i + 2].mRegister == BC_REG_ACCU &&
						mIns[i + 3].IsShiftByRegister() && mIns[i + 3].mRegister == mIns[i + 1].mRegister && mIns[i + 3].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 3].mRegister = mIns[i + 0].mRegister;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_LEA_ABS && mIns[i + 1].mRegister != BC_REG_ACCU &&
						mIns[i + 2].mCode == BC_BINOP_ADDR_16 && mIns[i + 2].mRegister == mIns[i + 1].mRegister && mIns[i + 2].mRegisterFinal &&
						mIns[i + 3].mCode == BC_ADDR_REG && mIns[i + 3].mRegister == BC_REG_ACCU && !(mIns[i + 3].mLive & LIVE_ACCU))
					{
						mIns[i + 1].mCode = BC_LEA_ABS_INDEX_U8;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						mIns[i + 1].mRegisterFinal = mIns[i + 0].mRegisterFinal;
						mIns[i + 1].mLive &= ~LIVE_ACCU;

						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						mIns[i + 3].mCode = BC_NOP;
						progress = true;
					}
#if 1
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						!mIns[i + 1].ChangesAccu() && !mIns[i + 1].ChangesRegister(mIns[i + 0].mRegister) &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 &&
						mIns[i + 3].IsCommutative() && mIns[i + 3].mRegister == mIns[i + 0].mRegister)
					{
						mIns[i + 2].mCode = mIns[i + 3].mCode;
						mIns[i + 3].mCode = BC_NOP;
						if (mIns[i + 3].mRegisterFinal && !mIns[i + 1].UsesRegister(mIns[i + 0].mRegister))
							mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
#endif
#if 1
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_BINOP_MULI8_16 && mIns[i + 1].mRegister == mIns[i + 0].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i + 2].mRegister != mIns[i + 0].mRegister &&
						mIns[i + 3].IsCommutative() && mIns[i + 3].mRegister == mIns[i + 0].mRegister && mIns[i + 3].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i + 1].mLive |= LIVE_ACCU;
						mIns[i + 2].mCode = BC_NOP;
						mIns[i + 3].mRegister = mIns[i + 2].mRegister;
						mIns[i + 3].mRegisterFinal = mIns[i + 2].mRegisterFinal;
						progress = true;
					}
#endif
				}
#endif
#if 1
				if (i + 2 < mIns.Size())
				{
					if (mIns[i].mCode == BC_LOAD_LOCAL_16 &&
						mIns[i + 1].mCode == BC_LOAD_LOCAL_16 && mIns[i + 1].mRegister != BC_REG_ACCU && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i + 2].mRegister == mIns[i].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 &&
						!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 2].mCode = BC_NOP;
						if (mIns[i + 2].mRegisterFinal)
							mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_8 &&
						!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 2].mRegister = BC_REG_ACCU;
						if (mIns[i + 2].mRegisterFinal)
							mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 &&
						(mIns[i + 1].mCode == BC_BINOP_ADDI_16 || mIns[i + 1].mCode == BC_BINOP_MULI8_16 || mIns[i + 1].mCode == BC_BINOP_ANDI_16 || mIns[i + 1].mCode == BC_BINOP_ORI_16) && mIns[i + 1].mRegister == mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = BC_REG_ACCU;
						if (mIns[i + 2].mRegisterFinal)
							mIns[i + 2].mCode = BC_NOP;
						else
							mIns[i + 2].mCode = BC_STORE_REG_16;

						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_32 &&
						!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_32 && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 2].mCode = BC_NOP;
						if (mIns[i + 2].mRegisterFinal)
							mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 &&
						!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].IsStore() && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i].mCode = BC_NOP;
						mIns[i + 2].mRegister = BC_REG_ACCU;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 &&
						!mIns[i + 1].ChangesAddr() && !mIns[i + 1].UsesAddr() && mIns[i + 1].mRegister != mIns[i].mRegister &&
						mIns[i + 2].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i].mCode = BC_ADDR_REG;
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
						mIns[i + 0].LoadsRegister(mIns[i + 2].mRegister) && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = mIns[i + 2].mCode;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
						mIns[i + 0].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;;
						mIns[i + 1].mCode = mIns[i + 2].mCode;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_32 &&
						mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
						mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						if (mIns[i + 2].mRegisterFinal)
							mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mRegister = mIns[i + 1].mRegister;
						mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_32 &&
						mIns[i + 1].LoadsRegister(BC_REG_ACCU) &&
						mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 2].mRegister;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
						mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister)
					{
						if (mIns[i + 2].mRegisterFinal)
							mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mRegister = mIns[i + 1].mRegister;
						mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						progress = true;
					}
					else if (mIns[i + 0].mCode == BC_STORE_REG_32 &&
						mIns[i + 2].mCode == BC_BINOP_CMP_F32 && mIns[i + 2].mRegister == mIns[i + 0].mRegister && mIns[i + 2].mRegisterFinal &&
						mIns[i + 1].LoadsRegister(BC_REG_ACCU) && i + 3 == mIns.Size())
					{
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						mIns[i + 0].mCode = BC_NOP;
						mBranch = TransposeBranchCondition(mBranch);
						progress = true;
					}
					else if (mIns[i + 0].mCode == BC_LOAD_REG_16 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_8 &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 0].mRegister == mIns[i + 2].mRegister)
					{
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 0].mCode == BC_CONST_16 && mIns[i + 2].mCode == BC_CONST_16 && 
							!mIns[i + 0].mRelocate && !mIns[i + 2].mRelocate &&
							mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 0].mValue == mIns[i + 2].mValue && 
							!mIns[i + 1].ChangesRegister(mIns[i + 0].mRegister))
					{
						if (mIns[i + 0].mRegister == BC_REG_ACCU)
							mIns[i + 1].mLive |= LIVE_ACCU;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 0].IsLocalStore() && mIns[i + 2].IsSame(mIns[i + 0]) && !mIns[i + 1].IsLocalAccess() && mIns[i + 1].mCode != BC_JSR)
					{
						mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_LOAD_LOCAL_16 && mIns[i + 1].mRegister == BC_REG_ACCU &&
						mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_8 &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_8 &&
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mRegister == mIns[i + 1].mRegister &&
						mIns[i + 2].mCode == BC_STORE_REG_8)
					{
						if (mIns[i + 1].mRegisterFinal)
							mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mRegister == mIns[i + 1].mRegister &&
						mIns[i + 2].mCode == BC_STORE_REG_8)
					{
						if (mIns[i + 1].mRegisterFinal)
							mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#if 1
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].LoadsRegister(BC_REG_ACCU) &&
						mIns[i + 2].IsCommutative() && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						progress = true;
					}
#endif
#if 1
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 &&
						mIns[i + 2].mCode == BC_BINOP_SUBR_16 && mIns[i].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_OP_NEGATE_16;
						mIns[i + 1].mCode = BC_BINOP_ADDR_16;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
#endif
					else if (
						mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 2].mRegister == BC_REG_ACCU && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						mIns[i + 0].mLive &= ~LIVE_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}

					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].mCode == BC_LEA_ABS_INDEX && mIns[i + 2].mRegister == mIns[i + 1].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU) && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 2].mCode = BC_LEA_ABS_INDEX_U8;
						mIns[i + 2].mRegister = mIns[i + 0].mRegister;
						mIns[i + 2].mRegisterFinal = mIns[i + 0].mRegisterFinal;
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}

					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						(mIns[i + 1].mCode == BC_BINOP_MULI8_16 || mIns[i + 1].mCode == BC_BINOP_ADDI_16) && mIns[i + 1].mRegister == mIns[i + 0].mRegister &&
						(mIns[i + 2].mCode == BC_STORE_ABS_16 || mIns[i + 2].mCode == BC_STORE_LOCAL_16 || mIns[i + 2].mCode == BC_STORE_FRAME_16 || mIns[i + 2].mCode == BC_STORE_ADDR_16) && mIns[i + 2].mRegister == mIns[i + 0].mRegister &&
						mIns[i + 2].mRegisterFinal && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i + 2].mRegister = BC_REG_ACCU;
						mIns[i + 1].mLive |= LIVE_ACCU;
						progress = true;
					}

					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].mCode == BC_BINOP_ANDI_16 && mIns[i + 2].mRegister == mIns[i + 1].mRegister && mIns[i + 2].mValue == 0x00ff)
					{
						mIns[i + 2].mCode = BC_STORE_REG_16;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 0].mLive |= LIVE_ACCU;
						progress = true;
					}

					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_BINOP_ADDI_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 2].mRegister == mIns[i + 0].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_LOAD_REG_8;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 0].mLive |= LIVE_ACCU;

						mIns[i + 1].mCode = BC_BINOP_ADDI_8;
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i + 1].mLive |= LIVE_ACCU;

						mIns[i + 2].mCode = BC_NOP;

						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_BINOP_SHRI_U16 &&
						mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 2].mRegister == BC_REG_ACCU)
					{
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LEA_ABS &&
						mIns[i + 1].mCode == BC_BINOP_ADDR_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal &&
						mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 2].mRegister == BC_REG_ACCU && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_BINOP_ADDA_16 &&
						mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 1].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 0].mRegister = mIns[i + 2].mRegister;
						mIns[i + 0].mRegisterFinal = true;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_16 &&
						mIns[i + 1].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 2].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_BINOP_ADDA_16;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_16 &&
						mIns[i + 1].mCode == BC_BINOP_SHLI_16 && mIns[i + 1].mValue == 1 &&
						mIns[i + 2].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegisterFinal = false;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_BINOP_ADDA_16;
						progress = true;
					}
					else if (
						(mIns[i + 0].mCode == BC_LOAD_LOCAL_16 || mIns[i + 0].mCode == BC_LOAD_ABS_16 || mIns[i + 0].mCode == BC_LOAD_ADDR_16 ||
							mIns[i + 0].mCode == BC_LOAD_LOCAL_U8 || mIns[i + 0].mCode == BC_LOAD_ABS_U8 || mIns[i + 0].mCode == BC_LOAD_ADDR_U8) &&
						mIns[i + 1].mCode == BC_BINOP_ADDR_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal &&
						mIns[i + 2].mCode == BC_STORE_REG_16 && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegister = mIns[i + 2].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_BINOP_ADDA_16;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 2].mCode == BC_LEA_ABS_INDEX && mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal &&
						(mIns[i + 1].mCode == BC_BINOP_ADDI_16 || mIns[i + 1].mCode == BC_BINOP_ANDI_16 || mIns[i + 1].mCode == BC_BINOP_ORI_16 || mIns[i + 1].mCode == BC_BINOP_MULI8_16) &&
						mIns[i + 1].mRegister == mIns[i + 0].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i + 2].mRegister = BC_REG_ACCU;
						mIns[i + 1].mLive |= LIVE_ACCU;
						progress = true;
					}

					else if (
						mIns[i + 0].mCode == BC_LEA_ABS &&
						mIns[i + 1].mCode == BC_BINOP_ADDA_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister &&
						mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mCode = BC_NOP;
						progress = true;
					}

#if 1
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_LEA_ABS &&
						mIns[i + 2].mCode == BC_LEA_ACCU_INDEX && mIns[i + 1].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal && !(mIns[i + 2].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_LEA_ABS_INDEX_U8;
						mIns[i + 2].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						progress = true;
					}
#endif
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDI_8 && mIns[i + 0].mValue == 1 &&
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 0].mRegister &&
						mIns[i + 2].mCode == BC_BINOP_CMPUI_8)
					{
						mIns[i + 2].mCode = BC_LOOP_U8;
						mIns[i + 2].mRegister = mIns[i + 0].mRegister;
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}

#if 1
					else if (
						i + 3 == mIns.Size() && mFalseJump &&
						mIns[i + 0].mCode == BC_STORE_REG_8 &&
						mIns[i + 1].mCode == BC_LOAD_REG_8 &&
						mIns[i + 2].mCode == BC_BINOP_CMPUR_8 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && !(mExitLive & LIVE_ACCU) && mIns[i + 2].mRegisterFinal
						)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mRegister = mIns[i + 1].mRegister;
						mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						mBranch = TransposeBranchCondition(mBranch);
						progress = true;
					}
					else if (
						i + 3 == mIns.Size() && mFalseJump &&
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 &&
						mIns[i + 2].mCode == BC_BINOP_CMPUR_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && !(mExitLive & LIVE_ACCU) && mIns[i + 2].mRegisterFinal
						)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_NOP;
						mIns[i + 2].mRegister = mIns[i + 1].mRegister;
						mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
						mBranch = TransposeBranchCondition(mBranch);
						progress = true;
					}

#endif
					
				}
#endif
#if 1
				if (i + 1 < mIns.Size())
				{
					if (mIns[i].mCode == BC_STORE_REG_16 && mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 1].mCode = BC_NOP;
						if (mIns[i + 1].mRegisterFinal)
							mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_LOAD_REG_16 && mIns[i + 1].mCode == BC_STORE_REG_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_32 && mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 1].mCode = BC_NOP;
						if (mIns[i + 1].mRegisterFinal)
							mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_LOAD_REG_32 && mIns[i + 1].mCode == BC_STORE_REG_32 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mCode = BC_ADDR_REG;
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 0].mCode == BC_LOAD_REG_16 && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 1].mRegister == BC_REG_ACCU && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_ADDR_REG;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i].LoadsRegister(mIns[i + 1].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i].LoadsRegister(mIns[i + 1].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_16 && mIns[i + 1].StoresRegister(mIns[i].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_32 && mIns[i + 1].StoresRegister(mIns[i].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i].LoadsRegister(mIns[i + 1].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_LOAD_LOCAL_16 && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ADDR;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						(mIns[i + 0].mCode == BC_LEA_FRAME || mIns[i + 0].mCode == BC_LEA_LOCAL || mIns[i + 0].mCode == BC_LEA_ABS) && 
						mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mRegister = BC_REG_ADDR;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_BINOP_ADDI_16 && mIns[i + 1].mCode == BC_BINOP_ADDI_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 1].mValue += mIns[i].mValue;
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_BINOP_ADDI_16 && mIns[i].mValue == 0)
					{
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
#if 1
					else if (mIns[i].mCode == BC_STORE_REG_8 && mIns[i + 1].StoresRegister(mIns[i].mRegister) && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_STORE_REG_8 && mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_LOAD_REG_16 && mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == BC_REG_ACCU)
					{
						mIns[i].mCode = BC_LOAD_REG_8;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if ((mIns[i].mCode == BC_CONST_16 || mIns[i].mCode == BC_CONST_P8 || mIns[i].mCode == BC_CONST_N8) &&
							(mIns[i + 1].mCode == BC_CONST_16 || mIns[i + 1].mCode == BC_CONST_P8 || mIns[i + 1].mCode == BC_CONST_N8 || mIns[i + 1].mCode == BC_CONST_32) && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_CONST_32 && mIns[i + 1].mCode == BC_CONST_32 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i].mCode == BC_CONST_8 && mIns[i + 1].mCode == BC_CONST_8 && mIns[i].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i].mCode = BC_NOP;
						progress = true;
					}
#endif
#if 1
					else if (mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mCode == BC_LOAD_ADDR_8 && mIns[i + 1].mRegisterFinal && mIns[i + 0].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 0].mCode = BC_LOAD_ADDR_U8;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 0].mCode == BC_LOAD_ABS_8 && mIns[i + 1].mRegisterFinal && mIns[i + 0].mRegister == mIns[i + 1].mRegister)
					{
						mIns[i + 0].mCode = BC_LOAD_ABS_U8;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_BINOP_ANDI_16 && mIns[i + 0].mValue == 0x00ff &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister == mIns[i + 0].mRegister)
					{
						mIns[i + 0].mCode = BC_LOAD_REG_8;
						mIns[i + 0].mLive |= LIVE_ACCU;

						if (!mIns[i + 1].mRegisterFinal)
							mIns[i + 1].mCode = BC_STORE_REG_16;
						else
							mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 && 
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == BC_REG_ACCU)
					{
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 && 
						mIns[i + 1].mCode == BC_BINOP_SHRI_I16)
					{
						mIns[i + 1].mCode = BC_BINOP_SHRI_U16;
						progress = true;
					}
					else if (
						(mIns[i + 0].mCode == BC_STORE_REG_16 || mIns[i + 0].mCode == BC_STORE_REG_8) && 
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 0].mRegister)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						if (mIns[i + 1].mRegisterFinal)
							mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_STORE_REG_16 &&
						(mIns[i + 1].mCode == BC_STORE_LOCAL_16 || mIns[i + 1].mCode == BC_STORE_ABS_16 || mIns[i + 1].mCode == BC_STORE_ADDR_16 || mIns[i + 1].mCode == BC_STORE_FRAME_16) && 
						mIns[i + 1].mRegister == mIns[i + 0].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mRegister = BC_REG_ACCU;
						mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}

					if ((mIns[i].mCode == BC_LOAD_ABS_U8 || mIns[i].mCode == BC_LOAD_ADDR_U8 || mIns[i].mCode == BC_LOAD_ABS_16 || mIns[i].mCode == BC_LOAD_ADDR_16) && mIns[i].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_STORE_REG_16 && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
					else if (
						mIns[i + 1].mCode == BC_STORE_REG_8 && !(mIns[i + 1].mLive & LIVE_ACCU) && mIns[i + 1].mRegister != BC_REG_ADDR &&
						(mIns[i + 0].mCode == BC_LOAD_ADDR_8 || mIns[i + 0].mCode == BC_LOAD_ADDR_U8 || mIns[i + 0].mCode == BC_LOAD_ADDR_16 || mIns[i + 0].mCode == BC_LOAD_ADDR_32) && 
						mIns[i + 0].mRegister == BC_REG_ACCU)	
					{
						mIns[i + 0].mCode = BC_LOAD_ADDR_8;
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 1].mCode == BC_STORE_REG_8 && !(mIns[i + 1].mLive & LIVE_ACCU) && mIns[i + 1].mRegister != BC_REG_ADDR &&
						(mIns[i + 0].mCode == BC_LOAD_ABS_8 || mIns[i + 0].mCode == BC_LOAD_ABS_U8 || mIns[i + 0].mCode == BC_LOAD_ABS_16 || mIns[i + 0].mCode == BC_LOAD_ABS_32) &&
						mIns[i + 0].mRegister == BC_REG_ACCU)
					{
						mIns[i + 0].mCode = BC_LOAD_ABS_8;
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 1].mCode == BC_STORE_REG_8 && !(mIns[i + 1].mLive & LIVE_ACCU) && mIns[i + 1].mRegister != BC_REG_ADDR &&
						(mIns[i + 0].mCode == BC_LOAD_LOCAL_8 || mIns[i + 0].mCode == BC_LOAD_LOCAL_U8 || mIns[i + 0].mCode == BC_LOAD_LOCAL_16 || mIns[i + 0].mCode == BC_LOAD_LOCAL_32) &&
						mIns[i + 0].mRegister == BC_REG_ACCU)
					{
						mIns[i + 0].mCode = BC_LOAD_LOCAL_8;
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_REG_8 && !(mIns[i + 1].mLive & LIVE_ACCU) && 
						(mIns[i + 1].mCode == BC_STORE_ABS_8 || mIns[i + 1].mCode == BC_STORE_LOCAL_8 || mIns[i + 1].mCode == BC_STORE_ADDR_8 || mIns[i + 1].mCode == BC_STORE_FRAME_8) &&
						mIns[i + 1].mRegister == BC_REG_ACCU)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						mIns[i + 1].mRegisterFinal = mIns[i + 0].mRegisterFinal;
						progress = true;
					}

#if 1
					else if (
						mIns[i + 0].mCode == BC_CONST_16 && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_STORE_REG_8 && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_CONST_8;
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
					else if (
						mIns[i + 0].mCode == BC_CONST_16 && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_STORE_REG_16 && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						(mIns[i + 0].mCode == BC_LEA_LOCAL || mIns[i + 0].mCode == BC_LEA_ABS || mIns[i + 0].mCode == BC_LEA_FRAME) && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_STORE_REG_16 && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#if 1
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 1].mRegister == BC_REG_ACCU && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_LEA_ACCU_INDEX;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
#if 1
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDA_16 &&
						mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 1].mRegister == mIns[i + 0].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_LEA_ACCU_INDEX;
						progress = true;
					}
#endif
					else if (
						mIns[i + 0].mCode == BC_LOAD_LOCAL_8 &&
						mIns[i + 1].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 0].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_LOAD_LOCAL_U8;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 0].mLive |= LIVE_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LOAD_LOCAL_U8 && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_STORE_REG_16 && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mRegister = mIns[i + 1].mRegister;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#if 1
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDR_16 &&
						mIns[i + 1].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 1].mCode = BC_BINOP_ADDA_16;
						mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDA_16 &&
						mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mCode = BC_BINOP_ADDR_16;
						mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_BINOP_ADDA_16 &&
						mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 1].mCode = BC_LEA_ACCU_INDEX;
						mIns[i + 0].mCode = BC_NOP;
						progress = true;
					}
#endif
#if 1
					else if (
						mIns[i + 0].mCode == BC_LOAD_ABS_16 && 
						mIns[i + 1].mCode == BC_ADDR_REG && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_LOAD_ABS_ADDR;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
					else if (
						(mIns[i + 0].mCode == BC_LOAD_ADDR_U8 || mIns[i + 0].mCode == BC_LOAD_ABS_U8 || mIns[i + 0].mCode == BC_LOAD_LOCAL_U8) &&
						mIns[i + 1].mCode == BC_BINOP_ANDI_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister)
					{
						// upper byte is already zero
						mIns[i + 1].mCode = BC_BINOP_ANDI_8;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_BINOP_ORI_16 &&
						mIns[i + 1].mCode == BC_STORE_ADDR_8 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_BINOP_ORI_8;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_BINOP_ANDI_16 &&
						mIns[i + 1].mCode == BC_STORE_ADDR_8 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_BINOP_ANDI_8;
						progress = true;
					}
					else if (
						mIns[i + 0].mCode == BC_LEA_ABS && 
						mIns[i + 1].mCode == BC_LEA_ACCU_INDEX && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 0].mRegister = BC_REG_ACCU;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}

#if 1
					else if (
						mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
						mIns[i + 1].mCode == BC_LEA_ACCU_INDEX && !(mIns[i + 1].mLive & LIVE_ACCU))
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mCode = BC_LEA_ABS_INDEX;
						mIns[i + 1].mLinkerObject = mIns[i + 0].mLinkerObject;
						mIns[i + 1].mValue = mIns[i + 0].mValue;
						mIns[i + 1].mRelocate = mIns[i + 0].mRelocate;
						progress = true;
					}
#endif
#if 1
					else if (
						i + 2 == mIns.Size() && mFalseJump &&
						mIns[i + 0].mCode == BC_LOAD_REG_8 &&
						mIns[i + 1].mCode == BC_BINOP_CMPUR_8 && accuTempByte == mIns[i + 1].mRegister && !(mExitLive & LIVE_ACCU)
						)
					{
						mIns[i + 0].mCode = BC_NOP;
						mIns[i + 1].mRegister = mIns[i + 0].mRegister;
						mBranch = TransposeBranchCondition(mBranch);
						progress = true;
					}

#endif

#if 0
					else if ((mIns[i].mCode == BC_LOAD_LOCAL_16 || mIns[i].mCode == BC_LOAD_ABS_16) && mIns[i + 1].mCode == BC_ADDR_REG && mIns[i].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal)
					{
						mIns[i].mRegister = BC_REG_ADDR;
						mIns[i + 1].mCode = BC_NOP;
						progress = true;
					}
#endif
				}

				if (mIns[i].mCode == BC_BINOP_ORI_16 && !(mIns[i].mValue & 0xff00))
				{
					mIns[i].mCode = BC_BINOP_ORI_8;
					progress = true;
				}

				if (mIns[i].mCode == BC_BINOP_ANDI_16 && (mIns[i].mValue & 0xff00) == 0xff00)
				{
					mIns[i].mCode = BC_BINOP_ANDI_8;
					progress = true;
				}

				if (mIns[i].mCode == BC_BINOP_ANDI_16 && mIns[i].mRegister == BC_REG_ACCU && mIns[i].mValue == 0x00ff)
				{
					mIns[i].mCode = BC_LOAD_REG_8;
					progress = true;
				}
#endif
#if 1
				if ((mIns[i].mCode == BC_LOAD_REG_16 || mIns[i].mCode == BC_STORE_REG_16 || mIns[i].mCode == BC_LOAD_REG_32 || mIns[i].mCode == BC_STORE_REG_32) && accuTemp == mIns[i].mRegister)
				{
					mIns[i].mCode = BC_NOP;
					progress = true;
				}
				else if ((mIns[i].mCode == BC_LOAD_REG_8 || mIns[i].mCode == BC_STORE_REG_8) && accuTempByte == mIns[i].mRegister)
				{
					mIns[i].mCode = BC_NOP;
					progress = true;
				}
#endif
				if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister == addrTemp)
				{
					if (mIns[i].mRegisterFinal)
					{
						int	j = i;
						while (j > 0 && !mIns[j - 1].UsesRegister(mIns[i].mRegister) && !mIns[j - 1].ChangesRegister(mIns[i].mRegister))
							j--;
						if (j > 0 && mIns[j - 1].UsesRegister(mIns[i].mRegister))
							mIns[j - 1].mRegisterFinal = true;
					}
					mIns[i].mCode = BC_NOP;
					progress = true;
				}

				if (accuConst && !mIns[i].mRelocate && mIns[i].mRegister == BC_REG_ACCU)
				{
					switch (mIns[i].mCode)
					{
					case BC_CONST_16:
						if ((mIns[i].mValue & 0xffff) == (accuVal & 0xffff))
						{
							mIns[i].mCode = BC_NOP;
							progress = true;
						}
						break;
					case BC_CONST_32:
						if (mIns[i].mValue == accuVal && accuLong)
						{
							mIns[i].mCode = BC_NOP;
							progress = true;
						}
						break;
					case BC_CONST_8:
						if ((mIns[i].mValue & 0xff) == (accuVal & 0xffff))
						{
							mIns[i].mCode = BC_NOP;
							progress = true;
						}
						break;
					}
				}

				if (mIns[i].ChangesAccu())
				{
					accuTemp = -1;
					accuTempByte = -1;
					accuConst = false;
					accuLong = false;
				}
				if (mIns[i].ChangesAddr())
					addrTemp = -1;
				if (accuTemp != -1 && mIns[i].ChangesRegister(accuTemp))
					accuTemp = -1;
				if (accuTempByte != -1 && mIns[i].ChangesRegister(accuTempByte))
					accuTempByte = -1;
				if (addrTemp != -1 && mIns[i].ChangesRegister(addrTemp))
					addrTemp = -1;

				if (mIns[i].mCode == BC_LOAD_REG_16 || mIns[i].mCode == BC_STORE_REG_16 || mIns[i].mCode == BC_LOAD_REG_32 || mIns[i].mCode == BC_STORE_REG_32)
					accuTemp = mIns[i].mRegister;
				else if (mIns[i].mCode == BC_LOAD_REG_8)
					accuTempByte = mIns[i].mRegister;
				else if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister != BC_REG_ACCU)
					addrTemp = mIns[i].mRegister;

				if (mIns[i].mRegister == BC_REG_ACCU && !mIns[i].mRelocate)
				{
					switch (mIns[i].mCode)
					{
					case BC_CONST_16:
						accuVal = mIns[i].mValue & 0xffff;
						accuConst = true;
						break;
					case BC_CONST_32:
						accuVal = mIns[i].mValue;
						accuConst = true;
						accuLong = true;
						break;
					case BC_CONST_8:
						accuVal = mIns[i].mValue & 0xff;
						accuConst = true;
						break;
					}
				}
			}

			if (phase >= 2)
			{
				for (int i = mIns.Size() - 1; i >= 0; i--)
				{
					if (mIns[i].CheckAccuSize(aused))
						progress = true;
				}
			}

			if (progress)
				changed = true;
		} while (progress);

		if (mTrueJump && mTrueJump->PeepHoleOptimizer(phase))
			changed = true;
		if (mFalseJump && mFalseJump->PeepHoleOptimizer(phase))
			changed = true;
	}

	return changed;
}

void ByteCodeBasicBlock::Assemble(ByteCodeGenerator* generator)
{
	if (!mAssembled)
	{
		mAssembled = true;

		int	nins = 0;
		for (int i = 0; i < mIns.Size(); i++)
		{
			mIns[i].Assemble(generator, this);
			if (mCode.Size() > nins + 240)
			{
				PutCode(generator, BC_NOP);
				nins = mCode.Size();
			}
		}

		mLinear = mCode.Size() - nins + 3;

		if (this->mTrueJump)
			this->mTrueJump->Assemble(generator);
		if (this->mFalseJump)
			this->mFalseJump->Assemble(generator);
	}
}

void ByteCodeBasicBlock::Close(ByteCodeBasicBlock* trueJump, ByteCodeBasicBlock* falseJump, ByteCode branch)
{
	if (branch == BC_NOP)
	{
		this->mTrueJump = this->mTrueLink = falseJump;
		this->mFalseJump = this->mFalseLink = nullptr;
		this->mBranch = BC_JUMPS;
	}
	else if (branch == BC_JUMPS)
	{
		this->mTrueJump = this->mTrueLink = trueJump;
		this->mFalseJump = this->mFalseLink = nullptr;
		this->mBranch = BC_JUMPS;
	}
	else
	{
		this->mTrueJump = this->mTrueLink = trueJump;
		this->mFalseJump = this->mFalseLink = falseJump;
		this->mBranch = branch;
	}
}

static int BranchByteSize(int from, int to)
{
	if (to - from >= -126 && to - from <= 129)
		return 2;
	else
		return 3;
}

static int JumpByteSize(int from, int to)
{
	if (to - from >= -126 && to - from <= 129)
		return 2;
	else
		return 3;
}

ByteCodeBasicBlock* ByteCodeBasicBlock::BypassEmptyBlocks(void)
{
	if (mBypassed)
		return this;
	else if (!mFalseJump && mCode.Size() == 0 && this != mTrueJump)
		return mTrueJump->BypassEmptyBlocks();
	else
	{
		mBypassed = true;

		if (mFalseJump)
			mFalseJump = mFalseJump->BypassEmptyBlocks();
		if (mTrueJump)
			mTrueJump = mTrueJump->BypassEmptyBlocks();

		return this;
	}
}

void ByteCodeBasicBlock::CopyCode(ByteCodeGenerator* generator, LinkerObject* linkerObject, uint8 * target)
{
	int i;
	int next, end;

	for (int i = 0; i < mRelocations.Size(); i++)
	{
		LinkerReference	rl = mRelocations[i];
		rl.mObject = linkerObject;
		rl.mOffset += mOffset;
		linkerObject->AddReference(rl);
	}

	end = mOffset + mCode.Size();
	next = mOffset + mSize;

	if (mFalseJump)
	{
		if (mFalseJump->mPlace == mPlace + 1)
			end += PutBranch(generator, mBranch, mTrueJump->mOffset - end);
		else if (mTrueJump->mPlace == mPlace + 1)
			end += PutBranch(generator, InvertBranchCondition(mBranch), mFalseJump->mOffset - end);
		else
		{
			end += PutBranch(generator, mBranch, mTrueJump->mOffset - end);
			end += PutBranch(generator, BC_JUMPS, mFalseJump->mOffset - end);
		}
	}
	else if (mTrueJump)
	{
		if (mTrueJump->mPlace != mPlace + 1)
			end += PutBranch(generator, mBranch, mTrueJump->mOffset - end);
	}

	assert(end == next);

	for (i = 0; i < mCode.Size(); i++)
		mCode.Lookup(i, target[i + mOffset]);
}

void ByteCodeBasicBlock::BuildPlacement(GrowingArray<ByteCodeBasicBlock*>& placement)
{
	if (!mPlaced)
	{
		mPlaced = true;
		mPlace = placement.Size();
		placement.Push(this);

		if (mFalseJump)
		{
			if (mFalseJump->mPlaced)
				mTrueJump->BuildPlacement(placement);
			else if (mTrueJump->mPlaced)
				mFalseJump->BuildPlacement(placement);
			else if (mTrueJump == mFalseJump)
				mTrueJump->BuildPlacement(placement);
			else if (!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump)
			{
				mFalseJump->mPlaced = true;
				mFalseJump->mPlace = placement.Size();
				placement.Push(mFalseJump);

				mTrueJump->BuildPlacement(placement);
			}
			else if (mTrueJump->mFalseJump == mFalseJump || mTrueJump->mTrueJump == mFalseJump)
			{
				mTrueJump->BuildPlacement(placement);
				mFalseJump->BuildPlacement(placement);
			}
			else if (mFalseJump->mFalseJump == mTrueJump || mFalseJump->mTrueJump == mTrueJump)
			{
				mFalseJump->BuildPlacement(placement);
				mTrueJump->BuildPlacement(placement);
			}
			else if (
				!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mTrueJump->mPlaced && mTrueJump->mCode.Size() < 120 ||
				mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mFalseJump->mPlaced && mTrueJump->mTrueJump->mPlaced && mTrueJump->mCode.Size() < 120)
			{
				mTrueJump->BuildPlacement(placement);
				mFalseJump->BuildPlacement(placement);
			}
			else if (mFalseJump->mCode.Size() < mTrueJump->mCode.Size())
			{
				mFalseJump->BuildPlacement(placement);
				mTrueJump->BuildPlacement(placement);
			}
			else
			{
				mTrueJump->BuildPlacement(placement);
				mFalseJump->BuildPlacement(placement);
			}
		}
		else if (mTrueJump)
		{
			mTrueJump->BuildPlacement(placement);
		}
	}
}

void ByteCodeBasicBlock::InitialOffset(int& total, int& linear)
{
	int	size = mCode.Size();
	if (size > 240)
		size = 240;

	mNeedsNop = linear + size > 240;
	if (mNeedsNop)
	{
		total++;
		linear = 0;
	}

	linear += mLinear;

	mOffset = total;
	total += mCode.Size();
	if (mFalseJump)
	{
		total += 3;
		if (mFalseJump->mPlace != mPlace + 1 && mTrueJump->mPlace != mPlace + 1)
		{
			total += 3;
			linear = 0;
		}
	}
	else if (mTrueJump)
	{
		if (mTrueJump->mPlace != mPlace + 1)
		{
			total += 3;
			linear = 0;
		}
	}

	mSize = total - mOffset;
}

bool ByteCodeBasicBlock::CalculateOffset(int& total)
{
	if (mNeedsNop)
		total++;

	bool	changed = total != mOffset;
	mOffset = total;

	total += mCode.Size();

	if (mFalseJump)
	{
		if (mFalseJump->mPlace == mPlace + 1)
			total += BranchByteSize(total, mTrueJump->mOffset);
		else if (mTrueJump->mPlace == mPlace + 1)
			total += BranchByteSize(total, mFalseJump->mOffset);
		else
		{
			total += BranchByteSize(total, mTrueJump->mOffset);
			total += JumpByteSize(total, mFalseJump->mOffset);
		}
	}
	else if (mTrueJump)
	{
		if (mTrueJump->mPlace != mPlace + 1)
			total += BranchByteSize(total, mTrueJump->mOffset);
	}

	if (mOffset + mSize != total)
		changed = true;

	mSize = total - mOffset;

	return changed;
}

#if 0
	int next;

	if (mOffset > total)
	{
		mNeedsNop = false;
		linear += mSize + 3;

		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);

					if (linear + mTrueJump->mCode.Size() > 240)
					{
						mNeedsNop = true;
						total++;
					}
					
					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);

				if (linear + mFalseJump->mCode.Size() > 240)
				{
					mNeedsNop = true;
					total++;
				}

				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;

				if (linear + mFalseJump->mCode.Size() > 240)
				{
					mNeedsNop = true;
					total++;
				}

				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 1
			else if (!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && 
				mTrueJump->mCode.Size() < 120 && mFalseJump->mCode.Size() < 120 && mTrueJump->mTrueJump->mOffset > mOffset)
			{
				// Small diamond so place true then false directly behind each other
				// with short branches

				total = next + 2;

				if (linear + mFalseJump->mCode.Size() > 240)
				{
					mNeedsNop = true;
					total++;
				}

				mSize = total - mOffset;

				mFalseJump->mOffset = next + 2;
				mFalseJump->mSize = mFalseJump->mCode.Size() + 2;

				total = mFalseJump->mOffset + mFalseJump->mSize;
				mTrueJump->CalculateOffset(total);
			}
#endif
			else
			{
				// neither falseJump nor trueJump have been placed
				// 

				if (mTrueJump->mFalseJump == mFalseJump || mTrueJump->mTrueJump == mFalseJump)
				{
					ByteCodeBasicBlock* block = mFalseJump;
					mFalseJump = mTrueJump;
					mTrueJump = block;
					mBranch = InvertBranchCondition(mBranch);
				}

				// this may lead to some undo operation...
				// first assume a full size branch:

				total = next + 3;
				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;
		}
	}
}
#endif


ByteCodeProcedure::ByteCodeProcedure(void)
	: mBlocks(nullptr)
{
}

ByteCodeProcedure::~ByteCodeProcedure(void)
{
}



void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure* proc)
{
	mID = proc->mID;

	mNumBlocks = proc->mNumBlocks;

	tblocks = new ByteCodeBasicBlock * [mNumBlocks];
	for (int i = 0; i < mNumBlocks; i++)
		tblocks[i] = nullptr;

	int		tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;

	entryBlock = new ByteCodeBasicBlock();
	mBlocks.Push(entryBlock);
	entryBlock->PutCode(generator, BC_ENTER); entryBlock->PutWord(proc->mLocalSize + 2 + tempSave); entryBlock->PutByte(tempSave);

	if (!proc->mLeafProcedure)
	{
		entryBlock->PutCode(generator, BC_PUSH_FRAME);
		entryBlock->PutWord(uint16(proc->mCommonFrameSize + 2));
	}

	tblocks[0] = entryBlock;

	exitBlock = new ByteCodeBasicBlock();
	mBlocks.Push(exitBlock);

	entryBlock->Compile(proc, this, proc->mBlocks[0]);

	bool	progress = false;

	entryBlock->mLocked = true;
	exitBlock->mLocked = true;
#if 1

	int	phase = 0;

	do {

		progress = false;

		ResetVisited();
		progress = entryBlock->PeepHoleOptimizer(phase);

		ResetVisited();
		entryBlock->CountEntries(nullptr);

		ResetVisited();
		entryBlock->MergeBasicBlocks();

		ResetVisited();
		for (int i = 0; i < mBlocks.Size(); i++)
			mBlocks[i]->mEntryBlocks.SetSize(0);
		entryBlock->CollectEntryBlocks(nullptr);


		ResetVisited();
		if (entryBlock->JoinTailCodeSequences())
			progress = true;

		if (!progress && phase < 4)
		{
			phase++;
			progress = true;
		}

	} while (progress);

#if 1
	ResetVisited();
	entryBlock->PropagateAccuCrossBorder(-1, -1);
#endif

#endif

	entryBlock->Assemble(generator);

	if (!proc->mLeafProcedure)
	{
		exitBlock->PutCode(generator, BC_POP_FRAME);
		exitBlock->PutWord(uint16(proc->mCommonFrameSize + 2));
	}
	exitBlock->PutCode(generator, BC_RETURN); exitBlock->PutByte(tempSave); exitBlock->PutWord(proc->mLocalSize + 2 + tempSave);


	ByteCodeBasicBlock* lentryBlock = entryBlock->BypassEmptyBlocks();

	GrowingArray<ByteCodeBasicBlock*>	placement(nullptr);

	int	total, linear;
	total = 0;
	linear = 0;

	lentryBlock->BuildPlacement(placement);

	for (int i = 0; i < placement.Size(); i++)
		placement[i]->InitialOffset(total, linear);

	do {
		progress = false;
		total = 0;
		for (int i = 0; i < placement.Size(); i++)
			if (placement[i]->CalculateOffset(total))
				progress = true;
	} while (progress);

	uint8* data = proc->mLinkerObject->AddSpace(total);

	for (int i = 0; i < placement.Size(); i++)
		placement[i]->CopyCode(generator, proc->mLinkerObject, data);

	mProgSize = total; 
}

ByteCodeBasicBlock* ByteCodeProcedure::CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* sblock)
{
	if (tblocks[sblock->mIndex])
		return tblocks[sblock->mIndex];

	ByteCodeBasicBlock	*	block = new ByteCodeBasicBlock();
	mBlocks.Push(block);
	tblocks[sblock->mIndex] = block;
	block->Compile(iproc, this, sblock);
	
	return block;
}

void ByteCodeProcedure::ResetVisited(void)
{
	for (int i = 0; i < mBlocks.Size(); i++)
	{
		mBlocks[i]->mVisited = false;
	}
}

ByteCodeGenerator::ByteCodeGenerator(Errors* errors, Linker* linker)
	: mErrors(errors), mLinker(linker)
{
	for (int i = 0; i < 128; i++)
	{
		mByteCodeUsed[i] = 0;
		mExtByteCodes[i] = nullptr;
	}

	mByteCodeUsed[BC_CALL_ABS] = 1;
	mByteCodeUsed[BC_EXIT] = 1;
	mByteCodeUsed[BC_NATIVE] = 1;
	mByteCodeUsed[BC_NOP] = 1;

	assert(sizeof(ByteCodeNames) == 128 * sizeof(char*));
}

ByteCodeGenerator::~ByteCodeGenerator(void)
{
}

bool ByteCodeGenerator::WriteByteCodeStats(const char* filename)
{
	FILE* file;
	fopen_s(&file, filename, "w");
	if (file)
	{
		for (int i = 0; i < 128; i++)
		{
			if (mByteCodeUsed[i] > 0)
				fprintf(file, "BC %s : %d\n", ByteCodeNames[i], mByteCodeUsed[i]);
		}
		fclose(file);

		return true;
	}

	return false;
}
