Added bitfields

This commit is contained in:
drmortalwombat 2023-09-11 08:04:09 +02:00
parent 3374544ced
commit c1ecf1c281
17 changed files with 1083 additions and 68 deletions

View File

@ -1,5 +1,8 @@
rem @echo off rem @echo off
@call :test bitfields.cpp
@if %errorlevel% neq 0 goto :error
@call :test opp_string.cpp @call :test opp_string.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

248
autotest/bitfields.cpp Normal file
View File

@ -0,0 +1,248 @@
#include <assert.h>
struct A
{
char x : 4;
char y : 1;
char z : 3;
};
A a = {7, 1, 2};
void test_char_fit(void)
{
assert(a.x == 7);
assert(a.y == 1);
assert(a.z == 2);
assert(sizeof(A) == 1);
for(int i=0; i<16; i++)
{
a.x = i;
a.y = 0;
a.z = 3;
assert(a.x == i);
assert(a.y == 0);
assert(a.z == 3);
}
}
struct B
{
char x : 6;
char y : 6;
char z : 6;
char w : 6;
};
B b = {11, 22, 33, 44};
void test_char_cross(void)
{
assert(b.x == 11);
assert(b.y == 22);
assert(b.z == 33);
assert(b.w == 44);
assert(sizeof(B) == 3);
for(int i=0; i<64; i++)
{
b.x = i * 1;
b.y = i * 3;
b.z = i * 5;
b.w = i * 7;
assert(b.x == ((i * 1) & 0x3f));
assert(b.y == ((i * 3) & 0x3f));
assert(b.z == ((i * 5) & 0x3f));
assert(b.w == ((i * 7) & 0x3f));
}
}
struct C
{
unsigned x : 4;
unsigned y : 1;
unsigned z : 3;
};
C c = {7, 1, 2};
void test_word_fit(void)
{
assert(c.x == 7);
assert(c.y == 1);
assert(c.z == 2);
assert(sizeof(C) == 1);
for(int i=0; i<16; i++)
{
c.x = i;
c.y = 0;
c.z = 3;
assert(c.x == i);
assert(c.y == 0);
assert(c.z == 3);
}
}
struct D
{
unsigned x : 10;
unsigned y : 10;
unsigned z : 10;
unsigned w : 10;
};
D d = {111, 222, 333, 444};
void test_word_cross(void)
{
assert(d.x == 111);
assert(d.y == 222);
assert(d.z == 333);
assert(d.w == 444);
assert(sizeof(D) == 5);
for(int i=0; i<1024; i++)
{
d.x = i * 1;
d.y = i * 3;
d.z = i * 5;
d.w = i * 7;
assert(d.x == ((i * 1) & 0x3ff));
assert(d.y == ((i * 3) & 0x3ff));
assert(d.z == ((i * 5) & 0x3ff));
assert(d.w == ((i * 7) & 0x3ff));
}
}
struct E
{
unsigned long x : 4;
unsigned long y : 1;
unsigned long z : 3;
};
E e = {7, 1, 2};
void test_dword_fit(void)
{
assert(e.x == 7);
assert(e.y == 1);
assert(e.z == 2);
assert(sizeof(E) == 1);
for(int i=0; i<16; i++)
{
e.x = i;
e.y = 0;
e.z = 3;
assert(e.x == i);
assert(e.y == 0);
assert(e.z == 3);
}
}
struct F
{
unsigned long x : 20;
unsigned long y : 20;
unsigned long z : 20;
unsigned long w : 20;
};
F f = {111111UL, 222222UL, 333333UL, 444444UL};
void test_dword_cross(void)
{
assert(f.x == 111111UL);
assert(f.y == 222222UL);
assert(f.z == 333333UL);
assert(f.w == 444444UL);
assert(sizeof(F) == 10);
for(int i=0; i<1024; i++)
{
f.x = i * 11UL;
f.y = i * 33UL;
f.z = i * 55UL;
f.w = i * 77UL;
assert(f.x == ((i * 11UL) & 0xfffffUL));
assert(f.y == ((i * 33UL) & 0xfffffUL));
assert(f.z == ((i * 55UL) & 0xfffffUL));
assert(f.w == ((i * 77UL) & 0xfffffUL));
}
}
struct G
{
signed char x : 1;
signed char y : 5;
signed char z : 2;
};
G g = {0, -1, -2};
void test_char_signed(void)
{
assert(g.x == 0);
assert(g.y == -1);
assert(g.z == -2);
assert(sizeof(G) == 1);
for(int i=-16; i<16; i++)
{
g.x = -1;
g.y = i;
g.z = 1;
assert(g.x == -1);
assert(g.y == i);
assert(g.z == 1);
}
}
struct H
{
int x : 10;
int y : 10;
int z : 10;
int w : 10;
};
H h = {111, -222, -333, 444};
void test_word_signed(void)
{
assert(h.x == 111);
assert(h.y == -222);
assert(h.z == -333);
assert(h.w == 444);
assert(sizeof(H) == 5);
for(int i=-32; i<32; i++)
{
h.x = i * 1;
h.y = i * 3;
h.z = i * 5;
h.w = i * 7;
assert(h.x == i * 1);
assert(h.y == i * 3);
assert(h.z == i * 5);
assert(h.w == i * 7);
}
}
int main(void)
{
test_char_fit();
test_char_cross();
test_word_fit();
test_word_cross();
test_dword_fit();
test_dword_cross();
test_char_signed();
test_word_signed();
return 0;
}

View File

