diff --git a/include/c128/mmu.h b/include/c128/mmu.h index 6718129..1dcf262 100644 --- a/include/c128/mmu.h +++ b/include/c128/mmu.h @@ -27,6 +27,7 @@ struct XMMU #define xmmu (*((struct XMMU *)0xd500)) +inline char mmu_set(char cr); #pragma compile("mmu.c") diff --git a/include/crt.c b/include/crt.c index 2f0e1e2..0c206d7 100644 --- a/include/crt.c +++ b/include/crt.c @@ -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: diff --git a/include/limits.h b/include/limits.h index 7796fd1..673b529 100644 --- a/include/limits.h +++ b/include/limits.h @@ -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 diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 5cf79f2..63d5eb5 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -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 (mLeft->mDecValue->mBase->mSize <= 2 && mRight->mDecValue->mBase->mSize <= 2) - dec->mBase = ival < 32768 ? TheSignedIntTypeDeclaration : TheUnsignedIntTypeDeclaration; + 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 - dec->mBase = ival < 2147483648 ? TheSignedLongTypeDeclaration : TheUnsignedLongTypeDeclaration; + { + 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; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d9075f8..8f2346b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1666,22 +1666,23 @@ 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 = ToTypedUnsigned(op1.mIntConst, op1.mType) / ToTypedUnsigned(op2.mIntConst, op1.mType); + dop.mIntConst = op1.mIntConst / op2.mIntConst; break; case IA_DIVS: dop.mType = op1.mType; 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; @@ -7361,7 +7394,15 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void) case IA_CMPEQ: if (cins->mSrc[0].mType == IT_INT8 && cins->mSrc[1].mType == IT_INT8 && (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)) + 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; @@ -7369,7 +7410,15 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void) case IA_CMPNE: if (cins->mSrc[0].mType == IT_INT8 && cins->mSrc[1].mType == IT_INT8 && (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)) + 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; @@ -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: @@ -9166,16 +9217,19 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray { if (s0 < 0) { - mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); - - if (mInstructions[sz - 2]->mSrc[0].mIntConst > 0 && mInstructions[sz - 2]->mSrc[0].mIntConst < SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType)) - mTrueValueRange[s1].LimitMin(0); - else - mTrueValueRange[s1].LimitMinWeak(0); - - if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0) + if (mInstructions[sz - 2]->mSrc[0].mIntConst > 0) { - mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); + mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); + + if (mInstructions[sz - 2]->mSrc[0].mIntConst > 0 && mInstructions[sz - 2]->mSrc[0].mIntConst < SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType)) + mTrueValueRange[s1].LimitMin(0); + else + mTrueValueRange[s1].LimitMinWeak(0); + + if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0) + { + mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); + } } } else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) @@ -9216,9 +9270,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray mTrueValueRange[s1].LimitMin(1); if (s0 < 0) { - mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); - mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); - mFalseValueRange[s1].LimitMin(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; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index e47af06..ca0e076 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -127,6 +127,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* srins->mSrc[0] = crsins->mDst; 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) { @@ -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); - exitBlock->Append(ins); + 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) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 68fb9b4..fc1c75e 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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 diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 1cf1166..6199ea7 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -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) {