Prepare access to local variables in inline assembler

This commit is contained in:
drmortalwombat 2021-10-07 10:42:18 +02:00
parent df152c2f9b
commit fb4ae26afb
11 changed files with 179 additions and 65 deletions

View File

@ -1899,6 +1899,27 @@ void ByteCodeBasicBlock::CallFunction(InterCodeProcedure* proc, const InterInstr
}
void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins)
{
if (ins->mSrc[0].mTemp < 0)
{
ByteCodeInstruction bins(BC_JSR);
bins.mRelocate = true;
bins.mLinkerObject = ins->mLinkerObject;
bins.mValue = ins->mSrc[0].mIntConst;
for (int i = 1; i < ins->mNumOperands; i++)
ins->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)
{
@ -2879,6 +2900,8 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
CallFunction(iproc, ins);
break;
case IC_CALL_NATIVE:
CallNative(iproc, ins);
break;
case IC_ASSEMBLER:
CallAssembler(iproc, ins);
break;

View File

@ -261,6 +261,7 @@ public:
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins);
void CallFunction(InterCodeProcedure* proc, const InterInstruction * ins);
void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins);
void CallNative(InterCodeProcedure* proc, const InterInstruction* ins);
void BinaryOperator(InterCodeProcedure* proc, const InterInstruction * ins);
void UnaryOperator(InterCodeProcedure* proc, const InterInstruction * ins);
void BinaryRROperator(InterCodeProcedure* proc, const InterInstruction * ins);

View File

@ -83,13 +83,13 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
if (bcdec->mType == DT_CONST_ASSEMBLER)
{
if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
linkerObject = bcdec->mLinkerObject;
}
else if (bcdec->mType == DT_LABEL)
{
if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
linkerObject = bcdec->mBase->mLinkerObject;
offset = bcdec->mInteger;
@ -157,7 +157,7 @@ bool Compiler::GenerateCode(void)
dcrtstart->mSection = sectionStartup;
mInterCodeGenerator->mForceNativeCode = mNativeCode;
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);
if (mErrors->mErrorCount != 0)
return false;
@ -201,7 +201,7 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER)
{
if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
}
}
@ -252,13 +252,13 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER)
{
if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
linkerObject = bcdec->mLinkerObject;
}
else if (bcdec->mType == DT_LABEL)
{
if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue);
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
linkerObject = bcdec->mBase->mLinkerObject;
offset = bcdec->mInteger;
}

View File

@ -61,7 +61,6 @@ static const uint32 DTF_UPPER_BYTE = 0x00000400;
static const uint32 DTF_LOWER_BYTE = 0x00000800;
static const uint32 DTF_SECTION_START = 0x00001000;
static const uint32 DTF_SECTION_END = 0x00002000;
static const uint32 DTF_PARAM_PTR = 0x00004000;
static const uint32 DTF_INLINE = 0x00008000;
class Declaration;

View File

