#include "ByteCodeGenerator.h" #include "Assembler.h" 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), mFunction(false), mRegisterFinal(false), mVIndex(-1), 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 { if (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_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_U16) return true; if (mCode >= BC_SET_EQ && mCode <= BC_SET_LE) return true; if (mCode == BC_JSR || mCode == BC_CALL) return true; return ChangesRegister(BC_REG_ACCU); } bool ByteCodeInstruction::ChangesAddr(void) const { if (mCode == BC_ADDR_REG) return true; if (mCode >= BC_LOAD_ABS_U8 && mCode <= BC_STORE_ABS_32) return true; if (mCode == BC_JSR || mCode == BC_CALL) return true; return ChangesRegister(BC_REG_ADDR); } bool ByteCodeInstruction::LoadsRegister(uint32 reg) const { if (mRegister == reg) { if (mCode >= BC_LOAD_ABS_U8 && mCode <= BC_LOAD_ABS_32) return true; if (mCode >= BC_LOAD_LOCAL_U8 && mCode <= BC_LOAD_LOCAL_32) return true; if (mCode >= BC_LOAD_ADDR_U8 && mCode <= BC_LOAD_ADDR_32) return true; if (mCode >= BC_CONST_P8 && mCode <= BC_CONST_32) return true; if (mCode == BC_LEA_ABS || mCode == BC_LEA_LOCAL) 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; 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::ChangesRegister(uint32 reg) const { if (mRegister == reg) { if (mCode == BC_STORE_REG_16 || mCode == BC_STORE_REG_32) return true; if (mCode >= BC_LOAD_ABS_U8 && mCode <= BC_LOAD_ABS_32) return true; if (mCode >= BC_LOAD_LOCAL_U8 && mCode <= BC_LOAD_LOCAL_32) return true; if (mCode >= BC_LOAD_ADDR_U8 && mCode <= BC_LOAD_ADDR_32) return true; if (mCode >= BC_CONST_P8 && mCode <= BC_CONST_32) return true; if (mCode == BC_LEA_ABS || mCode == BC_LEA_LOCAL) return true; if (mCode >= BC_BINOP_ADDI_16 && mCode <= BC_BINOP_MULI8_16) return true; if (mCode == BC_CALL) 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_P8: case BC_CONST_N8: case BC_CONST_16: if (mRelocate) { block->PutCode(generator, mCode); block->PutByte(mRegister); ByteCodeRelocation rl; rl.mAddr = block->mCode.Size(); rl.mFunction = mFunction; rl.mLower = true; rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; block->mRelocations.Push(rl); block->PutWord(0); } else if (mValue >= 0 && mValue < 255) { 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_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_U8: case BC_LOAD_ABS_I8: 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) { ByteCodeRelocation rl; rl.mAddr = block->mCode.Size(); rl.mFunction = mFunction; rl.mLower = true; rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; block->mRelocations.Push(rl); block->PutWord(0); } else block->PutWord(mValue); block->PutByte(mRegister); break; case BC_LEA_ABS: block->PutCode(generator, mCode); block->PutByte(mRegister); if (mRelocate) { ByteCodeRelocation rl; rl.mAddr = block->mCode.Size(); rl.mFunction = mFunction; rl.mLower = true; rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = mValue; block->mRelocations.Push(rl); block->PutWord(0); } else block->PutWord(uint16(mValue)); break; case BC_LOAD_LOCAL_U8: case BC_LOAD_LOCAL_I8: 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: block->PutCode(generator, mCode); block->PutByte(mRegister); block->PutWord(uint16(mValue)); 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: 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: 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: 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_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_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_SET_EQ: case BC_SET_NE: case BC_SET_GT: case BC_SET_GE: case BC_SET_LT: case BC_SET_LE: block->PutCode(generator, mCode); break; case BC_ENTER: case BC_RETURN: assert(false); break; case BC_CALL: block->PutCode(generator, mCode); 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); ByteCodeRelocation rl; rl.mAddr = block->mCode.Size(); rl.mFunction = false; rl.mLower = true; rl.mUpper = true; rl.mIndex = mVIndex; rl.mOffset = 0; block->mRelocations.Push(rl); block->PutWord(0); } break; case BC_LOAD_ADDR_U8: case BC_LOAD_ADDR_I8: 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); 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->PutByte(uint8(mValue)); } 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] = true; } 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)) { mTrueJump = mFalseJump = NULL; mTrueLink = mFalseLink = NULL; mOffset = 0x7fffffff; mCopied = false; mKnownShortBranch = false; mBypassed = false; } void ByteCodeBasicBlock::IntConstToAccu(__int64 val) { ByteCodeInstruction ins(BC_CONST_16); ins.mRegister = BC_REG_ACCU; ins.mValue = int(val); mIns.Push(ins); } void ByteCodeBasicBlock::FloatConstToAccu(double val) { union { float f; int v; } cc; cc.f = val; ByteCodeInstruction bins(BC_CONST_32); bins.mRegister = BC_REG_ACCU; 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::LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mTType == IT_FLOAT) { union { float f; int v; } cc; cc.f = ins.mFloatValue; ByteCodeInstruction bins(BC_CONST_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = cc.v; mIns.Push(bins); } else if (ins.mTType == IT_POINTER) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_LEA_ABS); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mIntValue; bins.mRelocate = true; bins.mFunction = false; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_LEA_ABS); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mIntValue; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL) { ByteCodeInstruction bins(BC_LEA_LOCAL); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mIntValue + proc->mLocalVars[ins.mVarIndex].mOffset; mIns.Push(bins); } else if (ins.mMemory == IM_PARAM) { ByteCodeInstruction bins(BC_LEA_LOCAL); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mIntValue + ins.mVarIndex + proc->mLocalSize + 2; mIns.Push(bins); } else if (ins.mMemory == IM_PROCEDURE) { ByteCodeInstruction bins(BC_CONST_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mVIndex = ins.mVarIndex; bins.mValue = 0; bins.mRelocate = true; bins.mFunction = true; mIns.Push(bins); } } else { ByteCodeInstruction bins(BC_CONST_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mIntValue; mIns.Push(bins); } } void ByteCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction& ins) { ByteCodeInstruction sins(BC_ADDR_REG); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; sins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(sins); ByteCodeInstruction dins(BC_LOAD_REG_16); dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; dins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(dins); ByteCodeInstruction cins(BC_COPY); cins.mValue = ins.mOperandSize; mIns.Push(cins); } void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mSType[0] == IT_FLOAT) { if (ins.mSTemp[1] < 0) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_32); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_32); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 252) { ByteCodeInstruction bins(BC_STORE_LOCAL_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; 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.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } else { if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_STORE_ADDR_32); bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_STORE_ADDR_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } } } else if (ins.mSType[0] == IT_POINTER) { if (ins.mSTemp[1] < 0) { if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.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; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_16); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } else { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 254) { ByteCodeInstruction bins(BC_STORE_LOCAL_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; 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.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } } else { if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_STORE_ADDR_16); bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_STORE_ADDR_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } } } else { if (ins.mSTemp[1] < 0) { if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); if (ins.mOperandSize == 1) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_8); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_8); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.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; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_8); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } else if (ins.mOperandSize == 2) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.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; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_16); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } } else { if (ins.mOperandSize == 1) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_8); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_8); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 255) { ByteCodeInstruction bins(BC_STORE_LOCAL_8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; 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.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } else if (ins.mOperandSize == 2) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_STORE_ABS_16); bins.mValue = ins.mSIntConst[1]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[1]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 254) { ByteCodeInstruction bins(BC_STORE_LOCAL_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; 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.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } else if (ins.mMemory == IM_FRAME) { ByteCodeInstruction bins(BC_STORE_FRAME_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; bins.mValue = ins.mVarIndex + ins.mSIntConst[1] + 2; mIns.Push(bins); } } } } else { if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); if (ins.mOperandSize == 1) { ByteCodeInstruction bins(BC_STORE_ADDR_8); bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } else if (ins.mOperandSize == 2) { ByteCodeInstruction bins(BC_STORE_ADDR_16); bins.mRegister = BC_REG_ACCU; mIns.Push(bins); } } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); if (ins.mOperandSize == 1) { ByteCodeInstruction bins(BC_STORE_ADDR_8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mOperandSize == 2) { ByteCodeInstruction bins(BC_STORE_ADDR_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } } } } } void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mTType == IT_FLOAT) { if (ins.mSTemp[0] < 0) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_LOAD_ABS_32); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_LOAD_ABS_32); bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[0]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 254) { ByteCodeInstruction bins(BC_LOAD_LOCAL_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; 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.mTTemp]; mIns.Push(bins); } } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(BC_LOAD_ADDR_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } } else if (ins.mTType == IT_POINTER) { if (ins.mSTemp[0] < 0) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_LOAD_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_LOAD_ABS_16); bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[0]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 254) { ByteCodeInstruction bins(BC_LOAD_LOCAL_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; 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.mTTemp]; mIns.Push(bins); } } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(BC_LOAD_ADDR_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } } else { if (ins.mSTemp[0] < 0) { if (ins.mOperandSize == 1) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_ABS_I8 : BC_LOAD_ABS_U8); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_ABS_I8 : BC_LOAD_ABS_U8); bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[0]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 255) { ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_LOAD_LOCAL_I8 : BC_LOAD_LOCAL_U8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; 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(ins.mTType == IT_SIGNED ? BC_LOAD_ADDR_I8 : BC_LOAD_ADDR_U8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } } else if (ins.mOperandSize == 2) { if (ins.mMemory == IM_GLOBAL) { ByteCodeInstruction bins(BC_LOAD_ABS_16); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_ABSOLUTE) { ByteCodeInstruction bins(BC_LOAD_ABS_16); bins.mValue = ins.mSIntConst[0]; bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { int index = ins.mSIntConst[0]; if (ins.mMemory == IM_LOCAL) index += proc->mLocalVars[ins.mVarIndex].mOffset; else index += ins.mVarIndex + proc->mLocalSize + 2; if (index <= 254) { ByteCodeInstruction bins(BC_LOAD_LOCAL_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; 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.mTTemp]; mIns.Push(bins); } } } } else { if (ins.mMemory == IM_INDIRECT) { ByteCodeInstruction lins(BC_ADDR_REG); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); if (ins.mOperandSize == 1) { if (ins.mTType == IT_SIGNED) { ByteCodeInstruction bins(BC_LOAD_ADDR_I8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else { ByteCodeInstruction bins(BC_LOAD_ADDR_U8); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } else if (ins.mOperandSize == 2) { ByteCodeInstruction bins(BC_LOAD_ADDR_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } } } } void ByteCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mSTemp[0] < 0) { if (ins.mSTemp[1] == ins.mTTemp) { ByteCodeInstruction bins(BC_BINOP_ADDI_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction ains(BC_BINOP_ADDI_16); ains.mRegister = BC_REG_ACCU; ains.mValue = ins.mSIntConst[0]; mIns.Push(ains); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction ains(BC_BINOP_ADDR_16); ains.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; ains.mRegisterFinal = ins.mSFinal[0]; mIns.Push(ains); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } } void ByteCodeBasicBlock::CallFunction(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mSTemp[0] < 0) { ByteCodeInstruction bins(BC_LEA_ABS); bins.mRelocate = true; bins.mFunction = true; bins.mVIndex = ins.mVarIndex; bins.mValue = 0; bins.mRegister = BC_REG_ADDR; mIns.Push(bins); } else { ByteCodeInstruction bins(BC_ADDR_REG); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } ByteCodeInstruction cins(BC_CALL); mIns.Push(cins); if (ins.mTTemp >= 0) { if (ins.mTType == IT_FLOAT) { ByteCodeInstruction bins(BC_STORE_REG_32); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } else { ByteCodeInstruction bins(BC_STORE_REG_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(bins); } } } void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mSTemp[0] < 0) { ByteCodeInstruction bins(BC_JSR); bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; mIns.Push(bins); } } ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins) { 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.mSType[0] == IT_FLOAT) { ByteCodeInstruction lins(BC_LOAD_REG_32); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction cins(BC_BINOP_CMP_F32); cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; cins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(cins); } else { if (ins.mSTemp[1] < 0) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); if (csigned) { ByteCodeInstruction cins(BC_BINOP_CMPSI_16); cins.mValue = ins.mSIntConst[1]; mIns.Push(cins); } else { ByteCodeInstruction cins(BC_BINOP_CMPUI_16); cins.mValue = ins.mSIntConst[1]; mIns.Push(cins); } } else if (ins.mSTemp[0] < 0) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); if (csigned) { ByteCodeInstruction cins(BC_BINOP_CMPSI_16); cins.mValue = ins.mSIntConst[0]; mIns.Push(cins); } else { ByteCodeInstruction cins(BC_BINOP_CMPUI_16); cins.mValue = ins.mSIntConst[0]; mIns.Push(cins); } code = TransposeBranchCondition(code); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); if (csigned) { ByteCodeInstruction cins(BC_BINOP_CMPSR_16); cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; cins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(cins); } else { ByteCodeInstruction cins(BC_BINOP_CMPUR_16); cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; cins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(cins); } } } return code; } static ByteCode ByteCodeBinRegOperator(const InterInstruction& ins) { if (ins.mTType == 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 { 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; } } 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.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(ins.mTType == IT_SIGNED ? BC_CONV_F32_I16 : BC_CONV_F32_U16); mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } break; case IA_INT2FLOAT: { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(ins.mSType[0] == IT_SIGNED ? BC_CONV_I16_F32 : BC_CONV_U16_F32); mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_32); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } break; } } void ByteCodeBasicBlock::UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mTType == IT_FLOAT) { ByteCodeInstruction lins(BC_LOAD_REG_32); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; 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.mTTemp]; mIns.Push(sins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; 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.mTTemp]; mIns.Push(sins); } } void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mTType == IT_FLOAT) { ByteCode bc = ByteCodeBinRegOperator(ins); ByteCodeInstruction lins(BC_LOAD_REG_32); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bc); if (ins.mSTemp[1] == ins.mSTemp[0]) bins.mRegister = BC_REG_ACCU; else bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_32); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } else { switch (ins.mOperator) { case IA_ADD: case IA_OR: case IA_AND: { ByteCode bc = ByteCodeBinRegOperator(ins); ByteCode bci = ByteCodeBinImmOperator(ins); if (ins.mSTemp[1] < 0) { if (ins.mSTemp[0] == ins.mTTemp) { ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); } else if (ins.mSTemp[0] < 0) { if (ins.mSTemp[1] == ins.mTTemp) { ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } break; case IA_SUB: if (ins.mSTemp[1] < 0) { if (ins.mSTemp[0] == ins.mTTemp) { ByteCodeInstruction bins(BC_BINOP_SUBI_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(BC_BINOP_SUBI_16); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); } else if (ins.mSTemp[0] < 0) { if (ins.mSTemp[1] == ins.mTTemp) { ByteCodeInstruction bins(BC_BINOP_ADDI_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; bins.mValue = - ins.mSIntConst[0]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_BINOP_ADDI_16); bins.mRegister = BC_REG_ACCU; bins.mValue = - ins.mSIntConst[0]; mIns.Push(bins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(BC_BINOP_SUBR_16); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } break; case IA_MUL: { ByteCode bc = ByteCodeBinRegOperator(ins); ByteCode bci = ByteCodeBinImmOperator(ins); if (ins.mSTemp[1] < 0) { if (ins.mSIntConst[1] >= 0 && ins.mSIntConst[1] <= 255) { if (ins.mSTemp[0] == ins.mTTemp) { ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mSIntConst[1]; mIns.Push(bins); } else { IntConstToAccu(ins.mSIntConst[1]); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } else if (ins.mSTemp[0] < 0) { if (ins.mSIntConst[0] >= 0 && ins.mSIntConst[0] <= 255) { if (ins.mSTemp[1] == ins.mTTemp) { ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; bins.mRegisterFinal = ins.mSFinal[1]; bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); return; } ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bci); bins.mRegister = BC_REG_ACCU; bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); } else { IntConstToAccu(ins.mSIntConst[0]); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; bins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(bins); } } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } break; case IA_XOR: { ByteCode bc = ByteCodeBinRegOperator(ins); if (ins.mSTemp[1] < 0) { IntConstToAccu(ins.mSIntConst[1]); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mSTemp[0] < 0) { IntConstToAccu(ins.mSIntConst[0]); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; bins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(bins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } break; case IA_DIVS: case IA_MODS: case IA_DIVU: case IA_MODU: { ByteCode bc = ByteCodeBinRegOperator(ins); if (ins.mSTemp[1] < 0) { IntConstToAccu(ins.mSIntConst[1]); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mSTemp[0] < 0) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); IntConstToAddr(ins.mSIntConst[0]); 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.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(bc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } break; case IA_SHL: case IA_SHR: case IA_SAR: { ByteCode rbc = ByteCodeBinRegOperator(ins); ByteCode ibc = ByteCodeBinImmOperator(ins); if (ins.mSTemp[1] < 0) { IntConstToAccu(ins.mSIntConst[1]); ByteCodeInstruction bins(rbc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } else if (ins.mSTemp[0] < 0) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(ibc); bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]]; lins.mRegisterFinal = ins.mSFinal[1]; mIns.Push(lins); ByteCodeInstruction bins(rbc); bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; bins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(bins); } } break; } ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; 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: LoadDirectValue(iproc, ins); break; case IC_COPY: CopyValue(iproc, ins); break; case IC_LOAD_TEMPORARY: { if (ins.mSTemp[0] != ins.mTTemp) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } } 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: CallFunction(iproc, ins); break; case IC_JSR: CallAssembler(iproc, ins); break; case IC_PUSH_FRAME: { ByteCodeInstruction bins(BC_PUSH_FRAME); bins.mValue = ins.mIntValue + 2; mIns.Push(bins); } break; case IC_POP_FRAME: { ByteCodeInstruction bins(BC_POP_FRAME); bins.mValue = ins.mIntValue + 2; mIns.Push(bins); } break; case IC_RELATIONAL_OPERATOR: if (sblock->mInstructions[i + 1].mCode == IC_BRANCH) { ByteCode code = RelationalOperator(iproc, ins); this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), code); i++; return; } else { ByteCode code = RelationalOperator(iproc, ins); ByteCodeInstruction bins(ByteCode(code - BC_BRANCHS_EQ + BC_SET_EQ)); mIns.Push(bins); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } break; case IC_RETURN_VALUE: if (ins.mSTemp[0] < 0) IntConstToAccu(ins.mSIntConst[0]); else if (ins.mSType[0] == IT_FLOAT) { ByteCodeInstruction lins(BC_LOAD_REG_32); lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); } else { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); } this->Close(proc->exitBlock, nullptr, BC_JUMPS); return; case IC_RETURN: this->Close(proc->exitBlock, nullptr, BC_JUMPS); return; case IC_TYPECAST: if (ins.mSTemp[0] >= 0 && ins.mTTemp != ins.mSTemp[0]) { ByteCodeInstruction lins(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); ByteCodeInstruction sins(BC_STORE_REG_16); sins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mTTemp]; mIns.Push(sins); } break; case IC_BRANCH: if (ins.mSTemp[0] < 0) { if (ins.mSIntConst[0] == 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(BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]]; lins.mRegisterFinal = ins.mSFinal[0]; mIns.Push(lins); this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), proc->CompileBlock(iproc, sblock->mFalseJump), BC_BRANCHS_NE); } return; } i++; } this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, BC_JUMPS); } void ByteCodeBasicBlock::PeepHoleOptimizer(void) { 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); int accuTemp = -1, addrTemp = -1; for (int i = 0; i < mIns.Size(); i++) { 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; } 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; } 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; } else if (mIns[i].mCode == BC_STORE_REG_16 && !mIns[i + 1].ChangesAddr() && 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; } 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; } 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; } 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; } 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; } 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); } } 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 + 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; } } 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; if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister == addrTemp) mIns[i].mCode = BC_NOP; if (mIns[i].ChangesAccu()) accuTemp = -1; if (mIns[i].ChangesAddr()) addrTemp = -1; if (accuTemp != -1 && mIns[i].ChangesRegister(accuTemp)) accuTemp = -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; if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister != BC_REG_ACCU) addrTemp = mIns[i].mRegister; } } while (progress); } void ByteCodeBasicBlock::Assemble(ByteCodeGenerator* generator) { if (!mAssembled) { mAssembled = true; PeepHoleOptimizer(); for (int i = 0; i < mIns.Size(); i++) mIns[i].Assemble(generator, this); if (this->mTrueJump) this->mTrueJump->Assemble(generator); if (this->mFalseJump) this->mFalseJump->Assemble(generator); } } void ByteCodeBasicBlock::Close(ByteCodeBasicBlock* trueJump, ByteCodeBasicBlock* falseJump, ByteCode branch) { 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) return mTrueJump->BypassEmptyBlocks(); else { mBypassed = true; if (mFalseJump) mFalseJump = mFalseJump->BypassEmptyBlocks(); if (mTrueJump) mTrueJump = mTrueJump->BypassEmptyBlocks(); return this; } } void ByteCodeBasicBlock::CopyCode(ByteCodeGenerator* generator, uint8 * target) { int i; int next; int pos, at; uint8 b; if (!mCopied) { mCopied = true; for (int i = 0; i < mRelocations.Size(); i++) { ByteCodeRelocation rl = mRelocations[i]; rl.mAddr += target - generator->mMemory + mOffset; generator->mRelocations.Push(rl); } next = mOffset + mCode.Size(); if (mFalseJump) { if (mFalseJump->mOffset <= mOffset) { if (mTrueJump->mOffset <= mOffset) { next += PutBranch(generator, mBranch, mTrueJump->mOffset - next); next += PutBranch(generator, BC_JUMPS, mFalseJump->mOffset - next); } else { next += PutBranch(generator, InvertBranchCondition(mBranch), mFalseJump->mOffset - next); } } else { next += PutBranch(generator, mBranch, mTrueJump->mOffset - next); } } else if (mTrueJump) { if (mTrueJump->mOffset != next) { next += PutBranch(generator, BC_JUMPS, mTrueJump->mOffset - next); } } assert(next - mOffset == mSize); for (i = 0; i < mCode.Size(); i++) { mCode.Lookup(i, target[i + mOffset]); } if (mTrueJump) mTrueJump->CopyCode(generator, target); if (mFalseJump) mFalseJump->CopyCode(generator, target); } } void ByteCodeBasicBlock::CalculateOffset(int& total) { int next; if (mOffset > total) { mOffset = total; next = total + mCode.Size(); if (mFalseJump) { if (mFalseJump->mOffset <= total) { // falseJump has been placed if (mTrueJump->mOffset <= total) { // trueJump and falseJump have been placed, not much to do next = next + BranchByteSize(next, mTrueJump->mOffset); total = next + JumpByteSize(next, mFalseJump->mOffset); mSize = total - mOffset; } else { // trueJump has not been placed, but falseJump has total = next + BranchByteSize(next, mFalseJump->mOffset); mSize = total - mOffset; mTrueJump->CalculateOffset(total); } } else if (mTrueJump->mOffset <= total) { // falseJump has not been placed, but trueJump has total = next + BranchByteSize(next, mTrueJump->mOffset); mSize = total - mOffset; mFalseJump->CalculateOffset(total); } else if (mKnownShortBranch) { // neither falseJump nor trueJump have been placed, // but we know from previous iteration that we can do // a short branch total = next + 2; mSize = total - mOffset; mFalseJump->CalculateOffset(total); if (mTrueJump->mOffset > total) { // trueJump was not placed in the process, so lets place it now mTrueJump->CalculateOffset(total); } } else { // neither falseJump nor trueJump have been placed // this may lead to some undo operation... // first assume a full size branch: total = next + 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; } } } ByteCodeProcedure::ByteCodeProcedure(void) { } ByteCodeProcedure::~ByteCodeProcedure(void) { } void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure* proc) { tblocks = new ByteCodeBasicBlock * [proc->mBlocks.Size()]; for (int i = 0; i < proc->mBlocks.Size(); i++) tblocks[i] = nullptr; int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0; entryBlock = new ByteCodeBasicBlock(); 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(); 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); entryBlock->Compile(proc, this, proc->mBlocks[0]); entryBlock->Assemble(generator); int total; ByteCodeBasicBlock* lentryBlock = entryBlock->BypassEmptyBlocks(); total = 0; lentryBlock->CalculateOffset(total); generator->AddAddress(proc->mID, true, generator->mProgEnd, total, proc->mIdent, false); mProgStart = generator->mProgEnd; lentryBlock->CopyCode(generator, generator->mMemory + generator->mProgEnd); mProgSize = total; generator->mProgEnd += total; } ByteCodeBasicBlock* ByteCodeProcedure::CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* sblock) { if (tblocks[sblock->mIndex]) return tblocks[sblock->mIndex]; ByteCodeBasicBlock * block = new ByteCodeBasicBlock(); tblocks[sblock->mIndex] = block; block->Compile(iproc, this, sblock); return block; } const char* ByteCodeProcedure::TempName(uint8 tmp, char* buffer, InterCodeProcedure* proc) { if (tmp == BC_REG_ADDR) return "ADDR"; else if (tmp == BC_REG_ACCU) return "ACCU"; else if (tmp >= BC_REG_TMP && tmp < BC_REG_TMP + proc->mTempSize) { int i = 0; while (i + 1 < proc->mTempOffset.Size() && proc->mTempOffset[i + 1] <= tmp - BC_REG_TMP) i++; sprintf_s(buffer, 10, "T%d", i); return buffer; } else { sprintf_s(buffer, 10, "$%02x", tmp); return buffer; } } void ByteCodeProcedure::Disassemble(FILE * file, ByteCodeGenerator * generator, InterCodeProcedure * proc) { fprintf(file, "--------------------------------------------------------------------\n"); if (proc->mIdent) fprintf(file, "%s:\n", proc->mIdent->mString); char tbuffer[10]; int i = 0; while (i < mProgSize) { ByteCode bc = ByteCode(generator->mMemory[mProgStart + i] / 2); fprintf(file, "%04x:\t", mProgStart + i); i++; switch (bc) { case BC_NOP: fprintf(file, "NOP"); break; case BC_EXIT: fprintf(file, "EXIT"); break; case BC_CONST_P8: fprintf(file, "MOV\t%s, #%d", TempName(generator->mMemory[mProgStart + i], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_CONST_N8: fprintf(file, "MOV\t%s, #%d", TempName(generator->mMemory[mProgStart + i], tbuffer, proc), int(generator->mMemory[mProgStart + i + 1]) - 0x100); i += 2; break; case BC_CONST_16: fprintf(file, "MOV\t%s, #$%04x", TempName(generator->mMemory[mProgStart + i], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_CONST_32: fprintf(file, "MOVD\t%s, #$%08x", TempName(generator->mMemory[mProgStart + i], tbuffer, proc), uint32(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2] + 0x10000 * generator->mMemory[mProgStart + i + 3] + 0x1000000 * generator->mMemory[mProgStart + i + 4])); i += 5; break; case BC_LOAD_REG_16: fprintf(file, "MOV\tACCU, %s", TempName(generator->mMemory[mProgStart + i], tbuffer, proc)); i += 1; break; case BC_STORE_REG_16: fprintf(file, "MOV\t%s, ACCU", TempName(generator->mMemory[mProgStart + i], tbuffer, proc)); i += 1; break; case BC_LOAD_REG_32: fprintf(file, "MOVD\tACCU, %s", TempName(generator->mMemory[mProgStart + i], tbuffer, proc)); i += 1; break; case BC_STORE_REG_32: fprintf(file, "MOVD\t%s, ACCU", TempName(generator->mMemory[mProgStart + i], tbuffer, proc)); i += 1; break; case BC_ADDR_REG: fprintf(file, "MOV\tADDR, %s", TempName(generator->mMemory[mProgStart + i], tbuffer, proc)); i += 1; break; case BC_LOAD_ABS_U8: fprintf(file, "MOVUB\t%s, $%04x", TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 3; break; case BC_LOAD_ABS_I8: fprintf(file, "MOVSB\t%s, $%04x", TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 3; break; case BC_LOAD_ABS_16: fprintf(file, "MOV\t%s, $%04x", TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 3; break; case BC_LOAD_ABS_32: fprintf(file, "MOVD\t%s, $%04x", TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 3; break; case BC_LEA_ABS: fprintf(file, "LEA\t%s, $%04x", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_STORE_ABS_8: fprintf(file, "MOVB\t$%04x, %s", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1]), TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc)); i += 3; break; case BC_STORE_ABS_16: fprintf(file, "MOV\t$%04x, %s", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1]), TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc)); i += 3; break; case BC_STORE_ABS_32: fprintf(file, "MOVD\t$%04x, %s", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1]), TempName(generator->mMemory[mProgStart + i + 2], tbuffer, proc)); i += 3; break; case BC_LOAD_LOCAL_U8: fprintf(file, "MOVUB\t%s, %d(FP)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_LOAD_LOCAL_I8: fprintf(file, "MOVSB\t%s, %d(FP)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_LOAD_LOCAL_16: fprintf(file, "MOV\t%s, %d(FP)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_LOAD_LOCAL_32: fprintf(file, "MOVD\t%s, %d(FP)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_STORE_LOCAL_8: fprintf(file, "MOVB\t%d(FP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_STORE_LOCAL_16: fprintf(file, "MOV\t%d(FP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_STORE_LOCAL_32: fprintf(file, "MOVD\t%d(FP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_LEA_LOCAL: fprintf(file, "LEA\t%s, %d(FP)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_STORE_FRAME_8: fprintf(file, "MOVB\t%d(SP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_STORE_FRAME_16: fprintf(file, "MOV\t%d(SP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_STORE_FRAME_32: fprintf(file, "MOVD\t%d(SP), %s", generator->mMemory[mProgStart + i + 1], TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 2; break; case BC_BINOP_ADDR_16: fprintf(file, "ADD\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_SUBR_16: fprintf(file, "SUB\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_MULR_16: fprintf(file, "MUL\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_DIVR_U16: fprintf(file, "DIVU\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_MODR_U16: fprintf(file, "MODU\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_DIVR_I16: fprintf(file, "DIVS\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_MODR_I16: fprintf(file, "MODS\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_ANDR_16: fprintf(file, "AND\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_ORR_16: fprintf(file, "OR\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_XORR_16: fprintf(file, "XOR\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_SHLR_16: fprintf(file, "SHL\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_SHRR_I16: fprintf(file, "SHRU\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_SHRR_U16: fprintf(file, "SHRI\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_ADDI_16: fprintf(file, "ADD\t%s, #$%04X", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_BINOP_SUBI_16: fprintf(file, "SUBR\t%s, #$%04X", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_BINOP_ANDI_16: fprintf(file, "AND\t%s, #$%04X", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_BINOP_ORI_16: fprintf(file, "OR\t%s, #$%04X", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_BINOP_MULI8_16: fprintf(file, "MUL\t%s, #%d", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc), generator->mMemory[mProgStart + i + 1]); i += 2; break; case BC_BINOP_SHLI_16: fprintf(file, "SHL\tACCU, #%d", uint8(generator->mMemory[mProgStart + i + 0])); i += 1; break; case BC_BINOP_SHRI_U16: fprintf(file, "SHRU\tACCU, #%d", uint8(generator->mMemory[mProgStart + i + 0])); i += 1; break; case BC_BINOP_SHRI_I16: fprintf(file, "SHRS\tACCU, #%d", uint8(generator->mMemory[mProgStart + i + 0])); i += 1; break; case BC_BINOP_CMPUR_16: fprintf(file, "CMPU\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_CMPSR_16: fprintf(file, "CMPS\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_CMPUI_16: fprintf(file, "CMPU\tACCU, #$%04X", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BINOP_CMPSI_16: fprintf(file, "CMPS\tACCU, #$%04X", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BINOP_ADD_F32: fprintf(file, "ADDF\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_SUB_F32: fprintf(file, "SUBF\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_MUL_F32: fprintf(file, "MULF\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_DIV_F32: fprintf(file, "DIVF\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_BINOP_CMP_F32: fprintf(file, "CMPF\tACCU, %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i += 1; break; case BC_COPY: fprintf(file, "COPY\t#%d", generator->mMemory[mProgStart + i + 0]); i++; break; case BC_COPY_LONG: fprintf(file, "COPYL\t#%d", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_OP_NEGATE_16: fprintf(file, "NEG\tACCU"); break; case BC_OP_INVERT_16: fprintf(file, "NOT\tACCU"); break; case BC_OP_NEGATE_F32: fprintf(file, "NEGF\tACCU"); break; case BC_OP_ABS_F32: fprintf(file, "ABSF\tACCU"); break; case BC_OP_FLOOR_F32: fprintf(file, "FLOORF\tACCU"); break; case BC_OP_CEIL_F32: fprintf(file, "CEILF\tACCU"); break; case BC_CONV_U16_F32: fprintf(file, "CNVUF\tACCU"); break; case BC_CONV_I16_F32: fprintf(file, "CNVSF\tACCU"); break; case BC_CONV_F32_U16: fprintf(file, "CNVFU\tACCU"); break; case BC_CONV_F32_I16: fprintf(file, "CNVFS\tACCU"); break; case BC_JUMPS: fprintf(file, "JUMP\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_EQ: fprintf(file, "BEQ\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_NE: fprintf(file, "BNE\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_GT: fprintf(file, "BGT\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_GE: fprintf(file, "BGE\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_LT: fprintf(file, "BLT\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_BRANCHS_LE: fprintf(file, "BLE\t$%04X", mProgStart + i + 1 + int8(generator->mMemory[mProgStart + i + 0])); i++; break; case BC_JUMPF: fprintf(file, "JUMPF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_EQ: fprintf(file, "BEQF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_NE: fprintf(file, "BNEF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_GT: fprintf(file, "BGTF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_GE: fprintf(file, "BGEF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_LT: fprintf(file, "BLTF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_BRANCHF_LE: fprintf(file, "BLEF\t$%04X", mProgStart + i + 2 + int16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_SET_EQ: fprintf(file, "SEQ"); break; case BC_SET_NE: fprintf(file, "SNE"); break; case BC_SET_GT: fprintf(file, "SGT"); break; case BC_SET_GE: fprintf(file, "SGE"); break; case BC_SET_LT: fprintf(file, "SLT"); break; case BC_SET_LE: fprintf(file, "SLE"); break; case BC_ENTER: fprintf(file, "ENTER\t%d, %d", generator->mMemory[mProgStart + i + 2], uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 3; break; case BC_RETURN: fprintf(file, "RETURN\t%d, %d", generator->mMemory[mProgStart + i], uint16(generator->mMemory[mProgStart + i + 1] + 256 * generator->mMemory[mProgStart + i + 2])); i += 3; break; case BC_CALL: fprintf(file, "CALL"); break; case BC_JSR: fprintf(file, "JSR\t$%04x", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_PUSH_FRAME: fprintf(file, "PUSH\t#$%04X", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_POP_FRAME: fprintf(file, "POP\t#$%04X", uint16(generator->mMemory[mProgStart + i + 0] + 256 * generator->mMemory[mProgStart + i + 1])); i += 2; break; case BC_LOAD_ADDR_U8: fprintf(file, "MOVUB\t%s, (ADDR)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_LOAD_ADDR_I8: fprintf(file, "MOVSB\t%s, (ADDR)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_LOAD_ADDR_16: fprintf(file, "MOV\t%s, (ADDR)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_LOAD_ADDR_32: fprintf(file, "MOVD\t%s, (ADDR)", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_STORE_ADDR_8: fprintf(file, "MOVB\t(ADDR), %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_STORE_ADDR_16: fprintf(file, "MOV\t(ADDR), %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; case BC_STORE_ADDR_32: fprintf(file, "MOV\t(ADDR), %s", TempName(generator->mMemory[mProgStart + i + 0], tbuffer, proc)); i++; break; } fprintf(file, "\n"); } } ByteCodeGenerator::ByteCodeGenerator(void) : mProcedureAddr({ 0 }), mGlobalAddr({ 0 }), mRelocations({ 0 }) { mProgStart = mProgEnd = 0x0801; for (int i = 0; i < 128; i++) mByteCodeUsed[i] = false; } ByteCodeGenerator::~ByteCodeGenerator(void) { } int ByteCodeGenerator::AddGlobal(int index, const Ident* ident, int size, const uint8* data, bool assembler) { int addr = mProgEnd; AddAddress(index, false, addr, size, ident, assembler); if (data) { for (int i = 0; i < size; i++) mMemory[mProgEnd + i] = data[i]; } else { for (int i = 0; i < size; i++) mMemory[mProgEnd + i] = 0; } mProgEnd += size; return addr; } void ByteCodeGenerator::AddAddress(int index, bool function, int address, int size, const Ident* ident, bool assembler) { Address addr; addr.mIndex = index; addr.mFunction = function; addr.mAddress = address; addr.mSize = size; addr.mIdent = ident; addr.mAssembler = assembler; if (function) mProcedureAddr[index] = addr; else mGlobalAddr[index] = addr; } void ByteCodeGenerator::WriteBasicHeader(void) { mMemory[mProgEnd++] = 0x0b; mMemory[mProgEnd++] = 0x08; mMemory[mProgEnd++] = 0x0a; mMemory[mProgEnd++] = 0x00; mMemory[mProgEnd++] = 0x9e; mMemory[mProgEnd++] = 0x32; mMemory[mProgEnd++] = 0x30; mMemory[mProgEnd++] = 0x36; mMemory[mProgEnd++] = 0x31; mMemory[mProgEnd++] = 0x00; mMemory[mProgEnd++] = 0x00; mMemory[mProgEnd++] = 0x00; } void ByteCodeGenerator::SetBasicEntry(int index) { mProgEntry = index; } void ByteCodeGenerator::WriteByteCodeHeader(void) { int n = mProgEnd + 6; mMemory[mProgEnd++] = BC_LEA_ABS * 2; mMemory[mProgEnd++] = BC_REG_ADDR; mMemory[mProgEnd++] = n & 255; mMemory[mProgEnd++] = n >> 8; mMemory[mProgEnd++] = BC_CALL * 2; mMemory[mProgEnd++] = BC_EXIT * 2; mByteCodeUsed[BC_LEA_ABS] = true; mByteCodeUsed[BC_CALL] = true; mByteCodeUsed[BC_EXIT] = true; } void ByteCodeGenerator::ResolveRelocations(void) { for (int i = 0; i < mRelocations.Size(); i++) { int dp = mRelocations[i].mAddr; int sp; if (mRelocations[i].mFunction) sp = mProcedureAddr[mRelocations[i].mIndex].mAddress + mRelocations[i].mOffset; else sp = mGlobalAddr[mRelocations[i].mIndex].mAddress + mRelocations[i].mOffset; if (mRelocations[i].mLower) mMemory[dp++] = sp & 255; if (mRelocations[i].mUpper) mMemory[dp++] = sp >> 8; } int entry = mGlobalAddr[mProgEntry].mAddress; mMemory[mProgStart + 5] = (entry / 1000) % 10 + '0'; mMemory[mProgStart + 6] = (entry / 100) % 10 + '0'; mMemory[mProgStart + 7] = (entry / 10) % 10 + '0'; mMemory[mProgStart + 8] = entry % 10 + '0'; } bool ByteCodeGenerator::WritePRGFile(const char* filename) { FILE* file; fopen_s(&file, filename, "wb"); if (file) { mMemory[mProgStart - 2] = mProgStart & 0xff; mMemory[mProgStart - 1] = mProgStart >> 8; int done = fwrite(mMemory + mProgStart - 2, 1, mProgEnd - mProgStart + 2, file); fclose(file); return done == mProgEnd - mProgStart + 2; } else return false; } void ByteCodeGenerator::WriteAsmFile(FILE* file) { for (int i = 0; i < mGlobalAddr.Size(); i++) { if (mGlobalAddr[i].mAssembler) { fprintf(file, "--------------------------------------------------------------------\n"); if (mGlobalAddr[i].mIdent) fprintf(file, "%s:\n", mGlobalAddr[i].mIdent->mString); int ip = mGlobalAddr[i].mAddress; while (ip < mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize) { int iip = ip; uint8 opcode = mMemory[ip++]; AsmInsData d = DecInsData[opcode]; int addr = 0; switch (d.mMode) { case ASMIM_IMPLIED: fprintf(file, "%04x : %04x %02x __ __ %s\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType]); break; case ASMIM_IMMEDIATE: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s #$%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE_X: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE_Y: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s $%02x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ABSOLUTE: addr = mMemory[ip] + 256 * mMemory[ip + 1]; fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_ABSOLUTE_X: addr = mMemory[ip] + 256 * mMemory[ip + 1]; fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,x\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_ABSOLUTE_Y: addr = mMemory[ip] + 256 * mMemory[ip + 1]; fprintf(file, "%04x : %04x %02x %02x %02x %s $%04x,y\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_INDIRECT: addr = mMemory[ip] + 256 * mMemory[ip + 1]; ip += 2; fprintf(file, "%04x : %04x %02x %02x %02x %s ($%04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); break; case ASMIM_INDIRECT_X: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x,x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_INDIRECT_Y: addr = mMemory[ip++]; fprintf(file, "%04x : %04x %02x %02x __ %s ($%02x),y\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_RELATIVE: addr = mMemory[ip++]; if (addr & 0x80) addr = addr + ip - 256; else addr = addr + ip; fprintf(file, "%04x : %04x %02x %02x __ %s $%02x\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); break; } } } } } bool ByteCodeGenerator::WriteMapFile(const char* filename) { FILE* file; fopen_s(&file, filename, "wb"); if (file) { for (int i = 0; i < mProcedureAddr.Size(); i++) { if (mProcedureAddr[i].mIdent) fprintf(file, "%04x - %04x : F %s\n", mProcedureAddr[i].mAddress, mProcedureAddr[i].mAddress + mProcedureAddr[i].mSize, mProcedureAddr[i].mIdent->mString); else fprintf(file, "%04x - %04x : F\n", mProcedureAddr[i].mAddress, mProcedureAddr[i].mAddress + mProcedureAddr[i].mSize); } for (int i = 0; i < mGlobalAddr.Size(); i++) { if (mGlobalAddr[i].mAssembler) { if (mGlobalAddr[i].mIdent) fprintf(file, "%04x - %04x : A %s\n", mGlobalAddr[i].mAddress, mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize, mGlobalAddr[i].mIdent->mString); else fprintf(file, "%04x - %04x : A\n", mGlobalAddr[i].mAddress, mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize); } else { if (mGlobalAddr[i].mIdent) fprintf(file, "%04x - %04x : V %s\n", mGlobalAddr[i].mAddress, mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize, mGlobalAddr[i].mIdent->mString); else fprintf(file, "%04x - %04x : V\n", mGlobalAddr[i].mAddress, mGlobalAddr[i].mAddress + mGlobalAddr[i].mSize); } } return true; } else return false; }