@ -4246,8 +4246,8 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
case IA_SAR: case IA_SAR:
{ {
ByteCode rbc = ByteCodeBinRegOperator(ins); ByteCode rbc = ByteCodeBinRegOperator(ins);
ByteCode ibc = ByteCodeBinImmOperator(ins); ByteCode ibc = ByteCodeBinImmOperator(ins);
if (ins->mSrc[1].mTemp < 0) if (ins->mSrc[1].mTemp < 0)
{ {
IntConstToAccu(ins->mSrc[1].mIntConst); IntConstToAccu(ins->mSrc[1].mIntConst);
@ -4259,18 +4259,25 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
} }
else if (ins->mSrc[0].mTemp < 0) else if (ins->mSrc[0].mTemp < 0)
{ {
ByteCodeInstruction lins(BC_LOAD_REG_16); ByteCodeInstruction lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
lins.mRegisterFinal = ins->mSrc[1].mFinal; lins.mRegisterFinal = ins->mSrc[1].mFinal;
mIns.Push(lins); mIns.Push(lins);
if (ins->mOperator == IA_SAR && InterTypeSize[ins->mSrc[1].mType] == 1)
{
ByteCodeInstruction xins(BC_CONV_I8_I16);
xins.mRegister = BC_REG_ACCU;
mIns.Push(xins);
}
ByteCodeInstruction bins(ibc); ByteCodeInstruction bins(ibc);
bins.mValue = int(ins->mSrc[0].mIntConst); bins.mValue = int(ins->mSrc[0].mIntConst);
mIns.Push(bins); mIns.Push(bins);
} }
else else
{ {
ByteCodeInstruction lins(BC_LOAD_REG_16); ByteCodeInstruction lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);; lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);;
mIns.Push(lins); mIns.Push(lins);

View File

@ -1236,7 +1236,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
return true; return true;
} }
int Compiler::ExecuteCode(bool profile, bool trace) int Compiler::ExecuteCode(bool profile, int trace)
{ {
Location loc; Location loc;
@ -1249,12 +1249,12 @@ int Compiler::ExecuteCode(bool profile, bool trace)
memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart); memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart);
emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff; emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff;
emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8; emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8;
ecode = emu->Emulate(2061, trace ? 2 : 0); ecode = emu->Emulate(2061, trace);
} }
else if (mCompilerOptions & COPT_TARGET_CRT) else if (mCompilerOptions & COPT_TARGET_CRT)
{ {
memcpy(emu->mMemory + 0x8000, mLinker->mMemory + 0x0800, 0x4000); memcpy(emu->mMemory + 0x8000, mLinker->mMemory + 0x0800, 0x4000);
ecode = emu->Emulate(0x8009, trace ? 2 : 0); ecode = emu->Emulate(0x8009, trace);
} }
printf("Emulation result %d\n", ecode); printf("Emulation result %d\n", ecode);

View File

@ -44,7 +44,7 @@ public:
bool ParseSource(void); bool ParseSource(void);
bool GenerateCode(void); bool GenerateCode(void);
bool WriteOutputFile(const char* targetPath, DiskImage * d64); bool WriteOutputFile(const char* targetPath, DiskImage * d64);
int ExecuteCode(bool profile, bool trace); int ExecuteCode(bool profile, int trace);
void AddDefine(const Ident* ident, const char* value); void AddDefine(const Ident* ident, const char* value);

View File

@ -819,6 +819,8 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
dec->mBase = mLeft->mDecValue; dec->mBase = mLeft->mDecValue;
dec->mOffset = mDecValue->mOffset; dec->mOffset = mDecValue->mOffset;
dec->mSize = mDecValue->mSize; dec->mSize = mDecValue->mSize;
dec->mBits = mDecValue->mBits;
dec->mShift = mDecValue->mShift;
ex->mDecValue = dec; ex->mDecValue = dec;
ex->mDecType = mDecType; ex->mDecType = mDecType;
return ex; return ex;
@ -831,6 +833,8 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
dec->mBase = mLeft->mDecValue->mBase; dec->mBase = mLeft->mDecValue->mBase;
dec->mOffset = mLeft->mDecValue->mOffset + mDecValue->mOffset; dec->mOffset = mLeft->mDecValue->mOffset + mDecValue->mOffset;
dec->mSize = mDecValue->mSize; dec->mSize = mDecValue->mSize;
dec->mBits = mDecValue->mBits;
dec->mShift = mDecValue->mShift;
ex->mDecValue = dec; ex->mDecValue = dec;
ex->mDecType = mDecType; ex->mDecType = mDecType;
return ex; return ex;
@ -887,7 +891,8 @@ Declaration::Declaration(const Location& loc, DecType type)
mVTable(nullptr), mTemplate(nullptr), mVTable(nullptr), mTemplate(nullptr),
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr),
mShift(0), mBits(0)
{} {}
Declaration::~Declaration(void) Declaration::~Declaration(void)

View File

@ -29,9 +29,6 @@ enum DecType
DT_TYPE_ASSEMBLER, DT_TYPE_ASSEMBLER,
DT_TYPE_AUTO, DT_TYPE_AUTO,
DT_TYPE_CONST,
DT_TYPE_VOLATILE,
DT_CONST_INTEGER, DT_CONST_INTEGER,
DT_CONST_FLOAT, DT_CONST_FLOAT,
DT_CONST_FUNCTION, DT_CONST_FUNCTION,
@ -264,6 +261,7 @@ public:
Expression* mValue; Expression* mValue;
DeclarationScope* mScope; DeclarationScope* mScope;
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe;
uint8 mShift, mBits;
int64 mInteger, mMinValue, mMaxValue; int64 mInteger, mMinValue, mMaxValue;
double mNumber; double mNumber;
uint64 mFlags, mCompilerOptions; uint64 mFlags, mCompilerOptions;

View File

@ -649,7 +649,7 @@ int Emulator::Emulate(int startIP, int trace)
break; break;
} }
if ((trace & 1) && ip == 0x0855) if ((trace & 1) && ip == 0x0862)
{ {
unsigned accu = mMemory[BC_REG_ACCU] + (mMemory[BC_REG_ACCU + 1] << 8) + (mMemory[BC_REG_ACCU + 2] << 16) + (mMemory[BC_REG_ACCU + 3] << 24); unsigned accu = mMemory[BC_REG_ACCU] + (mMemory[BC_REG_ACCU + 1] << 8) + (mMemory[BC_REG_ACCU + 2] << 16) + (mMemory[BC_REG_ACCU + 3] << 24);
int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1]; int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1];

View File

@ -83,6 +83,7 @@ enum ErrorID
EERR_NON_STATIC_MEMBER, EERR_NON_STATIC_MEMBER,
EERR_TEMPLATE_PARAMS, EERR_TEMPLATE_PARAMS,
EERR_FUNCTION_TEMPLATE, EERR_FUNCTION_TEMPLATE,
EERR_INVALID_BITFIELD,
EERR_INVALID_CONSTEXPR, EERR_INVALID_CONSTEXPR,
EERR_DOUBLE_FREE, EERR_DOUBLE_FREE,

View File

