Improve zero page addressing of global variables in inline assembler

This commit is contained in:
drmortalwombat 2024-12-01 15:33:51 +01:00
parent 907452d918
commit 803b868356
4 changed files with 76 additions and 23 deletions

View File

@ -174,13 +174,13 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
linkerObject = bcdec->mLinkerObject; linkerObject = bcdec->mLinkerObject;
} }
else if (bcdec->mType == DT_LABEL) else if (bcdec->mType == DT_LABEL)
{ {
if (!bcdec->mBase->mLinkerObject) if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
linkerObject = bcdec->mBase->mLinkerObject; linkerObject = bcdec->mBase->mLinkerObject;
offset = int(bcdec->mInteger); offset = int(bcdec->mInteger);
@ -910,7 +910,7 @@ bool Compiler::GenerateCode(void)
if (mCompilerOptions & COPT_VERBOSE) if (mCompilerOptions & COPT_VERBOSE)
printf("Generate intermediate code\n"); printf("Generate intermediate code\n");
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart, nullptr);
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++) for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
{ {
Declaration* dec = mCompilationUnits->mReferenced[i]; Declaration* dec = mCompilationUnits->mReferenced[i];
@ -993,7 +993,7 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject; mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
} }
} }
@ -1068,13 +1068,13 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
linkerObject = bcdec->mLinkerObject; linkerObject = bcdec->mLinkerObject;
} }
else if (bcdec->mType == DT_LABEL) else if (bcdec->mType == DT_LABEL)
{ {
if (!bcdec->mBase->mLinkerObject) if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
linkerObject = bcdec->mBase->mLinkerObject; linkerObject = bcdec->mBase->mLinkerObject;
offset = int(bcdec->mInteger); offset = int(bcdec->mInteger);
} }

View File

