Fix carry usage check in inline assembler, add optional volatile to __asm
This commit is contained in:
parent
1c7d71cadb
commit
c98e0751b0
|
@ -935,6 +935,11 @@ The compiler provides two levels of interrupt safe functions. The specifier __i
|
|||
return 0
|
||||
}
|
||||
|
||||
### Assembler optimizer
|
||||
|
||||
The compiler uses various optimizations on inline assembler that may not have the expected result in all cases. The optimizer can be disabled for a range of code with e.g. #pragma optimize(noasm) or for an individual __asm statement by using __asm volatile {}.
|
||||
The assembler optimizer is enabled with optimization levels O2 and up.
|
||||
|
||||
# Helping the compiler optimizing
|
||||
|
||||
The compiler does various optimization when compiling the code, but there are some rules to follow, things to avoid and hints to place to help the compiler to generate optimal code.
|
||||
|
|
|
@ -4335,6 +4335,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
jins->mDst.mTemp = proc->AddTemporary(IT_INT32);
|
||||
jins->mDst.mType = IT_INT32;
|
||||
|
||||
if (dec->mFlags & DTF_VOLATILE)
|
||||
jins->mVolatile = true;
|
||||
|
||||
jins->mSrc[0].mType = IT_POINTER;
|
||||
jins->mSrc[0].mTemp = ins->mDst.mTemp;
|
||||
jins->mNumOperands = 1;
|
||||
|
|
|
@ -642,6 +642,8 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
|
|||
requiredTemps += CPU_REG_X;
|
||||
if (mFlags & NCIF_USE_CPU_REG_Y)
|
||||
requiredTemps += CPU_REG_Y;
|
||||
if (mFlags & NCIF_USE_CPU_REG_C)
|
||||
requiredTemps += CPU_REG_C;
|
||||
|
||||
if (mFlags & NCIF_RUNTIME)
|
||||
{
|
||||
|
@ -1611,9 +1613,17 @@ bool NativeCodeInstruction::ChangesGlobalMemory(void) const
|
|||
|
||||
bool NativeCodeInstruction::RequiresCarry(void) const
|
||||
{
|
||||
return
|
||||
mType == ASMIT_ADC || mType == ASMIT_SBC ||
|
||||
mType == ASMIT_ROL || mType == ASMIT_ROR;
|
||||
if (mType == ASMIT_ADC || mType == ASMIT_SBC ||
|
||||
mType == ASMIT_ROL || mType == ASMIT_ROR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (mType == ASMIT_JSR)
|
||||
{
|
||||
return mFlags & NCIF_USE_CPU_REG_C;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeInstruction::ChangesZFlag(void) const
|
||||
|
@ -4706,6 +4716,11 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
|
|||
if (!providedTemps[CPU_REG_Y])
|
||||
requiredTemps += CPU_REG_Y;
|
||||
}
|
||||
if (mFlags & NCIF_USE_CPU_REG_C)
|
||||
{
|
||||
if (!providedTemps[CPU_REG_C])
|
||||
requiredTemps += CPU_REG_C;
|
||||
}
|
||||
|
||||
if (mFlags & NCIF_RUNTIME)
|
||||
{
|
||||
|
@ -14297,7 +14312,7 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodePro
|
|||
|
||||
assert(ins->mSrc[0].mLinkerObject);
|
||||
|
||||
if (ins->mCode == IC_ASSEMBLER && (proc->mCompilerOptions & COPT_OPTIMIZE_ASSEMBLER) && ins->mSrc[0].mLinkerObject->mSection == proc->mLinkerObject->mSection)
|
||||
if (ins->mCode == IC_ASSEMBLER && (proc->mCompilerOptions & COPT_OPTIMIZE_ASSEMBLER) && ins->mSrc[0].mLinkerObject->mSection == proc->mLinkerObject->mSection && !ins->mVolatile)
|
||||
{
|
||||
ExpandingArray<NativeCodeInstruction> tains;
|
||||
|
||||
|
@ -14339,6 +14354,8 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodePro
|
|||
uflags |= NCIF_USE_CPU_REG_X;
|
||||
if (dins.ChangesYReg())
|
||||
uflags |= NCIF_USE_CPU_REG_Y;
|
||||
if (dins.ChangesCarry())
|
||||
uflags |= NCIF_USE_CPU_REG_C;
|
||||
tains.Push(dins);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,13 +133,14 @@ static const uint32 NCIF_ALIASING = 0x00000800;
|
|||
static const uint32 NCIF_USE_CPU_REG_A = 0x00001000;
|
||||
static const uint32 NCIF_USE_CPU_REG_X = 0x00002000;
|
||||
static const uint32 NCIF_USE_CPU_REG_Y = 0x00004000;
|
||||
static const uint32 NCIF_USE_CPU_REG_C = 0x00008000;
|
||||
|
||||
// use a 32bit zero page register indexed by X for JSR
|
||||
static const uint32 NCIF_USE_ZP_32_X = 0x00008000;
|
||||
static const uint32 NICF_USE_ZP_ADDR = 0x00010000;
|
||||
static const uint32 NICF_USE_WORKREGS = 0x00020000;
|
||||
static const uint32 NCIF_USE_ZP_32_X = 0x00010000;
|
||||
static const uint32 NICF_USE_ZP_ADDR = 0x00020000;
|
||||
static const uint32 NICF_USE_WORKREGS = 0x00040000;
|
||||
|
||||
static const uint32 NCIF_BREAKPOINT = 0x00040000;
|
||||
static const uint32 NCIF_BREAKPOINT = 0x00080000;
|
||||
|
||||
class NativeCodeInstruction
|
||||
{
|
||||
|
|
|
@ -6866,11 +6866,18 @@ Expression* Parser::ParseSimpleExpression(bool lhs, bool tid)
|
|||
}
|
||||
break;
|
||||
case TK_ASM:
|
||||
{
|
||||
|
||||
mScanner->NextToken();
|
||||
|
||||
bool vol = ConsumeTokenIf(TK_VOLATILE);
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
exp = ParseAssembler();
|
||||
if (vol)
|
||||
exp->mDecValue->mFlags |= DTF_VOLATILE;
|
||||
|
||||
exp->mDecType = TheSignedLongTypeDeclaration;
|
||||
if (mScanner->mToken == TK_CLOSE_BRACE)
|
||||
mScanner->NextToken();
|
||||
|
@ -6882,7 +6889,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs, bool tid)
|
|||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "'{' expected");
|
||||
exp = new Expression(mScanner->mLocation, EX_VOID);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Term starts with invalid token", TokenNames[mScanner->mToken]);
|
||||
mScanner->NextToken();
|
||||
|
@ -9885,6 +9892,8 @@ Expression* Parser::ParseStatement(void)
|
|||
{
|
||||
mScanner->NextToken();
|
||||
ParsePragma();
|
||||
if (mScanner->mToken == TK_CLOSE_BRACE)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
|
@ -9901,21 +9910,24 @@ Expression* Parser::ParseStatement(void)
|
|||
do
|
||||
{
|
||||
Expression* nexp = ParseStatement();
|
||||
if (exp)
|
||||
if (nexp)
|
||||
{
|
||||
if (!pexp)
|
||||
if (exp)
|
||||
{
|
||||
pexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
pexp->mLeft = exp;
|
||||
exp = pexp;
|
||||
if (!pexp)
|
||||
{
|
||||
pexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
pexp->mLeft = exp;
|
||||
exp = pexp;
|
||||
}
|
||||
|
||||
pexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
pexp = pexp->mRight;
|
||||
pexp->mLeft = nexp;
|
||||
}
|
||||
|
||||
pexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||
pexp = pexp->mRight;
|
||||
pexp->mLeft = nexp;
|
||||
else
|
||||
exp = nexp;
|
||||
}
|
||||
else
|
||||
exp = nexp;
|
||||
|
||||
} while (mScanner->mToken != TK_CLOSE_BRACE && mScanner->mToken != TK_EOF);
|
||||
|
||||
|
@ -10488,11 +10500,16 @@ Expression* Parser::ParseStatement(void)
|
|||
mScanner->NextToken();
|
||||
break;
|
||||
case TK_ASM:
|
||||
{
|
||||
mScanner->NextToken();
|
||||
bool vol = ConsumeTokenIf(TK_VOLATILE);
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
exp = ParseAssembler();
|
||||
if (vol)
|
||||
exp->mDecValue->mFlags |= DTF_VOLATILE;
|
||||
|
||||
if (mScanner->mToken == TK_CLOSE_BRACE)
|
||||
mScanner->NextToken();
|
||||
else
|
||||
|
@ -10503,7 +10520,7 @@ Expression* Parser::ParseStatement(void)
|
|||
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "'{' expected");
|
||||
exp = new Expression(mScanner->mLocation, EX_VOID);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case TK_ASSUME:
|
||||
mScanner->NextToken();
|
||||
exp = new Expression(mScanner->mLocation, EX_ASSUME);
|
||||
|
@ -12241,6 +12258,9 @@ Expression* Parser::ParseAssembler(Declaration* vdasm)
|
|||
else
|
||||
dasm = vdasm->mBase;
|
||||
|
||||
if (!(mCompilerOptions & COPT_OPTIMIZE_ASSEMBLER))
|
||||
vdasm->mFlags |= DTF_VOLATILE;
|
||||
|
||||
DeclarationScope* scope = dasm->mScope;
|
||||
mScope = scope;
|
||||
|
||||
|
@ -13482,7 +13502,7 @@ void Parser::ParsePragma(void)
|
|||
else if (ConsumeIdentIf("pop"))
|
||||
{
|
||||
if (mCompilerOptionSP > 0)
|
||||
mCompilerOptions = mCompilerOptionStack[--mCompilerOptionSP] = mCompilerOptions;
|
||||
mCompilerOptions = mCompilerOptionStack[--mCompilerOptionSP];
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, ERRR_STACK_OVERFLOW, "Stack underflow");
|
||||
}
|
||||
|
@ -13688,6 +13708,9 @@ void Parser::Parse(void)
|
|||
mScope->Insert(ident, vdasm);
|
||||
}
|
||||
|
||||
if (ConsumeTokenIf(TK_VOLATILE))
|
||||
vdasm->mFlags |= DTF_VOLATILE;
|
||||
|
||||
if (mScanner->mToken == TK_OPEN_BRACE)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
|
|
Loading…
Reference in New Issue