@ -643,6 +643,16 @@ static bool SameMem(const InterOperand& op, const InterInstruction* ins)
return false; return false;
} }
static bool SameMemAndSize(const InterOperand& op, const InterInstruction* ins)
{
if (ins->mCode == IC_LOAD)
return SameMemAndSize(op, ins->mSrc[0]);
else if (ins->mCode == IC_STORE)
return SameMemAndSize(op, ins->mSrc[1]);
else
return false;
}
static bool SameInstruction(const InterInstruction* ins1, const InterInstruction* ins2) static bool SameInstruction(const InterInstruction* ins1, const InterInstruction* ins2)
{ {
if (ins1->mCode == ins2->mCode && ins1->mNumOperands == ins2->mNumOperands) if (ins1->mCode == ins2->mCode && ins1->mNumOperands == ins2->mNumOperands)
@ -7252,11 +7262,36 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
case IA_SHL: case IA_SHL:
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0) if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0)
{ {
if (vr.mMinState == IntegerValueRange::S_BOUND) if (ins->mDst.mType == IT_INT16)
ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst); {
if (vr.mMaxState == IntegerValueRange::S_BOUND) if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x4000 &&
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst); vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x4000)
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange); {
ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst);
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
}
else if (ins->mDst.mType == IT_INT8)
{
if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x40 &&
vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x40)
{
ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst);
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
}
else if (ins->mDst.mType == IT_INT32)
{
if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x40000000 &&
vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x40000000)
{
ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst);
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst);
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
}
}
} }
break; break;
case IA_SUB: case IA_SUB:
@ -8559,6 +8594,72 @@ bool InterCodeBasicBlock::RemoveUnusedStoreInstructions(const GrowingVariableArr
} }
bool InterCodeBasicBlock::RemoveUnusedIndirectStoreInstructions(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
ExpandingArray<InterInstructionPtr> stores;
for (int i = mInstructions.Size() - 1; i >= 0; i--)
{
InterInstruction* ins = mInstructions[i];
if (ins->mCode == IC_STORE)
{
int j = 0;
while (j < stores.Size() && !SameMemAndSize(ins->mSrc[1], stores[j]->mSrc[1]))
j++;
if (j < stores.Size())
{
if (ins->mVolatile)
stores[j] = ins;
else
{
ins->mCode = IC_NONE;
ins->mNumOperands = 0;
}
}
else
{
j = 0;
while (j < stores.Size())
{
if (CollidingMem(ins, stores[j]))
stores.Remove(j);
else
j++;
}
stores.Push(ins);
}
}
else
{
int j = 0;
while (j < stores.Size())
{
if (CollidingMem(ins, stores[j]) || ins->mDst.mTemp >= 0 && ins->mDst.mTemp == stores[j]->mSrc[1].mTemp)
stores.Remove(j);
else
j++;
}
}
}
if (mTrueJump && mTrueJump->RemoveUnusedIndirectStoreInstructions())
changed = true;
if (mFalseJump && mFalseJump->RemoveUnusedIndirectStoreInstructions())
changed = true;
}
return changed;
}
bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue) bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue)
{ {
bool changed = false; bool changed = false;
@ -9867,7 +9968,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
if (ins->mCode == IC_LOAD) if (ins->mCode == IC_LOAD)
{ {
j = 0; j = 0;
while (j < tvalue.Size() && !SameMem(ins->mSrc[0], tvalue[j])) while (j < tvalue.Size() && !SameMemAndSize(ins->mSrc[0], tvalue[j]))
j++; j++;
if (j < tvalue.Size()) if (j < tvalue.Size())
{ {
@ -9880,7 +9981,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
else if (ins->mCode == IC_STORE) else if (ins->mCode == IC_STORE)
{ {
j = 0; j = 0;
while (j < tvalue.Size() && !SameMem(ins->mSrc[1], tvalue[j])) while (j < tvalue.Size() && !SameMemAndSize(ins->mSrc[1], tvalue[j]))
j++; j++;
if (j < tvalue.Size()) if (j < tvalue.Size())
{ {
@ -9945,7 +10046,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
if (!ins->mVolatile) if (!ins->mVolatile)
{ {
int j = 0; int j = 0;
while (j < mLoadStoreInstructions.Size() && !SameMem(ins->mSrc[0], mLoadStoreInstructions[j])) while (j < mLoadStoreInstructions.Size() && !SameMemAndSize(ins->mSrc[0], mLoadStoreInstructions[j]))
j++; j++;
if (j < mLoadStoreInstructions.Size()) if (j < mLoadStoreInstructions.Size())
{ {
@ -9986,7 +10087,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray&
{ {
int j = 0, k = 0; int j = 0, k = 0;
while (j < mLoadStoreInstructions.Size() && !SameMem(ins->mSrc[1], mLoadStoreInstructions[j])) while (j < mLoadStoreInstructions.Size() && !SameMemAndSize(ins->mSrc[1], mLoadStoreInstructions[j]))
j++; j++;
if (!ins->mVolatile && j < mLoadStoreInstructions.Size() && mLoadStoreInstructions[j]->mCode == IC_LOAD && ins->mSrc[0].mTemp == mLoadStoreInstructions[j]->mDst.mTemp) if (!ins->mVolatile && j < mLoadStoreInstructions.Size() && mLoadStoreInstructions[j]->mCode == IC_LOAD && ins->mSrc[0].mTemp == mLoadStoreInstructions[j]->mDst.mTemp)
@ -14541,7 +14642,6 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
int64 mshift = mInstructions[i + 1]->mSrc[0].mIntConst; int64 mshift = mInstructions[i + 1]->mSrc[0].mIntConst;
mInstructions[i + 0]->mOperator = IA_AND; mInstructions[i + 0]->mOperator = IA_AND;
mInstructions[i + 0]->mSrc[0].mType = IT_INT16;
mInstructions[i + 0]->mSrc[0].mType = mInstructions[i + 1]->mSrc[0].mType; mInstructions[i + 0]->mSrc[0].mType = mInstructions[i + 1]->mSrc[0].mType;
switch (mInstructions[i + 0]->mSrc[1].mType) switch (mInstructions[i + 0]->mSrc[1].mType)
@ -14584,6 +14684,61 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
} }
} }
#endif #endif
#if 1
else if (
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHL && mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_SHR && mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal)
{
int64 shift = mInstructions[i + 0]->mSrc[0].mIntConst;
if (shift & 7)
{
int64 mshift = mInstructions[i + 1]->mSrc[0].mIntConst;
mInstructions[i + 0]->mOperator = IA_AND;
mInstructions[i + 0]->mSrc[0].mType = mInstructions[i + 1]->mSrc[0].mType;
switch (mInstructions[i + 0]->mSrc[1].mType)
{
case IT_INT8:
mInstructions[i + 0]->mSrc[0].mIntConst = 0xffu >> shift;
break;
case IT_INT16:
mInstructions[i + 0]->mSrc[0].mIntConst = 0xffffu >> shift;
break;
case IT_INT32:
mInstructions[i + 0]->mSrc[0].mIntConst = 0xffffffffu >> shift;
break;
}
if (shift > mshift && mInstructions[i + 0]->mDst.mType > mInstructions[i + 1]->mSrc[1].mType)
{
mInstructions[i + 1]->mSrc[1].mType = mInstructions[i + 0]->mDst.mType;
mInstructions[i + 1]->mDst.mType = mInstructions[i + 0]->mDst.mType;
}
if (shift > mshift)
{
mInstructions[i + 1]->mOperator = IA_SHL;
mInstructions[i + 1]->mSrc[0].mIntConst = shift - mshift;
}
else if (shift < mshift)
{
mInstructions[i + 1]->mOperator = IA_SHR;
mInstructions[i + 1]->mSrc[0].mIntConst = mshift - shift;
}
else
{
mInstructions[i + 0]->mDst = mInstructions[i + 1]->mDst;
mInstructions[i + 1]->mCode = IC_NONE;
mInstructions[i + 1]->mNumOperands = 0;
}
changed = true;
}
}
#endif
#if 1 #if 1
else if ( else if (
mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY && mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY &&
@ -16507,6 +16662,11 @@ void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory)
DisassembleDebug("removed unused static stores"); DisassembleDebug("removed unused static stores");
} }
// Remove unused indirect stores
ResetVisited();
mEntryBlock->RemoveUnusedIndirectStoreInstructions();
} }
} }
@ -16921,7 +17081,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "main"); CheckFunc = !strcmp(mIdent->mString, "test");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -428,6 +428,7 @@ public:
void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars, const GrowingVariableArray& params, NumberSet fromProvidedParams, InterMemory paramMemory); void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars, const GrowingVariableArray& params, NumberSet fromProvidedParams, InterMemory paramMemory);
bool BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars, const GrowingVariableArray& params, NumberSet& fromRequiredParams, InterMemory paramMemory); bool BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars, const GrowingVariableArray& params, NumberSet& fromRequiredParams, InterMemory paramMemory);
bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory);
bool RemoveUnusedIndirectStoreInstructions(void);
void BuildStaticVariableSet(const GrowingVariableArray& staticVars); void BuildStaticVariableSet(const GrowingVariableArray& staticVars);
void BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars); void BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars);

