Fix drop of Y register in asm code

This commit is contained in:
drmortalwombat 2024-09-22 13:46:29 +02:00 committed by John Schneiderman
parent b3ed9cf160
commit 71a65ce87d
8 changed files with 190 additions and 47 deletions

View File

@ -27,6 +27,7 @@ struct XMMU
#define xmmu (*((struct XMMU *)0xd500))
inline char mmu_set(char cr);
#pragma compile("mmu.c")

View File

@ -3628,11 +3628,19 @@ W1:
sec
sbc #$8e
bcc W2
bit accu + 3
bmi W5
lda #$ff
sta accu
lda #$7f
sta accu + 1
bne W3
rts
W5:
lda #$00
sta accu
lda #$80
sta accu + 1
rts
W2:
tax
L1:

View File

@ -11,7 +11,7 @@
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#define INT_MIN -32767
#define INT_MIN (-32767-1)
#define INT_MAX 32767
#define UINT_MAX 65535

View File

@ -517,6 +517,41 @@ Expression* Expression::ConstantDereference(Errors* errors, LinkerSection* dataS
return this;
}
static int64 signextend(int64 v, Declaration* type)
{
if (type->mFlags & DTF_SIGNED)
{
switch (type->mSize)
{
case 1:
if (v & 0x80)
return (v & 0xff) - 0x100;
else
return v;
case 2:
if (v & 0x8000)
return (v & 0xffff) - 0x10000;
else
return v;
default:
return v;
}
}
else
{
switch (type->mSize)
{
case 1:
return v & 0xff;
case 2:
return v & 0xffff;
default:
return v & 0xffffffff;
}
}
}
Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSection, Linker* linker)
{
if (mType == EX_PREFIX && mToken == TK_BANKOF && linker)
@ -554,11 +589,14 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
{
Expression* ex = new Expression(mLocation, EX_CONSTANT);
Declaration * dec = new Declaration(mLocation, DT_CONST_INTEGER);
if (mLeft->mDecValue->mBase->mSize <= 2)
if (mLeft->mDecValue->mBase->mSize < 2)
dec->mBase = TheSignedIntTypeDeclaration;
else
dec->mBase = TheSignedLongTypeDeclaration;
dec->mInteger = - mLeft->mDecValue->mInteger;
dec->mBase = mLeft->mDecValue->mBase;
dec->mInteger = signextend ( - mLeft->mDecValue->mInteger, dec->mBase );
ex->mDecValue = dec;
ex->mDecType = dec->mBase;
return ex;
@ -568,17 +606,12 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
Expression* ex = new Expression(mLocation, EX_CONSTANT);
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
dec->mInteger = ~mLeft->mDecValue->mInteger;
if (mLeft->mDecValue->mBase->mSize <= 2)
{
dec->mInteger &= 0xffff;
dec->mBase = TheUnsignedIntTypeDeclaration;
}
if (mLeft->mDecValue->mBase->mSize < 2)
dec->mBase = TheSignedIntTypeDeclaration;
else
{
dec->mInteger &= 0xffffffff;
dec->mBase = TheUnsignedLongTypeDeclaration;
}
dec->mBase = mLeft->mDecValue->mBase;
dec->mInteger = signextend( ~mLeft->mDecValue->mInteger, dec->mBase );
ex->mDecValue = dec;
ex->mDecType = dec->mBase;
@ -750,6 +783,11 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
{
int64 ival = 0, ileft = mLeft->mDecValue->mInteger, iright = mRight->mDecValue->mInteger;
bool signop =
(mLeft->mDecValue->mBase->mSize < 2 || (mLeft->mDecValue->mBase->mFlags & DTF_SIGNED)) &&
(mRight->mDecValue->mBase->mSize < 2 || (mRight->mDecValue->mBase->mFlags & DTF_SIGNED));
bool promote = true;
switch (mToken)
{
case TK_ADD:
@ -764,20 +802,26 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
case TK_DIV:
if (iright == 0)
errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero");
else
else if (signop)
ival = ileft / iright;
else
ival = (uint64)ileft / (uint64)iright;
break;
case TK_MOD:
if (iright == 0)
errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero");
else
else if (signop)
ival = ileft % iright;
else
ival = (uint64)ileft % (uint64)iright;
break;
case TK_LEFT_SHIFT:
ival = ileft << iright;
promote = false;
break;
case TK_RIGHT_SHIFT:
ival = ileft >> iright;
promote = false;
break;
case TK_BINARY_AND:
ival = ileft & iright;
@ -794,10 +838,21 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
Expression* ex = new Expression(mLocation, EX_CONSTANT);
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
if (promote)
{
if (mLeft->mDecValue->mBase->mSize <= 2 && mRight->mDecValue->mBase->mSize <= 2)
dec->mBase = ival < 32768 ? TheSignedIntTypeDeclaration : TheUnsignedIntTypeDeclaration;
else
dec->mBase = ival < 2147483648 ? TheSignedLongTypeDeclaration : TheUnsignedLongTypeDeclaration;
}
else
{
if (mLeft->mDecValue->mBase->mSize < 2)
dec->mBase = TheSignedIntTypeDeclaration;
else
dec->mBase = mLeft->mDecValue->mBase;
}
dec->mInteger = ival;
ex->mDecValue = dec;
ex->mDecType = dec->mBase;

View File

@ -1666,6 +1666,7 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
if (op1.mType == IT_FLOAT)
dop.mFloatConst = op1.mFloatConst / op2.mFloatConst;
else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) / ToTypedUnsigned(op2.mIntConst, op1.mType);
dop.mIntConst = op1.mIntConst / op2.mIntConst;
break;
case IA_DIVS:
@ -1673,15 +1674,15 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
if (op1.mType == IT_FLOAT)
dop.mFloatConst = op1.mFloatConst / op2.mFloatConst;
else
dop.mIntConst = op1.mIntConst / op2.mIntConst;
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) / ToTypedSigned(op2.mIntConst, op1.mType);
break;
case IA_MODU:
dop.mType = op1.mType;
dop.mIntConst = op1.mIntConst % op2.mIntConst;
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) % ToTypedUnsigned(op2.mIntConst, op1.mType);
break;
case IA_MODS:
dop.mType = op1.mType;
dop.mIntConst = op1.mIntConst % op2.mIntConst;
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) % ToTypedSigned(op2.mIntConst, op1.mType);
break;
case IA_OR:
dop.mType = op1.mType;
@ -5257,6 +5258,38 @@ bool InterInstruction::ConstantFolding(void)
return true;
}
break;
case IC_SELECT:
if (mSrc[2].mTemp < 0)
{
bool cond = mSrc[2].mIntConst != 0;
if (IsIntegerType(mSrc[2].mType))
cond = mSrc[2].mIntConst != 0;
else if (mSrc[2].mType == IT_FLOAT)
cond = mSrc[2].mFloatConst != 0;
else if (mSrc[2].mType == IT_POINTER)
{
if (mSrc[2].mMemory == IM_ABSOLUTE)
cond = mSrc[2].mIntConst != 0;
else
cond = true;
}
int ci = cond ? 1 : 0;
if (mSrc[ci].mTemp < 0)
{
mCode = IC_CONSTANT;
mConst = mSrc[ci];
}
else
{
mCode = IC_LOAD_TEMPORARY;
mSrc[0] = mSrc[ci];
}
mNumOperands = 1;
return true;
}
break;
}
return false;
@ -7363,6 +7396,14 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 256 + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 256 + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[0].mType == IT_INT16 && cins->mSrc[1].mType == IT_INT16 &&
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 65536 + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 65536 + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[0].mType == IT_INT32 && cins->mSrc[1].mType == IT_INT32 &&
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 0x100000000ll + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 0x100000000ll + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue || cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
break;
@ -7371,6 +7412,14 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 256 + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 256 + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[0].mType == IT_INT16 && cins->mSrc[1].mType == IT_INT16 &&
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 65536 + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 65536 + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[0].mType == IT_INT32 && cins->mSrc[1].mType == IT_INT32 &&
(cins->mSrc[0].mRange.mMinValue < 0 && cins->mSrc[1].mRange.mMaxValue >= 0x100000000ll + cins->mSrc[0].mRange.mMinValue ||
cins->mSrc[1].mRange.mMinValue < 0 && cins->mSrc[0].mRange.mMaxValue >= 0x100000000ll + cins->mSrc[1].mRange.mMinValue))
;
else if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue || cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
break;
@ -8557,6 +8606,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSetsForward(const GrowingVariab
vr.LimitMax(ins->mSrc[1].mRange.mMaxValue);
else
vr.mMaxState = IntegerValueRange::S_UNBOUND;
if (vr.mMaxValue < 0)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
break;
#endif
default:
@ -9165,6 +9216,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
if (s1 >= 0)
{
if (s0 < 0)
{
if (mInstructions[sz - 2]->mSrc[0].mIntConst > 0)
{
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
@ -9178,6 +9231,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
}
}
else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
{
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1);
@ -9215,12 +9269,15 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
mTrueValueRange[s1].LimitMin(1);
if (s0 < 0)
{
if (mInstructions[sz - 2]->mSrc[0].mIntConst >= 0)
{
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[s1].LimitMin(0);
}
}
}
break;
case IA_CMPGEU:
if (s0 < 0)

View File

@ -128,6 +128,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure*
srins->mNumOperands = 2;
block->Append(srins);
// Promote unsigned bitfields that fit into a signed int to signed int
Declaration* vtype = v.mType;
if (vtype->mSize == 2 && v.mBits < 16 && !(vtype->mFlags & DTF_SIGNED))
vtype = TheSignedIntTypeDeclaration;
if (InterTypeSize[ins->mDst.mType] < v.mType->mSize)
{
InterInstruction* crins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR);
@ -142,10 +147,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure*
else
crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT8TO32S : IA_EXT8TO32U;
block->Append(crins);
v = ExValue(v.mType, crins->mDst.mTemp, v.mReference - 1);
v = ExValue(vtype, crins->mDst.mTemp, v.mReference - 1);
}
else
v = ExValue(v.mType, srins->mDst.mTemp, v.mReference - 1);
v = ExValue(vtype, srins->mDst.mTemp, v.mReference - 1);
}
else
v = ExValue(v.mType, ins->mDst.mTemp, v.mReference - 1, v.mBits, v.mShift);
@ -3218,7 +3223,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (!(vl.mType->mType == DT_TYPE_POINTER || vl.mType->IsNumericType()))
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric or pointer type");
else if (vl.mType->mType == DT_TYPE_INTEGER && vl.mType->mSize < 2)
vl = CoerceType(proc, exp, block, inlineMapper, vl, TheUnsignedIntTypeDeclaration);
vl = CoerceType(proc, exp, block, inlineMapper, vl, TheSignedIntTypeDeclaration);
ins->mOperator = IA_NOT;
break;
case TK_MUL:
@ -5839,14 +5844,30 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
if (!strcmp(proc->mIdent->mString, "main"))
{
InterInstruction* zins = new InterInstruction(dec->mLocation, IC_CONSTANT);
zins->mDst.mType = IT_INT16;
zins->mDst.mTemp = proc->AddTemporary(IT_INT16);
zins->mConst.mType = IT_INT16;
zins->mConst.mIntConst = 0;
exitBlock->Append(zins);
InterInstruction* rins = new InterInstruction(dec->mLocation, IC_RETURN_VALUE);
rins->mSrc[0].mType = IT_INT16;
rins->mSrc[0].mTemp = zins->mDst.mTemp;
exitBlock->Append(rins);
mMainStartupBlock = entryBlock;
}
}
else
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString);
InterInstruction * ins = new InterInstruction(exp ? exp->mEndLocation : dec->mLocation, IC_RETURN);
if (strcmp(proc->mIdent->mString, "main"))
{
InterInstruction* ins = new InterInstruction(exp ? exp->mEndLocation : dec->mLocation, IC_RETURN);
exitBlock->Append(ins);
}
exitBlock->Close(nullptr, nullptr);
if (mErrors->mErrorCount == 0 && proc != mMainInitProc)

