Fix broken left shift optimization due to branch in basic block
This commit is contained in:
parent
75ea2ee439
commit
18ab7ce079
|
@ -1,6 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#pragma region( main, 0x0a00, 0xd000, , , {code, data, bss, heap, stack} )
|
||||||
|
|
||||||
unsigned shl1b(int n)
|
unsigned shl1b(int n)
|
||||||
{
|
{
|
||||||
return 1 << n;
|
return 1 << n;
|
||||||
|
@ -306,6 +308,8 @@ void shr32n(unsigned long xu, long xi)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
*(volatile char *)0x01 = 0x36;
|
||||||
|
|
||||||
for(int i=0; i<32; i++)
|
for(int i=0; i<32; i++)
|
||||||
{
|
{
|
||||||
printf("1: %.4x : %.4x | %.4x : %.4x\n", shl1b(i), shl1n(i), shr1b(i), shr1n(i));
|
printf("1: %.4x : %.4x | %.4x : %.4x\n", shl1b(i), shl1n(i), shr1b(i), shr1n(i));
|
||||||
|
@ -327,7 +331,6 @@ int main(void)
|
||||||
assert(shr8b(i) == shr8n(i));
|
assert(shr8b(i) == shr8n(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shl8xb(0x00, 0x00);
|
shl8xb(0x00, 0x00);
|
||||||
shl8xb(0xff, 0xff);
|
shl8xb(0xff, 0xff);
|
||||||
shl8xb(0x34, 0x34);
|
shl8xb(0x34, 0x34);
|
||||||
|
|
|
@ -183,11 +183,16 @@ float sqrt(float f)
|
||||||
{
|
{
|
||||||
if (f >= 0)
|
if (f >= 0)
|
||||||
{
|
{
|
||||||
float fx = f;
|
union {
|
||||||
int ex = (((int*)&fx)[1] >> 7) - 0x7f;
|
float f;
|
||||||
|
int i[2];
|
||||||
|
} x;
|
||||||
|
|
||||||
|
x.f = f;
|
||||||
|
int ex = (x.i[1] >> 7) - 0x7f;
|
||||||
ex /= 2;
|
ex /= 2;
|
||||||
((int*)&fx)[1] = (ex + 0x7f) << 7;
|
x.i[1] = (ex + 0x7f) << 7;
|
||||||
float fq = fx;
|
float fq = x.f;
|
||||||
fq = 0.5 * (fq + f / fq);
|
fq = 0.5 * (fq + f / fq);
|
||||||
fq = 0.5 * (fq + f / fq);
|
fq = 0.5 * (fq + f / fq);
|
||||||
fq = 0.5 * (fq + f / fq);
|
fq = 0.5 * (fq + f / fq);
|
||||||
|
|
|
@ -5680,8 +5680,8 @@ void ByteCodeBasicBlock::InitialOffset(int& total, int& linear)
|
||||||
total++;
|
total++;
|
||||||
linear = 0;
|
linear = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
linear += mLinear;
|
linear += mLinear;
|
||||||
|
|
||||||
mOffset = total;
|
mOffset = total;
|
||||||
total += mCode.Size();
|
total += mCode.Size();
|
||||||
|
|
|
@ -640,7 +640,7 @@ int Emulator::Emulate(int startIP)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((trace & 1) && ip == 0x0851)
|
if ((trace & 1) && ip == 0x0855)
|
||||||
{
|
{
|
||||||
int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1];
|
int accu = mMemory[BC_REG_ACCU] + 256 * mMemory[BC_REG_ACCU + 1];
|
||||||
int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1];
|
int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1];
|
||||||
|
|
|
@ -90,24 +90,100 @@ void ValueSet::FlushFrameAliases(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueSet::FlushCallAliases(void)
|
|
||||||
|
static bool MemPtrRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset)
|
||||||
|
{
|
||||||
|
while (ins && ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_INDIRECT)
|
||||||
|
ins = tvalue[ins->mSrc[1].mTemp];
|
||||||
|
|
||||||
|
if (ins)
|
||||||
|
{
|
||||||
|
if (ins->mCode == IC_CONSTANT)
|
||||||
|
{
|
||||||
|
mem = ins->mConst.mMemory;
|
||||||
|
vindex = ins->mConst.mVarIndex;
|
||||||
|
offset = ins->mConst.mIntConst;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (ins->mCode == IC_LEA)
|
||||||
|
{
|
||||||
|
mem = ins->mSrc[1].mMemory;
|
||||||
|
vindex = ins->mSrc[1].mVarIndex;
|
||||||
|
offset = ins->mSrc[1].mIntConst;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool MemRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset, int& size)
|
||||||
|
{
|
||||||
|
if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT)
|
||||||
|
{
|
||||||
|
size = ins->mSrc[0].mOperandSize;
|
||||||
|
return MemPtrRange(tvalue[ins->mSrc[0].mTemp], tvalue, mem, vindex, offset);
|
||||||
|
}
|
||||||
|
else if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
||||||
|
{
|
||||||
|
size = ins->mSrc[1].mOperandSize;
|
||||||
|
return MemPtrRange(tvalue[ins->mSrc[1].mTemp], tvalue, mem, vindex, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins)
|
||||||
|
{
|
||||||
|
if (ins->mCode == IC_LOAD)
|
||||||
|
{
|
||||||
|
mem = ins->mSrc[0].mMemory;
|
||||||
|
vindex = ins->mSrc[0].mVarIndex;
|
||||||
|
offset = ins->mSrc[0].mIntConst;
|
||||||
|
size = ins->mSrc[0].mOperandSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mem = ins->mSrc[1].mMemory;
|
||||||
|
vindex = ins->mSrc[1].mVarIndex;
|
||||||
|
offset = ins->mSrc[1].mIntConst;
|
||||||
|
size = ins->mSrc[1].mOperandSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueSet::FlushCallAliases(const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = 0;
|
InterMemory mem;
|
||||||
|
int vindex;
|
||||||
|
int offset;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
while (i < mNum)
|
while (i < mNum)
|
||||||
{
|
{
|
||||||
if ((mInstructions[i]->mCode == IC_LOAD && mInstructions[i]->mSrc[0].mMemory != IM_PARAM && mInstructions[i]->mSrc[0].mMemory != IM_LOCAL) ||
|
if (mInstructions[i]->mCode == IC_LOAD || mInstructions[i]->mCode == IC_STORE)
|
||||||
(mInstructions[i]->mCode == IC_STORE && mInstructions[i]->mSrc[1].mMemory != IM_PARAM && mInstructions[i]->mSrc[1].mMemory != IM_LOCAL))
|
|
||||||
{
|
{
|
||||||
//
|
if (MemRange(mInstructions[i], tvalue, mem, vindex, offset, size) &&
|
||||||
// potential alias load
|
((mem == IM_PARAM && !aliasedParams[vindex]) ||
|
||||||
//
|
(mem == IM_LOCAL && !aliasedLocals[vindex])))
|
||||||
mNum--;
|
i++;
|
||||||
if (i < mNum)
|
else
|
||||||
{
|
{
|
||||||
mInstructions[i] = mInstructions[mNum];
|
//
|
||||||
|
// potential alias load
|
||||||
|
//
|
||||||
|
mNum--;
|
||||||
|
if (i < mNum)
|
||||||
|
{
|
||||||
|
mInstructions[i] = mInstructions[mNum];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -373,71 +449,6 @@ void ValueSet::InsertValue(InterInstruction * ins)
|
||||||
mInstructions[mNum++] = ins;
|
mInstructions[mNum++] = ins;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MemPtrRange(const InterInstruction* ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset)
|
|
||||||
{
|
|
||||||
while (ins && ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
||||||
ins = tvalue[ins->mSrc[1].mTemp];
|
|
||||||
|
|
||||||
if (ins)
|
|
||||||
{
|
|
||||||
if (ins->mCode == IC_CONSTANT)
|
|
||||||
{
|
|
||||||
mem = ins->mConst.mMemory;
|
|
||||||
vindex = ins->mConst.mVarIndex;
|
|
||||||
offset = ins->mConst.mIntConst;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (ins->mCode == IC_LEA)
|
|
||||||
{
|
|
||||||
mem = ins->mSrc[1].mMemory;
|
|
||||||
vindex = ins->mSrc[1].mVarIndex;
|
|
||||||
offset = ins->mSrc[1].mIntConst;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool MemRange(const InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, InterMemory& mem, int& vindex, int& offset, int& size)
|
|
||||||
{
|
|
||||||
if (ins->mCode == IC_LOAD && ins->mSrc[0].mMemory == IM_INDIRECT)
|
|
||||||
{
|
|
||||||
size = ins->mSrc[0].mOperandSize;
|
|
||||||
return MemPtrRange(tvalue[ins->mSrc[0].mTemp], tvalue, mem, vindex, offset);
|
|
||||||
}
|
|
||||||
else if (ins->mSrc[1].mMemory == IM_INDIRECT)
|
|
||||||
{
|
|
||||||
size = ins->mSrc[1].mOperandSize;
|
|
||||||
return MemPtrRange(tvalue[ins->mSrc[1].mTemp], tvalue, mem, vindex, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ins)
|
|
||||||
{
|
|
||||||
if (ins->mCode == IC_LOAD)
|
|
||||||
{
|
|
||||||
mem = ins->mSrc[0].mMemory;
|
|
||||||
vindex = ins->mSrc[0].mVarIndex;
|
|
||||||
offset = ins->mSrc[0].mIntConst;
|
|
||||||
size = ins->mSrc[0].mOperandSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mem = ins->mSrc[1].mMemory;
|
|
||||||
vindex = ins->mSrc[1].mVarIndex;
|
|
||||||
offset = ins->mSrc[1].mIntConst;
|
|
||||||
size = ins->mSrc[1].mOperandSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool StoreAliasing(const InterInstruction * lins, const InterInstruction* sins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, const GrowingVariableArray& staticVars)
|
static bool StoreAliasing(const InterInstruction * lins, const InterInstruction* sins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, const GrowingVariableArray& staticVars)
|
||||||
{
|
{
|
||||||
InterMemory lmem, smem;
|
InterMemory lmem, smem;
|
||||||
|
@ -1463,7 +1474,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
|
||||||
break;
|
break;
|
||||||
case IC_CALL:
|
case IC_CALL:
|
||||||
case IC_CALL_NATIVE:
|
case IC_CALL_NATIVE:
|
||||||
FlushCallAliases();
|
FlushCallAliases(tvalue, aliasedLocals, aliasedParams);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ public:
|
||||||
ValueSet& operator=(const ValueSet& values);
|
ValueSet& operator=(const ValueSet& values);
|
||||||
|
|
||||||
void FlushAll(void);
|
void FlushAll(void);
|
||||||
void FlushCallAliases(void);
|
void FlushCallAliases(const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams);
|
||||||
void FlushFrameAliases(void);
|
void FlushFrameAliases(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5698,6 +5698,9 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
|
||||||
|
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
@ -5720,14 +5723,15 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
||||||
}
|
}
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2));
|
this->Close(lblock, eblock, ASMIT_BNE);
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2)));
|
lblock->Close(lblock, eblock, ASMIT_BNE);
|
||||||
|
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||||
|
return eblock;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case IA_SHR:
|
case IA_SHR:
|
||||||
|
|
Loading…
Reference in New Issue