View File

@ -68,16 +68,220 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure*
ins->mDst.mRange.LimitMin(v.mType->mMinValue); ins->mDst.mRange.LimitMin(v.mType->mMinValue);
ins->mDst.mRange.LimitMax(v.mType->mMaxValue); ins->mDst.mRange.LimitMax(v.mType->mMaxValue);
} }
if (v.mType->mFlags & DTF_VOLATILE) if (v.mType->mFlags & DTF_VOLATILE)
ins->mVolatile = true; ins->mVolatile = true;
block->Append(ins); block->Append(ins);
v = ExValue(v.mType, ins->mDst.mTemp, v.mReference - 1); if (v.mReference == 1 && v.mBits)
{
if (v.mBits + v.mShift <= 8)
ins->mDst.mType = IT_INT8;
else if (v.mBits + v.mShift <= 16)
ins->mDst.mType = IT_INT16;
else
ins->mDst.mType = IT_INT32;
ins->mSrc[0].mOperandSize = InterTypeSize[ins->mDst.mType];
int nbits = ins->mSrc[0].mOperandSize * 8;
InterInstruction* clsins = new InterInstruction(exp->mLocation, IC_CONSTANT);
clsins->mDst.mType = IT_INT8;
clsins->mDst.mTemp = proc->AddTemporary(clsins->mDst.mType);
clsins->mConst.mType = IT_INT8;
clsins->mConst.mIntConst = nbits - v.mShift - v.mBits;
clsins->mNumOperands = 0;
block->Append(clsins);
InterInstruction* crsins = new InterInstruction(exp->mLocation, IC_CONSTANT);
crsins->mDst.mType = IT_INT8;
crsins->mDst.mTemp = proc->AddTemporary(crsins->mDst.mType);
crsins->mConst.mType = IT_INT8;
crsins->mConst.mIntConst = nbits - v.mBits;
crsins->mNumOperands = 0;
block->Append(crsins);
InterInstruction* slins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
slins->mOperator = IA_SHL;
slins->mDst.mType = ins->mDst.mType;
slins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType);
slins->mSrc[1] = ins->mDst;
slins->mSrc[0] = clsins->mDst;
slins->mNumOperands = 2;
block->Append(slins);
InterInstruction* srins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
srins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_SAR : IA_SHR;
srins->mDst.mType = ins->mDst.mType;
srins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType);
srins->mSrc[1] = slins->mDst;
srins->mSrc[0] = crsins->mDst;
srins->mNumOperands = 2;
block->Append(srins);
if (InterTypeSize[ins->mDst.mType] < v.mType->mSize)
{
InterInstruction* crins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR);
crins->mDst.mType = InterTypeOf(v.mType);
crins->mDst.mTemp = proc->AddTemporary(crins->mDst.mType);
crins->mSrc[0] = srins->mDst;
crins->mNumOperands = 1;
if (ins->mDst.mType == IT_INT16)
crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT16TO32S : IA_EXT16TO32U;
else if (v.mType->mSize == 2)
crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT8TO16S : IA_EXT8TO16U;
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);
}
else
v = ExValue(v.mType, srins->mDst.mTemp, v.mReference - 1);
}
else
v = ExValue(v.mType, ins->mDst.mTemp, v.mReference - 1, v.mBits, v.mShift);
} }
return v; return v;
} }
void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr)
{
// Bitfield assignment
if (vl.mBits)
{
InterType itype;
if (vl.mBits + vl.mShift <= 8)
itype = IT_INT8;
else if (vl.mBits + vl.mShift <= 16)
itype = IT_INT16;
else
itype = IT_INT32;
int nbits = InterTypeSize[itype] * 8;
InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD);
lins->mDst.mType = itype;
lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType);
lins->mSrc[0].mMemory = IM_INDIRECT;
lins->mSrc[0].mType = IT_POINTER;
lins->mSrc[0].mTemp = vl.mTemp;
lins->mSrc[0].mOperandSize = InterTypeSize[itype];
lins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
lins->mNumOperands = 1;
block->Append(lins);
InterInstruction* csins = new InterInstruction(exp->mLocation, IC_CONSTANT);
csins->mDst.mType = IT_INT8;
csins->mDst.mTemp = proc->AddTemporary(csins->mDst.mType);
csins->mConst.mType = IT_INT8;
csins->mConst.mIntConst = vl.mShift;
csins->mNumOperands = 0;
block->Append(csins);
InterInstruction* cmsins = new InterInstruction(exp->mLocation, IC_CONSTANT);
cmsins->mDst.mType = itype;
cmsins->mDst.mTemp = proc->AddTemporary(cmsins->mDst.mType);
cmsins->mConst.mType = itype;
cmsins->mConst.mIntConst = ((1 << vl.mBits) - 1) << vl.mShift;
cmsins->mNumOperands = 0;
block->Append(cmsins);
InterInstruction* cmlins = new InterInstruction(exp->mLocation, IC_CONSTANT);
cmlins->mDst.mType = itype;
cmlins->mDst.mTemp = proc->AddTemporary(cmlins->mDst.mType);
cmlins->mConst.mType = itype;
cmlins->mConst.mIntConst = ~cmsins->mConst.mIntConst;
cmlins->mNumOperands = 0;
block->Append(cmlins);
int rtemp = vr.mTemp;
if (InterTypeSize[itype] > vr.mType->mSize)
{
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR);
if (InterTypeSize[itype] == 2)
cins->mOperator = IA_EXT8TO16U;
else if (vr.mType->mSize == 1)
cins->mOperator = IA_EXT8TO32U;
else
cins->mOperator = IA_EXT8TO16U;
cins->mDst.mType = itype;
cins->mDst.mTemp = proc->AddTemporary(itype);
cins->mSrc[0].mTemp = rtemp;
cins->mSrc[0].mType = InterTypeOf(vr.mType);
block->Append(cins);
rtemp = cins->mDst.mTemp;
}
InterInstruction* sins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
sins->mOperator = IA_SHL;
sins->mDst.mType = itype;
sins->mDst.mTemp = proc->AddTemporary(sins->mDst.mType);
sins->mSrc[1].mTemp = rtemp;
sins->mSrc[1].mType = itype;
sins->mSrc[0] = csins->mDst;
sins->mNumOperands = 2;
block->Append(sins);
InterInstruction* msins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
msins->mOperator = IA_AND;
msins->mDst.mType = itype;
msins->mDst.mTemp = proc->AddTemporary(msins->mDst.mType);
msins->mSrc[0] = sins->mDst;
msins->mSrc[1] = cmsins->mDst;
msins->mNumOperands = 2;
block->Append(msins);
InterInstruction* mlins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
mlins->mOperator = IA_AND;
mlins->mDst.mType = itype;
mlins->mDst.mTemp = proc->AddTemporary(mlins->mDst.mType);
mlins->mSrc[0] = lins->mDst;
mlins->mSrc[1] = cmlins->mDst;
mlins->mNumOperands = 2;
block->Append(mlins);
InterInstruction* oins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
oins->mOperator = IA_OR;
oins->mDst.mType = itype;
oins->mDst.mTemp = proc->AddTemporary(oins->mDst.mType);
oins->mSrc[0] = msins->mDst;
oins->mSrc[1] = mlins->mDst;
oins->mNumOperands = 2;
block->Append(oins);
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE);
ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mSrc[0] = oins->mDst;
ins->mSrc[1].mType = IT_POINTER;
ins->mSrc[1].mTemp = vl.mTemp;
ins->mSrc[1].mOperandSize = InterTypeSize[itype];
ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
ins->mNumOperands = 2;
block->Append(ins);
}
else
{
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE);
ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mSrc[0].mType = InterTypeOf(vr.mType);
ins->mSrc[0].mTemp = vr.mTemp;
ins->mSrc[1].mType = IT_POINTER;
ins->mSrc[1].mTemp = vl.mTemp;
ins->mSrc[1].mOperandSize = vl.mType->mSize;
ins->mSrc[1].mStride = vl.mType->mStripe;
ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
ins->mNumOperands = 2;
block->Append(ins);
}
}
InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration* type, bool checkTrunc) InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration* type, bool checkTrunc)
{ {
int stemp = v.mTemp; int stemp = v.mTemp;
@ -1713,6 +1917,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mConst.mOperandSize = dec->mSize; ins->mConst.mOperandSize = dec->mSize;
ins->mConst.mIntConst = dec->mOffset; ins->mConst.mIntConst = dec->mOffset;
int lbits = dec->mBits, lshift = dec->mShift;
if (dec->mType == DT_VARIABLE_REF) if (dec->mType == DT_VARIABLE_REF)
dec = dec->mBase; dec = dec->mBase;
@ -1779,13 +1985,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (exp->mDecType->IsReference()) if (exp->mDecType->IsReference())
return ExValue(exp->mDecType->mBase, ins->mDst.mTemp, ref + 1); return ExValue(exp->mDecType->mBase, ins->mDst.mTemp, ref + 1);
else else
return ExValue(exp->mDecType, ins->mDst.mTemp, ref); return ExValue(exp->mDecType, ins->mDst.mTemp, ref, lbits, lshift);
} }
case EX_ASSIGNMENT: case EX_ASSIGNMENT:
case EX_INITIALIZATION: case EX_INITIALIZATION:
{ {
if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
@ -1902,8 +2108,6 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (vl.mReference != 1) if (vl.mReference != 1)
mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression");
InterInstruction * ins = new InterInstruction(exp->mLocation, IC_STORE);
if (exp->mToken != TK_ASSIGN) if (exp->mToken != TK_ASSIGN)
{ {
ExValue vll = Dereference(proc, exp, block, vl); ExValue vll = Dereference(proc, exp, block, vl);
@ -2043,17 +2247,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vr = CoerceType(proc, exp, block, vr, vl.mType); vr = CoerceType(proc, exp, block, vr, vl.mType);
} }
ins->mCode = IC_STORE; StoreValue(proc, exp, block, vl, vr);
ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mSrc[0].mType = InterTypeOf(vr.mType);
ins->mSrc[0].mTemp = vr.mTemp;
ins->mSrc[1].mType = IT_POINTER;
ins->mSrc[1].mTemp = vl.mTemp;
ins->mSrc[1].mOperandSize = vl.mType->mSize;
ins->mSrc[1].mStride = vl.mType->mStripe;
ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
ins->mNumOperands = 2;
block->Append(ins);
} }
} }
@ -2151,7 +2345,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
block->Append(ains); block->Append(ains);
return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1); return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift);
} }
case EX_BINARY: case EX_BINARY:
@ -2483,7 +2677,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (vl.mType->mFlags & DTF_CONST) if (vl.mType->mFlags & DTF_CONST)
mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value");
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR), * sins = new InterInstruction(exp->mLocation, IC_STORE); InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE);
ExValue vdl = Dereference(proc, exp, block, vl); ExValue vdl = Dereference(proc, exp, block, vl);
@ -2524,6 +2718,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
block->Append(ains); block->Append(ains);
StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp));
#if 0
sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[1].mMemory = IM_INDIRECT;
sins->mSrc[0].mType = ains->mDst.mType; sins->mSrc[0].mType = ains->mDst.mType;
sins->mSrc[0].mTemp = ains->mDst.mTemp; sins->mSrc[0].mTemp = ains->mDst.mTemp;
@ -2532,6 +2728,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sins->mSrc[1].mOperandSize = vl.mType->mSize; sins->mSrc[1].mOperandSize = vl.mType->mSize;
sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
block->Append(sins); block->Append(sins);
#endif
// Return reference to value // Return reference to value
return ExValue(vl.mType, vl.mTemp, 1); return ExValue(vl.mType, vl.mTemp, 1);
@ -2550,7 +2747,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (vl.mType->mFlags & DTF_CONST) if (vl.mType->mFlags & DTF_CONST)
mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value");
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR), * sins = new InterInstruction(exp->mLocation, IC_STORE); InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE);
ExValue vdl = Dereference(proc, exp, block, vl); ExValue vdl = Dereference(proc, exp, block, vl);
@ -2590,6 +2787,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ains->mDst.mTemp = proc->AddTemporary(ttype); ains->mDst.mTemp = proc->AddTemporary(ttype);
block->Append(ains); block->Append(ains);
StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp));
#if 0
sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[1].mMemory = IM_INDIRECT;
sins->mSrc[0].mType = ains->mDst.mType; sins->mSrc[0].mType = ains->mDst.mType;
sins->mSrc[0].mTemp = ains->mDst.mTemp; sins->mSrc[0].mTemp = ains->mDst.mTemp;
@ -2598,7 +2797,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sins->mSrc[1].mOperandSize = vl.mType->mSize; sins->mSrc[1].mOperandSize = vl.mType->mSize;
sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE;
block->Append(sins); block->Append(sins);
#endif
return ExValue(vdl.mType, vdl.mTemp); return ExValue(vdl.mType, vdl.mTemp);
} }
break; break;
@ -2642,7 +2841,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1); return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1);
case TK_BINARY_AND: case TK_BINARY_AND:
{ {
if (vl.mReference < 1) if (vl.mReference < 1 || vl.mBits)
mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable value"); mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable value");
Declaration* dec = new Declaration(exp->mLocation, DT_TYPE_POINTER); Declaration* dec = new Declaration(exp->mLocation, DT_TYPE_POINTER);
@ -4582,10 +4781,38 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int
else if (data->mType == DT_CONST_INTEGER) else if (data->mType == DT_CONST_INTEGER)
{ {
int64 t = data->mInteger; int64 t = data->mInteger;
for (int i = 0; i < data->mBase->mSize; i++) if (data->mBits)
{ {
dp[offset + i * data->mBase->mStripe] = uint8(t & 0xff); if (data->mBits + data->mShift <= 8)
t >>= 8; {
uint8 mask = uint8(((1 << data->mBits) - 1) << data->mShift);
dp[offset] = (dp[offset] & ~mask) | (uint8(t << data->mShift) & mask);
}
else if (data->mBits + data->mShift <= 16)
{
uint16 mask = uint16(((1 << data->mBits) - 1) << data->mShift);
dp[offset + 0] = (dp[offset + 0] & ~(mask & 0xff)) | (uint8(t << data->mShift) & (mask & 0xff));
dp[offset + 1] = (dp[offset + 1] & ~(mask >> 8)) | (uint8(t >> (8 - data->mShift)) & (mask >> 8));
}
else
{
uint32 mask = uint32(((1 << data->mBits) - 1) << data->mShift);
t = (t << data->mShift) & mask;
dp[offset + 0] = (dp[offset + 0] & ~(mask & 0xff)) | (uint8(t ));
dp[offset + 1] = (dp[offset + 1] & ~(mask >> 8)) | (uint8(t >> 8));
dp[offset + 2] = (dp[offset + 2] & ~(mask >> 16)) | (uint8(t >> 16));
dp[offset + 3] = (dp[offset + 3] & ~(mask >> 24)) | (uint8(t >> 24));
}
}
else
{
for (int i = 0; i < data->mBase->mSize; i++)
{
dp[offset + i * data->mBase->mStripe] = uint8(t & 0xff);
t >>= 8;
}
} }
} }
else if (data->mType == DT_CONST_ADDRESS) else if (data->mType == DT_CONST_ADDRESS)

View File

@ -21,9 +21,10 @@ public:
{ {
Declaration* mType; Declaration* mType;
int mTemp, mReference; int mTemp, mReference;
int mBits, mShift;
ExValue(Declaration* type = nullptr, int temp = -1, int reference = 0) ExValue(Declaration* type = nullptr, int temp = -1, int reference = 0, int bits = 0, int shift = 0)
: mType(type), mTemp(temp), mReference(reference) : mType(type), mTemp(temp), mReference(reference), mBits(bits), mShift(shift)
{} {}
}; };
@ -86,6 +87,7 @@ protected:
void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper);
ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp);
void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving);
void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr);
void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper);
void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable);