@ -825,16 +825,46 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
} }
} }
void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* exp, GrowingArray<Declaration*> * refvars) void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Declaration * adec,GrowingArray<Declaration*> * refvars)
{ {
int offset = 0, osize = 0; Expression* exp = adec->mValue;
GrowingArray<int> offsetMap(-1);
int offset = 0, osize = 0, rsize = 0;
Expression* cexp = exp; Expression* cexp = exp;
while (cexp) while (cexp)
{ {
offsetMap[rsize] = osize;
rsize += AsmInsSize(cexp->mAsmInsType, cexp->mAsmInsMode);
#if 1
Declaration* aexp = nullptr;
if (cexp->mLeft)
aexp = cexp->mLeft->mDecValue;
if (cexp->mAsmInsMode == ASMIM_ABSOLUTE && HasAsmInstructionMode(cexp->mAsmInsType, ASMIM_ZERO_PAGE) && aexp->mType == DT_VARIABLE && (aexp->mFlags & DTF_GLOBAL) && (aexp->mFlags & DTF_ZEROPAGE))
{
cexp->mAsmInsMode = ASMIM_ZERO_PAGE;
}
else if (cexp->mAsmInsMode == ASMIM_ABSOLUTE && HasAsmInstructionMode(cexp->mAsmInsType, ASMIM_ZERO_PAGE) && aexp->mType == DT_VARIABLE_REF && (aexp->mBase->mFlags & DTF_GLOBAL) && (aexp->mBase->mFlags & DTF_ZEROPAGE))
{
cexp->mAsmInsMode = ASMIM_ZERO_PAGE;
}
#endif
osize += AsmInsSize(cexp->mAsmInsType, cexp->mAsmInsMode); osize += AsmInsSize(cexp->mAsmInsType, cexp->mAsmInsMode);
cexp = cexp->mRight; cexp = cexp->mRight;
} }
// Check if remapping of lables due to operand address size change
if (osize != rsize)
{
adec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* dec) {
if (dec->mType == DT_LABEL)
dec->mInteger = offsetMap[int(dec->mInteger)];
});
}
Declaration* dec = exp->mDecValue; Declaration* dec = exp->mDecValue;
dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_NATIVE_CODE, dec->mAlignment); dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_NATIVE_CODE, dec->mAlignment);
@ -846,16 +876,16 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
cexp = exp; cexp = exp;
while (cexp) while (cexp)
{ {
Declaration* aexp = nullptr;
if (cexp->mLeft)
aexp = cexp->mLeft->mDecValue;
if (cexp->mAsmInsType != ASMIT_BYTE) if (cexp->mAsmInsType != ASMIT_BYTE)
{ {
int opcode = AsmInsOpcodes[cexp->mAsmInsType][cexp->mAsmInsMode]; int opcode = AsmInsOpcodes[cexp->mAsmInsType][cexp->mAsmInsMode];
d[offset++] = opcode; d[offset++] = opcode;
} }
Declaration* aexp = nullptr;
if (cexp->mLeft)
aexp = cexp->mLeft->mDecValue;
switch (cexp->mAsmInsMode) switch (cexp->mAsmInsMode)
{ {
case ASMIM_IMPLIED: case ASMIM_IMPLIED:
@ -870,7 +900,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
if (aexp->mBase->mBase) if (aexp->mBase->mBase)
{ {
if (!aexp->mBase->mBase->mLinkerObject) if (!aexp->mBase->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mBase->mValue, nullptr); TranslateAssembler(mod, aexp->mBase->mBase, nullptr);
LinkerReference ref; LinkerReference ref;
ref.mObject = dec->mLinkerObject; ref.mObject = dec->mLinkerObject;
@ -977,7 +1007,20 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand");
else if (aexp->mType == DT_VARIABLE_REF) else if (aexp->mType == DT_VARIABLE_REF)
{ {
if (refvars) if (aexp->mBase->mFlags & DTF_GLOBAL)
{
InitGlobalVariable(mod, aexp->mBase);
LinkerReference ref;
ref.mObject = dec->mLinkerObject;
ref.mOffset = offset;
ref.mFlags = LREF_LOWBYTE;
ref.mRefObject = aexp->mBase->mLinkerObject;
ref.mRefOffset = aexp->mOffset;
ref.mRefObject->mFlags |= LOBJF_RELEVANT;
dec->mLinkerObject->AddReference(ref);
}
else if (refvars)
{ {
int j = 0; int j = 0;
while (j < refvars->Size() && (*refvars)[j] != aexp->mBase) while (j < refvars->Size() && (*refvars)[j] != aexp->mBase)
@ -1056,7 +1099,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
if (aexp->mBase) if (aexp->mBase)
{ {
if (!aexp->mBase->mLinkerObject) if (!aexp->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mValue, nullptr); TranslateAssembler(mod, aexp->mBase, nullptr);
LinkerReference ref; LinkerReference ref;
ref.mObject = dec->mLinkerObject; ref.mObject = dec->mLinkerObject;
@ -1075,7 +1118,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
if (aexp->mBase->mBase) if (aexp->mBase->mBase)
{ {
if (!aexp->mBase->mBase->mLinkerObject) if (!aexp->mBase->mBase->mLinkerObject)
TranslateAssembler(mod, aexp->mBase->mBase->mValue, nullptr); TranslateAssembler(mod, aexp->mBase->mBase, nullptr);
LinkerReference ref; LinkerReference ref;
ref.mObject = dec->mLinkerObject; ref.mObject = dec->mLinkerObject;
@ -1092,7 +1135,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
else if (aexp->mType == DT_CONST_ASSEMBLER) else if (aexp->mType == DT_CONST_ASSEMBLER)
{ {
if (!aexp->mLinkerObject) if (!aexp->mLinkerObject)
TranslateAssembler(mod, aexp->mValue, nullptr); TranslateAssembler(mod, aexp, nullptr);
LinkerReference ref; LinkerReference ref;
ref.mObject = dec->mLinkerObject; ref.mObject = dec->mLinkerObject;
@ -1203,7 +1246,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
cexp = cexp->mRight; cexp = cexp->mRight;
} }
assert(offset == osize); assert(offset < osize);
} }
void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock) void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock)
@ -2234,7 +2277,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case DT_CONST_ASSEMBLER: case DT_CONST_ASSEMBLER:
{ {
if (!dec->mLinkerObject) if (!dec->mLinkerObject)
TranslateAssembler(proc->mModule, dec->mValue, nullptr); TranslateAssembler(proc->mModule, dec, nullptr);
InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
ins->mDst.mType = IT_POINTER; ins->mDst.mType = IT_POINTER;
@ -2251,7 +2294,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case DT_LABEL: case DT_LABEL:
{ {
if (!dec->mBase->mLinkerObject) if (!dec->mBase->mLinkerObject)
TranslateAssembler(proc->mModule, dec->mBase->mValue, nullptr); TranslateAssembler(proc->mModule, dec->mBase, nullptr);
InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
ins->mDst.mType = IT_POINTER; ins->mDst.mType = IT_POINTER;
@ -4222,7 +4265,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
GrowingArray<Declaration*> refvars(nullptr); GrowingArray<Declaration*> refvars(nullptr);
TranslateAssembler(proc->mModule, exp, &refvars); TranslateAssembler(proc->mModule, exp->mDecValue, &refvars);
Declaration* dec = exp->mDecValue; Declaration* dec = exp->mDecValue;
@ -5627,7 +5670,7 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int
else if (data->mType == DT_CONST_ASSEMBLER) else if (data->mType == DT_CONST_ASSEMBLER)
{ {
if (!data->mLinkerObject) if (!data->mLinkerObject)
TranslateAssembler(mod, data->mValue, nullptr); TranslateAssembler(mod, data, nullptr);
LinkerReference ref; LinkerReference ref;
ref.mObject = variable->mLinkerObject; ref.mObject = variable->mLinkerObject;

View File

@ -45,7 +45,7 @@ public:
uint64 mCompilerOptions; uint64 mCompilerOptions;
InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec); InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec);
void TranslateAssembler(InterCodeModule* mod, Expression * exp, GrowingArray<Declaration *> * refvars); void TranslateAssembler(InterCodeModule* mod, Declaration* adec,GrowingArray<Declaration *> * refvars);
void InitGlobalVariable(InterCodeModule* mod, Declaration* dec); void InitGlobalVariable(InterCodeModule* mod, Declaration* dec);
void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index); void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index);
void InitParameter(InterCodeProcedure* proc, Declaration* dec, int index); void InitParameter(InterCodeProcedure* proc, Declaration* dec, int index);

View File

@ -14021,6 +14021,11 @@ NativeCodeInstruction NativeCodeBasicBlock::DecodeNative(const InterInstruction*
address = lobj->mData[offset++]; address = lobj->mData[offset++];
if (lref && (lref->mFlags & LREF_TEMPORARY)) if (lref && (lref->mFlags & LREF_TEMPORARY))
address += lobj->mTemporaries[lref->mRefOffset]; address += lobj->mTemporaries[lref->mRefOffset];
else if (lref)
{
linkerObject = lref->mRefObject;
address = lref->mRefOffset;
}
else if (address >= BC_REG_TMP) else if (address >= BC_REG_TMP)
flags |= NCIF_VOLATILE; flags |= NCIF_VOLATILE;
break; break;
@ -14124,6 +14129,11 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodePro
if (dins.mMode == ASMIM_ZERO_PAGE && dins.mAddress >= BC_REG_WORK && dins.mAddress < BC_REG_WORK + 8) if (dins.mMode == ASMIM_ZERO_PAGE && dins.mAddress >= BC_REG_WORK && dins.mAddress < BC_REG_WORK + 8)
uflags |= NICF_USE_WORKREGS; uflags |= NICF_USE_WORKREGS;
// Make sure we are not aliasing zeropage globals
if (dins.mMode == ASMIM_ZERO_PAGE && dins.mLinkerObject)
dins.mMode = ASMIM_ABSOLUTE;
if (dins.ChangesAccu()) if (dins.ChangesAccu())
uflags |= NCIF_USE_CPU_REG_A; uflags |= NCIF_USE_CPU_REG_A;
if (dins.ChangesXReg()) if (dins.ChangesXReg())