@ -241,7 +241,7 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
}
}
void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * exp)
void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* exp, GrowingArray<Declaration*> * refvars)
{
int offset = 0, osize = 0;
Expression* cexp = exp;
@ -257,6 +257,8 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
uint8* d = dec->mLinkerObject->AddSpace(osize);
GrowingArray<Declaration*> refVars(nullptr);
cexp = exp;
while (cexp)
{
@ -280,7 +282,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
else if (aexp->mType == DT_LABEL_REF)
{
if (!aexp->mBase->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mBase->mValue);
TranslateAssembler(mod, aexp->mBase->mBase->mValue, nullptr);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
@ -344,17 +346,57 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
case ASMIM_ZERO_PAGE_X:
case ASMIM_INDIRECT_X:
case ASMIM_INDIRECT_Y:
if (aexp->mFlags & DTF_PARAM_PTR)
if (aexp->mType == DT_VARIABLE_REF)
{
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
ref.mOffset = offset;
ref.mFlags = LREF_PARAM_PTR;
ref.mRefObject = dec->mLinkerObject;
ref.mRefOffset = 0;
dec->mLinkerObject->AddReference(ref);
if (refvars)
{
int j = 0;
while (j < refvars->Size() && (*refvars)[j] != aexp->mBase)
j++;
if (j == refvars->Size())
refvars->Push(aexp->mBase);
offset += 1;
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
ref.mOffset = offset;
ref.mFlags = LREF_TEMPORARY;
ref.mRefObject = dec->mLinkerObject;
ref.mRefOffset = j;
dec->mLinkerObject->AddReference(ref);
d[offset++] = aexp->mOffset;
}
else
{
mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Local variable outside scope");
offset += 1;
}
}
else if (aexp->mType == DT_ARGUMENT || aexp->mType == DT_VARIABLE)
{
if (refvars)
{
int j = 0;
while (j < refvars->Size() && (*refvars)[j] != aexp)
j++;
if (j == refvars->Size())
refvars->Push(aexp);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
ref.mOffset = offset;
ref.mFlags = LREF_TEMPORARY;
ref.mRefObject = dec->mLinkerObject;
ref.mRefOffset = j;
dec->mLinkerObject->AddReference(ref);
d[offset++] = 0;
}
else
{
mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Local variable outside scope");
offset += 1;
}
}
else
d[offset++] = aexp->mInteger;
@ -373,7 +415,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
if (aexp->mBase)
{
if (!aexp->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mValue);
TranslateAssembler(mod, aexp->mBase->mValue, nullptr);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
@ -391,7 +433,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
else if (aexp->mType == DT_LABEL_REF)
{
if (!aexp->mBase->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mBase->mValue);
TranslateAssembler(mod, aexp->mBase->mBase->mValue, nullptr);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
@ -406,7 +448,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression * e
else if (aexp->mType == DT_CONST_ASSEMBLER)
{
if (!aexp->mLinkerObject)
TranslateAssembler(mod, aexp->mValue);
TranslateAssembler(mod, aexp->mValue, nullptr);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
@ -1860,7 +1902,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_ASSEMBLER:
{
TranslateAssembler(proc->mModule, exp);
GrowingArray<Declaration*> refvars(nullptr);
TranslateAssembler(proc->mModule, exp, &refvars);
Declaration* dec = exp->mDecValue;
@ -1883,6 +1927,40 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
jins->mCode = IC_ASSEMBLER;
jins->mSrc[0].mType = IT_POINTER;
jins->mSrc[0].mTemp = ins->mDst.mTemp;
jins->mNumOperands = 1;
for (int i = 0; i < refvars.Size(); i++)
{
InterInstruction* vins = new InterInstruction();
vins->mCode = IC_CONSTANT;
vins->mDst.mType = IT_POINTER;
vins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
Declaration* vdec = refvars[i];
if (vdec->mType == DT_ARGUMENT)
{
vins->mMemory = IM_PARAM;
vins->mOperandSize = vdec->mSize;
vins->mIntValue = vdec->mOffset;
vins->mVarIndex = vdec->mVarIndex;
}
block->Append(vins);
InterInstruction* lins = new InterInstruction();
lins->mCode = IC_LOAD;
lins->mMemory = IM_INDIRECT;
lins->mSrc[0].mType = IT_POINTER;
lins->mSrc[0].mTemp = vins->mDst.mTemp;
lins->mDst.mType = InterTypeOf(vdec->mBase);
lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType);
lins->mOperandSize = vdec->mSize;
block->Append(lins);
jins->mSrc[jins->mNumOperands].mType = InterTypeOf(vdec->mBase);
jins->mSrc[jins->mNumOperands].mTemp = lins->mDst.mTemp;
jins->mNumOperands++;
}
block->Append(jins);
}
@ -2505,7 +2583,7 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int
else if (data->mType == DT_CONST_ASSEMBLER)
{
if (!data->mLinkerObject)
TranslateAssembler(mod, data->mValue);
TranslateAssembler(mod, data->mValue, nullptr);
LinkerReference ref;
ref.mObject = variable->mLinkerObject;

View File

@ -23,7 +23,7 @@ public:
bool mForceNativeCode;
InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec);
void TranslateAssembler(InterCodeModule* mod, Expression * exp);
void TranslateAssembler(InterCodeModule* mod, Expression * exp, GrowingArray<Declaration *> * refvars);
void InitGlobalVariable(InterCodeModule* mod, Declaration* dec);
protected:

View File

@ -12,7 +12,7 @@ LinkerSection::LinkerSection(void)
{}
LinkerObject::LinkerObject(void)
: mReferences(nullptr)
: mReferences(nullptr), mNumTemporaries(0)
{}
LinkerObject::~LinkerObject(void)
@ -285,13 +285,8 @@ void Linker::Link(void)
*dp++ = raddr & 0xff;
if (ref->mFlags & LREF_HIGHBYTE)
*dp++ = (raddr >> 8) & 0xff;
if (ref->mFlags & LREF_PARAM_PTR)
{
if (obj->mFlags & LOBJF_NO_FRAME)
*dp++ = BC_REG_STACK;
else
*dp++ = BC_REG_LOCALS;
}
if (ref->mFlags & LREF_TEMPORARY)
*dp += obj->mTemporaries[ref->mRefOffset];
}
}
}

View File

@ -50,7 +50,7 @@ public:
static const uint32 LREF_LOWBYTE = 0x00000001;
static const uint32 LREF_HIGHBYTE = 0x00000002;
static const uint32 LREF_PARAM_PTR = 0x00000004;
static const uint32 LREF_TEMPORARY = 0x00000004;
class LinkerReference
{
@ -92,6 +92,8 @@ public:
uint8 * mData;
InterCodeProcedure* mProc;
uint32 mFlags;
uint8 mTemporaries[16], mTempSizes[16];
int mNumTemporaries;
LinkerObject(void);
~LinkerObject(void);

View File

@ -87,6 +87,14 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
{
requiredTemps += BC_REG_LOCALS;
requiredTemps += BC_REG_LOCALS + 1;
if (mLinkerObject)
{
for (int i = 0; i < mLinkerObject->mNumTemporaries; i++)
{
for (int j = 0; j < mLinkerObject->mTempSizes[i]; j++)
requiredTemps += mLinkerObject->mTemporaries[i] + j;
}
}
}
return true;
@ -1968,13 +1976,20 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
for (int i = 0; i < mLinkerObject->mReferences.Size(); i++)
{
LinkerReference rl = *(mLinkerObject->mReferences[i]);
rl.mOffset += pos;
if (rl.mRefObject == rl.mObject)
if (rl.mFlags & LREF_TEMPORARY)
{
rl.mRefObject = nullptr;
rl.mRefOffset += pos;
block->mCode[pos + rl.mOffset] += mLinkerObject->mTemporaries[rl.mRefOffset];
}
else
{
rl.mOffset += pos;
if (rl.mRefObject == rl.mObject)
{
rl.mRefObject = nullptr;
rl.mRefOffset += pos;
}
block->mRelocations.Push(rl);
}
block->mRelocations.Push(rl);
}
}
else
@ -2047,13 +2062,13 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
void NativeCodeBasicBlock::PutByte(uint8 code)
{
this->mCode.Insert(code);
this->mCode.Push(code);
}
void NativeCodeBasicBlock::PutWord(uint16 code)
{
this->mCode.Insert((uint8)(code & 0xff));
this->mCode.Insert((uint8)(code >> 8));
this->mCode.Push((uint8)(code & 0xff));
this->mCode.Push((uint8)(code >> 8));
}
static AsmInsType InvertBranchCondition(AsmInsType code)
@ -5940,8 +5955,15 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc
void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins)
{
if (ins->mCode == IC_ASSEMBLER && mNoFrame)
ins->mLinkerObject->mFlags |= LOBJF_NO_FRAME;
if (ins->mCode == IC_ASSEMBLER)
{
for (int i = 1; i < ins->mNumOperands; i++)
{
ins->mLinkerObject->mTemporaries[i - 1] = BC_REG_TMP + proc->mTempOffset[ins->mSrc[i].mTemp];
ins->mLinkerObject->mTempSizes[i - 1] = InterTypeSize[ins->mSrc[i].mType];
}
ins->mLinkerObject->mNumTemporaries = ins->mNumOperands - 1;
}
assert(ins->mLinkerObject);
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mLinkerObject));
@ -7503,7 +7525,7 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
for (i = 0; i < mCode.Size(); i++)
{
mCode.Lookup(i, target[i + mOffset]);
target[i + mOffset] = mCode[i];
}
for (int i = 0; i < mRelocations.Size(); i++)
@ -7650,7 +7672,7 @@ void NativeCodeBasicBlock::CalculateOffset(int& total)
}
NativeCodeBasicBlock::NativeCodeBasicBlock(void)
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 }), mEntryBlocks(nullptr)
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 }), mEntryBlocks(nullptr), mCode(0)
{
mTrueJump = mFalseJump = NULL;
mOffset = 0x7fffffff;

View File

@ -81,7 +81,7 @@ public:
NativeCodeBasicBlock(void);
~NativeCodeBasicBlock(void);
DynamicArray<uint8> mCode;
GrowingArray<uint8> mCode;
int mIndex;
NativeCodeBasicBlock* mTrueJump, * mFalseJump, * mFromJump;

View File

@ -1896,10 +1896,6 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
exp = new Expression(mScanner->mLocation, EX_CONSTANT);
if (dec->mType == DT_ARGUMENT)
{
Declaration* ndec = new Declaration(exp->mLocation, DT_CONST_INTEGER);
ndec->mBase = TheUnsignedIntTypeDeclaration;
ndec->mInteger = 2 + dec->mVarIndex;
dec = ndec;
exp->mDecType = TheUnsignedIntTypeDeclaration;
}
else if (dec->mType == DT_CONST_ASSEMBLER)
@ -2171,14 +2167,6 @@ Expression* Parser::ParseAssembler(void)
mScanner->SetAssemblerMode(true);
Declaration* decfp = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
decfp->mIdent = Ident::Unique("fp");
decfp->mBase = TheUnsignedIntTypeDeclaration;
decfp->mSize = 2;
decfp->mInteger = BC_REG_LOCALS;
decfp->mFlags = DTF_PARAM_PTR;
mScope->Insert(decfp->mIdent, decfp);
Declaration* decaccu = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
decaccu->mIdent = Ident::Unique("accu");
decaccu->mBase = TheUnsignedIntTypeDeclaration;
@ -2314,14 +2302,20 @@ Expression* Parser::ParseAssembler(void)
}
}
if (ilast->mLeft && ilast->mLeft->mDecValue && ilast->mLeft->mDecValue->mType == DT_CONST_INTEGER && ilast->mLeft->mDecValue->mInteger < 256)
if (ilast->mLeft && ilast->mLeft->mDecValue)
{
if (ilast->mAsmInsMode == ASMIM_ABSOLUTE && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE;
else if (ilast->mAsmInsMode == ASMIM_ABSOLUTE_X && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE_X))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE_X;
else if (ilast->mAsmInsMode == ASMIM_ABSOLUTE_Y && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE_Y))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE_Y;
if ((ilast->mLeft->mDecValue->mType == DT_CONST_INTEGER && ilast->mLeft->mDecValue->mInteger < 256) ||
(ilast->mLeft->mDecValue->mType == DT_VARIABLE_REF && !(ilast->mLeft->mDecValue->mBase->mFlags & DTF_GLOBAL)) ||
(ilast->mLeft->mDecValue->mType == DT_VARIABLE && !(ilast->mLeft->mDecValue->mFlags & DTF_GLOBAL)) ||
ilast->mLeft->mDecValue->mType == DT_ARGUMENT)
{
if (ilast->mAsmInsMode == ASMIM_ABSOLUTE && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE;
else if (ilast->mAsmInsMode == ASMIM_ABSOLUTE_X && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE_X))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE_X;
else if (ilast->mAsmInsMode == ASMIM_ABSOLUTE_Y && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE_Y))
ilast->mAsmInsMode = ASMIM_ZERO_PAGE_Y;
}
}
if (ilast->mAsmInsType == ASMIT_BYTE)