View File

@ -9788,7 +9788,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
int shift = ins->mSrc[0].mIntConst & 15; int shift = ins->mSrc[0].mIntConst & 15;
if (ins->mDst.IsUByte()) if (ins->mDst.IsUByte() || InterTypeSize[ins->mDst.mType] == 1)
{ {
if (shift == 0) if (shift == 0)
{ {
@ -9834,8 +9834,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg));
} }
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
} }
else else
{ {
@ -10045,7 +10048,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
{ {
int shift = ins->mSrc[0].mIntConst & 15; int shift = ins->mSrc[0].mIntConst & 15;
#if 1 #if 1
if (ins->mSrc[1].IsUByte()) if (ins->mSrc[1].IsUByte() || InterTypeSize[ins->mSrc[1].mType] == 1)
{ {
if (shift == 0) if (shift == 0)
{ {
@ -10053,8 +10056,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
} }
} }
else if (shift == 7) else if (shift == 7)
@ -10062,7 +10068,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
} }
@ -10074,14 +10081,18 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 3)); mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 3));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
} }
else if (shift >= 8) else if (shift >= 8)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
} }
else else
{ {
@ -10089,8 +10100,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
for (int i = 0; i < shift; i++) for (int i = 0; i < shift; i++)
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); if (InterTypeSize[ins->mDst.mType] > 1)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
} }
} }
else else
@ -10377,6 +10391,33 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
} }
} }
else if (InterTypeSize[ins->mDst.mType] == 1)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
if (shift > 5)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED));
for (int i = shift; i < 8; i++)
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 0xff >> shift));
mIns.Push(NativeCodeInstruction(ins, ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift));
mIns.Push(NativeCodeInstruction(ins, ASMIT_SEC, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift));
}
else if (shift > 0)
{
for (int i = 0; i < shift; i++)
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift));
mIns.Push(NativeCodeInstruction(ins, ASMIT_SEC, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift));
}
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
}
else if (ins->mSrc[1].IsSByte() && shift != 0 && shift < 5) else if (ins->mSrc[1].IsSByte() && shift != 0 && shift < 5)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
@ -18939,6 +18980,148 @@ bool NativeCodeBasicBlock::ShortcutPointerAddForward(void)
return changed; return changed;
} }
bool NativeCodeBasicBlock::MoveIndirectLoadZeroStoreDown(int at)
{
int yval = mIns[at].mAddress;
for (int i = at + 3; i < mIns.Size(); i++)
{
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[at + 2].mAddress)
{
if (mIns[i].mLive & LIVE_CPU_REG_Y)
return false;
mIns.Insert(i, mIns[at]);
mIns.Insert(i + 1, mIns[at + 1]);
mIns[i + 2].mType = ASMIT_STA;
mIns[i].mLive |= mIns[i + 2].mLive;
mIns[i + 1].mLive |= mIns[i + 2].mLive;
mIns.Remove(at + 1, 2);
return true;
}
if (mIns[i].ChangesZeroPage(mIns[at + 1].mAddress) || mIns[i].ChangesZeroPage(mIns[at + 1].mAddress + 1) || mIns[i].ReferencesZeroPage(mIns[at + 2].mAddress))
return false;
if (mIns[i].mType == ASMIT_JSR)
return false;
if (mIns[i].ChangesAddress())
{
if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == mIns[at + 1].mAddress)
{
if (yval == -1 || yval == mIns[at].mAddress)
return false;
}
else if (mIns[at + 1].MayBeChangedOnAddress(mIns[i]))
return false;
}
if (mIns[i].ChangesYReg())
{
if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE)
yval = mIns[i].mAddress;
else if (mIns[i].mType == ASMIT_INY && yval >= 0)
yval = (yval + 1) & 255;
else if (mIns[i].mType == ASMIT_DEY && yval >= 0)
yval = (yval - 1) & 255;
else
yval = -1;
}
}
return false;
}
bool NativeCodeBasicBlock::MoveLoadZeroStoreIndirectUp(int at)
{
int i = at - 1;
while (i >= 0 && !(mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[at].mAddress))
i--;
if (i >= 0 && mIns[i].mType == ASMIT_STA && !(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_Y)))
{
int yval = -1;
for (int j = i + 1; j < at; j++)
{
if (mIns[j].mType == ASMIT_JSR)
return false;
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress) || mIns[j].ChangesZeroPage(mIns[at + 2].mAddress + 1))
return false;
if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress == mIns[at + 2].mAddress)
{
if (yval == -1 || yval == mIns[at].mAddress)
return false;
}
else if (mIns[j].MayBeSameAddress(mIns[at + 2]))
return false;
if (mIns[j].ChangesYReg())
{
if (mIns[j].mType == ASMIT_LDY && mIns[j].mMode == ASMIM_IMMEDIATE)
yval = mIns[j].mAddress;
else if (mIns[j].mType == ASMIT_INY && yval >= 0)
yval = (yval + 1) & 255;
else if (mIns[j].mType == ASMIT_DEY && yval >= 0)
yval = (yval - 1) & 255;
else
yval = -1;
}
}
NativeCodeInstruction i0 = mIns[at + 1], i1 = mIns[at + 2];
mIns.Remove(at + 1, 2);
mIns.Insert(i + 1, i0);
mIns.Insert(i + 2, i1);
mIns[i].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mLive |= mIns[i].mLive;
mIns[i + 2].mLive |= mIns[i].mLive;
return true;
}
return false;
}
bool NativeCodeBasicBlock::ShortcutIndirectLoadStore(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
for (int i = 0; i + 2 < mIns.Size(); i++)
{
if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) &&
mIns[i + 2].mAddress != mIns[i + 1].mAddress && mIns[i + 2].mAddress != mIns[i + 1].mAddress + 1)
{
if (MoveIndirectLoadZeroStoreDown(i))
changed = true;
}
else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
if (MoveLoadZeroStoreIndirectUp(i))
changed = true;
}
}
if (mTrueJump && mTrueJump->ShortcutIndirectLoadStore())
changed = true;
if (mFalseJump && mFalseJump->ShortcutIndirectLoadStore())
changed = true;
}
return changed;
}
#if 0 #if 0
static int NativeCodeExpressionID; static int NativeCodeExpressionID;
@ -34683,6 +34866,39 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #endif
#if 1
for (int i = 0; i + 1 < mIns.Size(); i++)
{
if (mIns[i + 0].mType == ASMIT_ASL && mIns[i + 0].mMode == ASMIM_IMPLIED &&
mIns[i + 1].mType == ASMIT_LSR && mIns[i + 1].mMode == ASMIM_IMPLIED && !(mIns[i + 1].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
{
int j = 1;
while (i >= j && i + j + 1 < mIns.Size() &&
mIns[i - j].mType == ASMIT_ASL && mIns[i - j].mMode == ASMIM_IMPLIED &&
mIns[i + 1 + j].mType == ASMIT_LSR && mIns[i + 1 + j].mMode == ASMIM_IMPLIED && !(mIns[i + 1 + j].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
j++;
mIns[i + 1 - j].mType = ASMIT_AND;
mIns[i + 1 - j].mMode = ASMIM_IMMEDIATE;
mIns[i + 1 - j].mAddress = 0xff >> j;
while (j > 1)
{
mIns[i + j].mType = ASMIT_NOP;
mIns[i + j].mMode = ASMIM_IMPLIED;
j--;
mIns[i + 1 - j].mType = ASMIT_NOP;
mIns[i + 1 - j].mMode = ASMIM_IMPLIED;
}
mIns[i + 1].mType = ASMIT_NOP;
mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
CheckLive();
#endif
#if 1 #if 1
bool progress = false; bool progress = false;
do { do {
@ -36740,6 +36956,19 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true; progress = true;
} }
#endif
#if 1
else if (
mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
mIns[i + 2].mType == ASMIT_ROL && mIns[i + 2].mMode == ASMIM_IMPLIED && !(mIns[i + 2].mLive & LIVE_CPU_REG_C))
{
mIns[i + 1].mType = ASMIT_AND; mIns[i + 1].mAddress = 1;
mIns[i + 0].mAddress &= (mIns[i + 2].mAddress << 1) | 1;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif #endif
else if ( else if (
mIns[i + 0].IsShift() && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].IsShift() && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
@ -36984,6 +37213,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns.Remove(i + 2); mIns.Remove(i + 2);
progress = true; progress = true;
} }
else if (
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_STA &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) &&
!(mIns[i + 0].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && (mIns[i + 1].mAddress == mIns[i + 0].mAddress || mIns[i + 1].mAddress + 1 == mIns[i + 0].mAddress)))
{
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
if ( if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress <= 1 && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress <= 1 &&
@ -40915,7 +41153,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{ {
mInterProc = proc; mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "test");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -41688,6 +41926,14 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
#endif #endif
if (step == 2)
{
ResetVisited();
if (mEntryBlock->ShortcutIndirectLoadStore())
changed = true;
}
#if 1 #if 1
if (step >= 3) if (step >= 3)
{ {

View File

@ -604,6 +604,10 @@ public:
bool CheckShortcutPointerAddForward(int at); bool CheckShortcutPointerAddForward(int at);
bool ShortcutPointerAddForward(void); bool ShortcutPointerAddForward(void);
bool ShortcutIndirectLoadStore(void);
bool MoveIndirectLoadZeroStoreDown(int at);
bool MoveLoadZeroStoreIndirectUp(int at);
bool CommonSubExpressionElimination(void); bool CommonSubExpressionElimination(void);
bool CheckPatchFailReg(const NativeCodeBasicBlock* block, int reg); bool CheckPatchFailReg(const NativeCodeBasicBlock* block, int reg);

View File

@ -231,6 +231,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
} }
else else
{ {
int bitsleft = 0;
Declaration* mlast = nullptr; Declaration* mlast = nullptr;
for (;;) for (;;)
{ {
@ -334,7 +336,103 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
mdec->mType = DT_ELEMENT; mdec->mType = DT_ELEMENT;
mdec->mOffset = offset; mdec->mOffset = offset;
offset += mdec->mBase->mSize; if (mdec->mBits)
{
if (mdec->mBits <= 8)
{
if (bitsleft == 0)
{
bitsleft = 8 - mdec->mBits;
offset++;
}
else if (bitsleft >= mdec->mBits)
{
mdec->mOffset--;
mdec->mShift = 8 - bitsleft;
bitsleft -= mdec->mBits;
}
else
{
mdec->mOffset--;
mdec->mShift = 8 - bitsleft;
bitsleft = 8 + bitsleft - mdec->mBits;
offset++;
}
}
else if (mdec->mBits <= 16)
{
if (bitsleft == 0)
{
bitsleft = 16 - mdec->mBits;
offset += 2;
}
else if (bitsleft + 8 >= mdec->mBits)
{
mdec->mOffset--;
mdec->mShift = 8 - bitsleft;
bitsleft = bitsleft + 8 - mdec->mBits;
offset++;
}
else
{
mdec->mOffset -= 3;
mdec->mShift = 24 - bitsleft;
bitsleft = bitsleft + 16 - mdec->mBits;
offset += 2;
}
}
else if (mdec->mBits <= 24)
{
if (bitsleft == 0)
{
bitsleft = 24 - mdec->mBits;
offset += 3;
}
else if (bitsleft + 16 >= mdec->mBits)
{
mdec->mOffset -= 2;
mdec->mShift = 16 - bitsleft;
bitsleft = bitsleft + 16 - mdec->mBits;
offset += 2;
}
else
{
mdec->mOffset -= 1;
mdec->mShift = 8 - bitsleft;
bitsleft = bitsleft + 24 - mdec->mBits;
offset += 3;
}
}
else
{
if (bitsleft == 0)
{
bitsleft = 32 - mdec->mBits;
offset += 4;
}
else if (bitsleft + 24 >= mdec->mBits)
{
mdec->mOffset--;
mdec->mShift = 8 - bitsleft;
bitsleft = bitsleft + 24 - mdec->mBits;
offset+=2;
}
else
{
bitsleft = 32 - mdec->mBits;
offset += mdec->mBase->mSize;
}
}
if (mdec->mShift == 0 && mdec->mBits == 8 * mdec->mSize)
mdec->mBits = 0;
}
else
{
bitsleft = 0;
offset += mdec->mBase->mSize;
}
if (offset > dec->mSize) if (offset > dec->mSize)
dec->mSize = offset; dec->mSize = offset;
@ -1409,6 +1507,8 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
Expression* texp = ParseInitExpression(mdec->mBase); Expression* texp = ParseInitExpression(mdec->mBase);
Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp); Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp);
cdec->mBits = mdec->mBits;
cdec->mShift = mdec->mShift;
if (last) if (last)
last->mNext = cdec; last->mNext = cdec;
@ -4043,9 +4143,19 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
ldec = ndec; ldec = ndec;
// ndec->mNext = nullptr; // ndec->mNext = nullptr;
if (mScanner->mToken == TK_ASSIGN) if (ConsumeTokenIf(TK_COLON))
{
Expression* exp = ParseRExpression();
if (!ndec->mBase->IsIntegerType())
mErrors->Error(exp->mLocation, EERR_INVALID_BITFIELD, "Invalid bitfíeld for non integer type");
else if (exp->mType == EX_CONSTANT && exp->mDecType->IsIntegerType() && exp->mDecValue->mType == DT_CONST_INTEGER)
ndec->mBits = uint8(exp->mDecValue->mInteger);
else
mErrors->Error(exp->mLocation, EERR_CONSTANT_TYPE, "Constant integer expression expected");
}
if (ConsumeTokenIf(TK_ASSIGN))
{ {
mScanner->NextToken();
ndec->mValue = ParseInitExpression(ndec->mBase); ndec->mValue = ParseInitExpression(ndec->mBase);
if (ndec->mBase->mType == DT_TYPE_AUTO) if (ndec->mBase->mType == DT_TYPE_AUTO)
{ {

View File

@ -116,7 +116,8 @@ int main2(int argc, const char** argv)
strcpy_s(crtPath, includePath); strcpy_s(crtPath, includePath);
strcat_s(crtPath, "crt.c"); strcat_s(crtPath, "crt.c");
bool emulate = false, profile = false, trace = false; bool emulate = false, profile = false;
int trace = 0;
targetPath[0] = 0; targetPath[0] = 0;
diskPath[0] = 0; diskPath[0] = 0;
@ -211,7 +212,9 @@ int main2(int argc, const char** argv)
if (arg[2] == 'p') if (arg[2] == 'p')
profile = true; profile = true;
else if (arg[2] == 't') else if (arg[2] == 't')
trace = true; trace = 2;
else if (arg[2] == 'b')
trace = 1;
} }
else if (arg[1] == 'd') else if (arg[1] == 'd')
{ {