View File

@ -2154,7 +2154,7 @@ void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data)
{
if (data.mRegs[reg].mMode == NRDM_IMMEDIATE)
{
data.mRegs[reg].mValue = (data.mRegs[reg].mValue + 1) & 255;
data.mRegs[reg].mValue = (data.mRegs[reg].mValue - 1) & 255;
data.mRegs[CPU_REG_Z].mValue = data.mRegs[reg].mValue;
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
}
@ -16989,7 +16989,7 @@ bool NativeCodeBasicBlock::CanGlobalSwapXY(void)
return false;
if (ins.mMode == ASMIM_ABSOLUTE_X && (ins.mType != ASMIT_LDY && !HasAsmInstructionMode(ins.mType, ASMIM_ABSOLUTE_Y)))
return false;
if (ins.mType == ASMIT_JSR && (ins.mFlags & (NCIF_USE_CPU_REG_X | NCIF_USE_ZP_32_X)))
if (ins.mType == ASMIT_JSR && (ins.mFlags & (NCIF_USE_CPU_REG_X | NCIF_USE_CPU_REG_Y | NCIF_USE_ZP_32_X)))
return false;
}
@ -51643,7 +51643,6 @@ void NativeCodeProcedure::Optimize(void)
ResetVisited();
mEntryBlock->CheckAsmCode();
#endif
int t = 0;
#if 1
do

View File

@ -2354,8 +2354,10 @@ void Scanner::ParseNumberToken(void)
NextChar();
mToken = TK_INTEGERUL;
}
else
else if (mant <= 0x7fffffff)
mToken = TK_INTEGERL;
else
mToken = TK_INTEGERUL;
}
else if (mant < 65536)
{