More autoinline optimizations
This commit is contained in:
parent
5e02e48c5a
commit
11af372509
|
@ -18,6 +18,13 @@ if %errorlevel% neq 0 goto :error
|
||||||
..\release\oscar64 -e -n testint32.c
|
..\release\oscar64 -e -n testint32.c
|
||||||
if %errorlevel% neq 0 goto :error
|
if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
..\release\oscar64 -e testint16mul.c
|
||||||
|
if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
..\release\oscar64 -e -n testint16mul.c
|
||||||
|
if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
|
||||||
..\release\oscar64 -e recursiontest.c
|
..\release\oscar64 -e recursiontest.c
|
||||||
if %errorlevel% neq 0 goto :error
|
if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int mul[32][32];
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
for(int i=0; i<32; i++)
|
||||||
|
for(int j=0; j<32; j++)
|
||||||
|
mul[i][j] = i * j;
|
||||||
|
#assign xi 0
|
||||||
|
#repeat
|
||||||
|
|
||||||
|
for(int j=0; j<32; j++)
|
||||||
|
{
|
||||||
|
assert(mul[xi][j] == xi * j);
|
||||||
|
assert(mul[j][xi] == j * xi);
|
||||||
|
}
|
||||||
|
|
||||||
|
#assign xi xi + 1
|
||||||
|
#until xi == 32
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "joystick.h"
|
||||||
|
|
||||||
|
signed char joyx[2], joyy[2];
|
||||||
|
bool joyb[2];
|
||||||
|
|
||||||
|
void joy_poll(char n)
|
||||||
|
{
|
||||||
|
char b = ((char *)0xdc00)[n];
|
||||||
|
|
||||||
|
if (!(b & 1))
|
||||||
|
joyy[n] = -1;
|
||||||
|
else if (!(b & 2))
|
||||||
|
joyy[n] = 1;
|
||||||
|
else
|
||||||
|
joyy[n] = 0;
|
||||||
|
|
||||||
|
if (!(b & 4))
|
||||||
|
joyx[n] = -1;
|
||||||
|
else if (!(b & 8))
|
||||||
|
joyx[n] = 1;
|
||||||
|
else
|
||||||
|
joyx[n] = 0;
|
||||||
|
|
||||||
|
joyb[n] = (b & 0x10) == 0;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef C64_JOYSTICK_H
|
||||||
|
#define C64_JOYSTICK_H
|
||||||
|
|
||||||
|
extern signed char joyx[2], joyy[2];
|
||||||
|
extern bool joyb[2];
|
||||||
|
|
||||||
|
void joy_poll(char n);
|
||||||
|
|
||||||
|
#pragma compile("joystick.c")
|
||||||
|
|
||||||
|
#endif
|
|
@ -6,6 +6,8 @@ void StackStart, StackEnd, BSSStart, BSSEnd;
|
||||||
#pragma section(stack, 0x0000, StackStart, StackEnd)
|
#pragma section(stack, 0x0000, StackStart, StackEnd)
|
||||||
#pragma section(bss, 0x0000, BSSStart, BSSEnd)
|
#pragma section(bss, 0x0000, BSSStart, BSSEnd)
|
||||||
|
|
||||||
|
char spentry;
|
||||||
|
|
||||||
int main(void);
|
int main(void);
|
||||||
|
|
||||||
__asm startup
|
__asm startup
|
||||||
|
@ -25,6 +27,9 @@ __asm startup
|
||||||
|
|
||||||
// Clear BSS Segment
|
// Clear BSS Segment
|
||||||
|
|
||||||
|
tsx
|
||||||
|
stx spentry
|
||||||
|
|
||||||
lda #<BSSStart
|
lda #<BSSStart
|
||||||
sta ip
|
sta ip
|
||||||
lda #>BSSStart
|
lda #>BSSStart
|
||||||
|
@ -202,13 +207,18 @@ __asm divmod
|
||||||
// byte / byte
|
// byte / byte
|
||||||
BB:
|
BB:
|
||||||
lda #0
|
lda #0
|
||||||
ldx #8
|
ldx #4
|
||||||
asl accu
|
asl accu
|
||||||
LBB1: rol
|
LBB1: rol
|
||||||
cmp tmp
|
cmp tmp
|
||||||
bcc WBB1
|
bcc WBB1
|
||||||
sbc tmp
|
sbc tmp
|
||||||
WBB1: rol accu
|
WBB1: rol accu
|
||||||
|
rol
|
||||||
|
cmp tmp
|
||||||
|
bcc WBB2
|
||||||
|
sbc tmp
|
||||||
|
WBB2: rol accu
|
||||||
dex
|
dex
|
||||||
bne LBB1
|
bne LBB1
|
||||||
sta tmp + 2
|
sta tmp + 2
|
||||||
|
@ -330,26 +340,55 @@ W1: dey
|
||||||
|
|
||||||
__asm mul16
|
__asm mul16
|
||||||
{
|
{
|
||||||
lda #0
|
ldy #0
|
||||||
sta tmp + 2
|
sty tmp + 3
|
||||||
sta tmp + 3
|
|
||||||
|
|
||||||
ldx #16
|
lda tmp
|
||||||
L1: lsr tmp + 1
|
ldx tmp + 1
|
||||||
ror tmp
|
beq W1
|
||||||
bcc W1
|
|
||||||
|
sec
|
||||||
|
ror
|
||||||
|
bcc L2
|
||||||
|
L1:
|
||||||
|
tax
|
||||||
clc
|
clc
|
||||||
lda tmp + 2
|
tya
|
||||||
adc accu
|
adc accu
|
||||||
sta tmp + 2
|
tay
|
||||||
lda tmp + 3
|
lda tmp + 3
|
||||||
adc accu + 1
|
adc accu + 1
|
||||||
sta tmp + 3
|
sta tmp + 3
|
||||||
W1: asl accu
|
txa
|
||||||
|
L2:
|
||||||
|
asl accu + 0
|
||||||
rol accu + 1
|
rol accu + 1
|
||||||
dex
|
lsr
|
||||||
|
bcc L2
|
||||||
bne L1
|
bne L1
|
||||||
rts
|
|
||||||
|
lda tmp + 1
|
||||||
|
W1:
|
||||||
|
lsr
|
||||||
|
bcc L4
|
||||||
|
L3:
|
||||||
|
tax
|
||||||
|
clc
|
||||||
|
tya
|
||||||
|
adc accu
|
||||||
|
tay
|
||||||
|
lda tmp + 3
|
||||||
|
adc accu + 1
|
||||||
|
sta tmp + 3
|
||||||
|
txa
|
||||||
|
L4:
|
||||||
|
asl accu + 0
|
||||||
|
rol accu + 1
|
||||||
|
lsr
|
||||||
|
bcs L3
|
||||||
|
bne L4
|
||||||
|
|
||||||
|
sty tmp + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm mul32
|
__asm mul32
|
||||||
|
@ -1010,6 +1049,25 @@ __asm inp_lea_abs
|
||||||
|
|
||||||
#pragma bytecode(BC_LEA_ABS, inp_lea_abs)
|
#pragma bytecode(BC_LEA_ABS, inp_lea_abs)
|
||||||
|
|
||||||
|
__asm inp_lea_abs_index
|
||||||
|
{
|
||||||
|
lda (ip), y
|
||||||
|
tax
|
||||||
|
iny
|
||||||
|
clc
|
||||||
|
lda $00, x
|
||||||
|
adc (ip), y
|
||||||
|
sta addr
|
||||||
|
iny
|
||||||
|
lda $01, x
|
||||||
|
adc (ip), y
|
||||||
|
sta addr + 1
|
||||||
|
iny
|
||||||
|
jmp startup.exec
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma bytecode(BC_LEA_ABS_INDEX, inp_lea_abs_index)
|
||||||
|
|
||||||
__asm inp_load_local_16
|
__asm inp_load_local_16
|
||||||
{
|
{
|
||||||
lda (ip), y
|
lda (ip), y
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define sregs 0x43
|
#define sregs 0x43
|
||||||
#define regs 0x53
|
#define regs 0x53
|
||||||
|
|
||||||
|
extern char spentry;
|
||||||
|
|
||||||
enum ByteCode
|
enum ByteCode
|
||||||
{
|
{
|
||||||
|
@ -42,6 +43,7 @@ enum ByteCode
|
||||||
BC_STORE_ABS_32,
|
BC_STORE_ABS_32,
|
||||||
|
|
||||||
BC_LEA_ABS,
|
BC_LEA_ABS,
|
||||||
|
BC_LEA_ABS_INDEX,
|
||||||
|
|
||||||
BC_LOAD_LOCAL_8,
|
BC_LOAD_LOCAL_8,
|
||||||
BC_LOAD_LOCAL_16,
|
BC_LOAD_LOCAL_16,
|
||||||
|
|
|
@ -92,7 +92,7 @@ struct sinfo
|
||||||
bool sign, left, prefix;
|
bool sign, left, prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
int nformi(const sinfo * si, char * str, int v, bool s)
|
inline int nformi(const sinfo * si, char * str, int v, bool s)
|
||||||
{
|
{
|
||||||
char * sp = str;
|
char * sp = str;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
#include "crt.h"
|
||||||
|
|
||||||
void itoa(int n, char * s, unsigned radix)
|
void itoa(int n, char * s, unsigned radix)
|
||||||
{
|
{
|
||||||
|
@ -312,8 +313,12 @@ void exit(int status)
|
||||||
sta accu + 0
|
sta accu + 0
|
||||||
lda status + 1
|
lda status + 1
|
||||||
sta accu + 1
|
sta accu + 1
|
||||||
pla
|
ldx spentry
|
||||||
pla
|
txs
|
||||||
|
lda #$4c
|
||||||
|
sta $54
|
||||||
|
lda #0
|
||||||
|
sta $13
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,10 @@ char * strcpy(char * dst, const char * src)
|
||||||
|
|
||||||
ldy #0
|
ldy #0
|
||||||
L1: lda (src), y
|
L1: lda (src), y
|
||||||
|
sta (dst), y
|
||||||
|
beq W1
|
||||||
|
iny
|
||||||
|
lda (src), y
|
||||||
sta (dst), y
|
sta (dst), y
|
||||||
beq W1
|
beq W1
|
||||||
iny
|
iny
|
||||||
|
@ -21,7 +25,6 @@ char * strcpy(char * dst, const char * src)
|
||||||
inc dst + 1
|
inc dst + 1
|
||||||
bne L1
|
bne L1
|
||||||
W1:
|
W1:
|
||||||
rts
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,17 +60,18 @@ int strcmp(const char * ptr1, const char * ptr2)
|
||||||
W2: bcs gt
|
W2: bcs gt
|
||||||
lda #$ff
|
lda #$ff
|
||||||
sta accu
|
sta accu
|
||||||
sta accu + 1
|
bmi E
|
||||||
rts
|
|
||||||
gt: lda #$01
|
gt: lda #$01
|
||||||
sta accu
|
sta accu
|
||||||
lda #$00
|
lda #$00
|
||||||
sta accu + 1
|
beq E
|
||||||
rts
|
|
||||||
W1: cmp (ptr2), y
|
W1: cmp (ptr2), y
|
||||||
bne W2
|
bne W2
|
||||||
lda #$00
|
lda #$00
|
||||||
sta accu
|
sta accu
|
||||||
|
E:
|
||||||
sta accu + 1
|
sta accu + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef STRING_H
|
#ifndef STRING_H
|
||||||
#define STRING_H
|
#define STRING_H
|
||||||
|
|
||||||
__fastcall char * strcpy(char * dst, const char * src);
|
char * strcpy(char * dst, const char * src);
|
||||||
|
|
||||||
__fastcall int strcmp(const char * ptr1, const char * ptr2);
|
int strcmp(const char * ptr1, const char * ptr2);
|
||||||
|
|
||||||
int strlen(const char * str);
|
int strlen(const char * str);
|
||||||
|
|
||||||
|
|
|
@ -267,4 +267,12 @@ public:
|
||||||
{
|
{
|
||||||
Grow(size, true);
|
Grow(size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IndexOf(const T& t)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
if (array[i] == t)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -206,6 +206,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const
|
||||||
return true;
|
return true;
|
||||||
if (mCode == BC_JSR || mCode == BC_CALL)
|
if (mCode == BC_JSR || mCode == BC_CALL)
|
||||||
return true;
|
return true;
|
||||||
|
if (mCode == BC_LEA_ABS_INDEX)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -293,6 +295,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BC_LEA_ABS:
|
case BC_LEA_ABS:
|
||||||
|
case BC_LEA_ABS_INDEX:
|
||||||
block->PutCode(generator, mCode); block->PutByte(mRegister);
|
block->PutCode(generator, mCode); block->PutByte(mRegister);
|
||||||
if (mRelocate)
|
if (mRelocate)
|
||||||
{
|
{
|
||||||
|
@ -3261,6 +3264,23 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
|
if (i + 3 < mIns.Size())
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
mIns[i + 0].mCode == BC_LEA_ABS && mIns[i + 0].mRegister == BC_REG_ACCU &&
|
||||||
|
mIns[i + 1].mCode == BC_BINOP_ADDR_16 &&
|
||||||
|
mIns[i + 2].mCode == BC_ADDR_REG && mIns[i + 2].mRegister == BC_REG_ACCU &&
|
||||||
|
mIns[i + 3].ChangesAccu())
|
||||||
|
{
|
||||||
|
mIns[i + 0].mCode = BC_LEA_ABS_INDEX;
|
||||||
|
mIns[i + 0].mRegister = mIns[i + 1].mRegister;
|
||||||
|
mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal;
|
||||||
|
mIns[i + 1].mCode = BC_NOP;
|
||||||
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (i + 2 < mIns.Size())
|
if (i + 2 < mIns.Size())
|
||||||
{
|
{
|
||||||
if (mIns[i].mCode == BC_LOAD_LOCAL_16 &&
|
if (mIns[i].mCode == BC_LOAD_LOCAL_16 &&
|
||||||
|
@ -3403,6 +3423,15 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
|
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mCode == BC_LOAD_REG_8 &&
|
||||||
|
mIns[i + 1].mCode == BC_STORE_REG_8 &&
|
||||||
|
mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 2].mRegister && mIns[i + 2].mRegisterFinal)
|
||||||
|
{
|
||||||
|
mIns[i + 1].mCode = BC_NOP;
|
||||||
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i + 1 < mIns.Size())
|
if (i + 1 < mIns.Size())
|
||||||
|
|
|
@ -32,6 +32,7 @@ enum ByteCode
|
||||||
BC_STORE_ABS_32,
|
BC_STORE_ABS_32,
|
||||||
|
|
||||||
BC_LEA_ABS,
|
BC_LEA_ABS,
|
||||||
|
BC_LEA_ABS_INDEX,
|
||||||
|
|
||||||
BC_LOAD_LOCAL_8,
|
BC_LOAD_LOCAL_8,
|
||||||
BC_LOAD_LOCAL_16,
|
BC_LOAD_LOCAL_16,
|
||||||
|
|
|
@ -19,6 +19,7 @@ Compiler::Compiler(void)
|
||||||
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
|
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
|
||||||
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker);
|
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker);
|
||||||
mInterCodeModule = new InterCodeModule();
|
mInterCodeModule = new InterCodeModule();
|
||||||
|
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
|
||||||
|
|
||||||
mCompilationUnits->mLinker = mLinker;
|
mCompilationUnits->mLinker = mLinker;
|
||||||
|
|
||||||
|
@ -156,6 +157,11 @@ bool Compiler::GenerateCode(void)
|
||||||
|
|
||||||
dcrtstart->mSection = sectionStartup;
|
dcrtstart->mSection = sectionStartup;
|
||||||
|
|
||||||
|
mGlobalAnalyzer->AnalyzeAssembler(dcrtstart->mValue, nullptr);
|
||||||
|
mGlobalAnalyzer->DumpCallGraph();
|
||||||
|
mGlobalAnalyzer->AutoInline();
|
||||||
|
mGlobalAnalyzer->DumpCallGraph();
|
||||||
|
|
||||||
mInterCodeGenerator->mForceNativeCode = mNativeCode;
|
mInterCodeGenerator->mForceNativeCode = mNativeCode;
|
||||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);
|
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "ByteCodeGenerator.h"
|
#include "ByteCodeGenerator.h"
|
||||||
#include "NativeCodeGenerator.h"
|
#include "NativeCodeGenerator.h"
|
||||||
#include "InterCodeGenerator.h"
|
#include "InterCodeGenerator.h"
|
||||||
|
#include "GlobalAnalyzer.h"
|
||||||
#include "Linker.h"
|
#include "Linker.h"
|
||||||
|
|
||||||
class Compiler
|
class Compiler
|
||||||
|
@ -22,6 +23,7 @@ public:
|
||||||
NativeCodeGenerator* mNativeCodeGenerator;
|
NativeCodeGenerator* mNativeCodeGenerator;
|
||||||
InterCodeGenerator* mInterCodeGenerator;
|
InterCodeGenerator* mInterCodeGenerator;
|
||||||
InterCodeModule* mInterCodeModule;
|
InterCodeModule* mInterCodeModule;
|
||||||
|
GlobalAnalyzer* mGlobalAnalyzer;
|
||||||
|
|
||||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ Expression* Expression::ConstantFold(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
Declaration::Declaration(const Location& loc, DecType type)
|
Declaration::Declaration(const Location& loc, DecType type)
|
||||||
: mLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mVarIndex(-1), mLinkerObject(nullptr)
|
: mLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Declaration::~Declaration(void)
|
Declaration::~Declaration(void)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Scanner.h"
|
#include "Scanner.h"
|
||||||
#include "MachineTypes.h"
|
#include "MachineTypes.h"
|
||||||
#include "Assembler.h"
|
#include "Assembler.h"
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
class LinkerObject;
|
class LinkerObject;
|
||||||
class LinkerSection;
|
class LinkerSection;
|
||||||
|
@ -63,6 +64,14 @@ static const uint32 DTF_SECTION_START = 0x00001000;
|
||||||
static const uint32 DTF_SECTION_END = 0x00002000;
|
static const uint32 DTF_SECTION_END = 0x00002000;
|
||||||
static const uint32 DTF_FASTCALL = 0x00004000;
|
static const uint32 DTF_FASTCALL = 0x00004000;
|
||||||
static const uint32 DTF_INLINE = 0x00008000;
|
static const uint32 DTF_INLINE = 0x00008000;
|
||||||
|
static const uint32 DTF_ANALYZED = 0x00010000;
|
||||||
|
static const uint32 DTF_REQUEST_INLINE = 0x00020000;
|
||||||
|
|
||||||
|
static const uint32 DTF_FUNC_VARIABLE = 0x00040000;
|
||||||
|
static const uint32 DTF_FUNC_ASSEMBLER = 0x00080000;
|
||||||
|
static const uint32 DTF_FUNC_RECURSIVE = 0x00100000;
|
||||||
|
static const uint32 DTF_FUNC_ANALYZING = 0x00200000;
|
||||||
|
|
||||||
|
|
||||||
class Declaration;
|
class Declaration;
|
||||||
|
|
||||||
|
@ -156,7 +165,7 @@ public:
|
||||||
Declaration* mBase, *mParams, * mNext;
|
Declaration* mBase, *mParams, * mNext;
|
||||||
Expression* mValue;
|
Expression* mValue;
|
||||||
DeclarationScope* mScope;
|
DeclarationScope* mScope;
|
||||||
int mOffset, mSize, mVarIndex, mNumVars;
|
int mOffset, mSize, mVarIndex, mNumVars, mComplexity;
|
||||||
int64 mInteger;
|
int64 mInteger;
|
||||||
double mNumber;
|
double mNumber;
|
||||||
uint32 mFlags;
|
uint32 mFlags;
|
||||||
|
@ -165,6 +174,8 @@ public:
|
||||||
const uint8 * mData;
|
const uint8 * mData;
|
||||||
LinkerObject * mLinkerObject;
|
LinkerObject * mLinkerObject;
|
||||||
|
|
||||||
|
GrowingArray<Declaration*> mCallers, mCalled;
|
||||||
|
|
||||||
bool CanAssign(const Declaration* fromType) const;
|
bool CanAssign(const Declaration* fromType) const;
|
||||||
bool IsSame(const Declaration* dec) const;
|
bool IsSame(const Declaration* dec) const;
|
||||||
bool IsSubType(const Declaration* dec) const;
|
bool IsSubType(const Declaration* dec) const;
|
||||||
|
|
|
@ -20,6 +20,11 @@ const char* ByteCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodePro
|
||||||
return "ADDR";
|
return "ADDR";
|
||||||
else if (tmp == BC_REG_ACCU)
|
else if (tmp == BC_REG_ACCU)
|
||||||
return "ACCU";
|
return "ACCU";
|
||||||
|
else if (tmp >= BC_REG_FPARAMS && tmp <= BC_REG_FPARAMS + 7)
|
||||||
|
{
|
||||||
|
sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
else if (proc && tmp >= BC_REG_TMP && tmp < BC_REG_TMP + proc->mTempSize)
|
else if (proc && tmp >= BC_REG_TMP && tmp < BC_REG_TMP + proc->mTempSize)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -152,6 +157,11 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star
|
||||||
i += 3;
|
i += 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BC_LEA_ABS_INDEX:
|
||||||
|
fprintf(file, "LEAX\tADDR, %s + %s", AddrName(uint16(memory[start + i + 1] + 256 * memory[start + i + 2]), abuffer, linker), TempName(memory[start + i + 0], tbuffer, proc));
|
||||||
|
i += 3;
|
||||||
|
break;
|
||||||
|
|
||||||
case BC_STORE_ABS_8:
|
case BC_STORE_ABS_8:
|
||||||
fprintf(file, "MOVB\t%s, %s", AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker), TempName(memory[start + i + 2], tbuffer, proc));
|
fprintf(file, "MOVB\t%s, %s", AddrName(uint16(memory[start + i + 0] + 256 * memory[start + i + 1]), abuffer, linker), TempName(memory[start + i + 2], tbuffer, proc));
|
||||||
i += 3;
|
i += 3;
|
||||||
|
@ -639,7 +649,7 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, Linker* lin
|
||||||
LinkerObject* obj = linker->FindObjectByAddr(addr);
|
LinkerObject* obj = linker->FindObjectByAddr(addr);
|
||||||
if (obj && obj->mIdent)
|
if (obj && obj->mIdent)
|
||||||
{
|
{
|
||||||
sprintf_s(buffer, 40, "%s + %d", obj->mIdent->mString, addr - obj->mAddress);
|
sprintf_s(buffer, 40, "$%04x ; (%s + %d)", addr, obj->mIdent->mString, addr - obj->mAddress);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,6 +681,11 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP
|
||||||
sprintf_s(buffer, 10, "IP + %d", tmp - BC_REG_IP);
|
sprintf_s(buffer, 10, "IP + %d", tmp - BC_REG_IP);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
else if (tmp >= BC_REG_FPARAMS && tmp <= BC_REG_FPARAMS + 7)
|
||||||
|
{
|
||||||
|
sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 3)
|
else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 3)
|
||||||
{
|
{
|
||||||
sprintf_s(buffer, 10, "FP + %d", tmp - BC_REG_LOCALS);
|
sprintf_s(buffer, 10, "FP + %d", tmp - BC_REG_LOCALS);
|
||||||
|
|
|
@ -633,7 +633,7 @@ int Emulator::Emulate(int startIP)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((trace & 1) && ip == 0x081f)
|
if ((trace & 1) && ip == 0x0850)
|
||||||
{
|
{
|
||||||
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];
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
#include "GlobalAnalyzer.h"
|
||||||
|
|
||||||
|
GlobalAnalyzer::GlobalAnalyzer(Errors* errors, Linker* linker)
|
||||||
|
: mErrors(errors), mLinker(linker), mCalledFunctions(nullptr), mCallingFunctions(nullptr), mVariableFunctions(nullptr), mFunctions(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalAnalyzer::~GlobalAnalyzer(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::DumpCallGraph(void)
|
||||||
|
{
|
||||||
|
printf("------------------------------\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < mFunctions.Size(); i++)
|
||||||
|
{
|
||||||
|
GrowingArray<Declaration*> decs(nullptr);
|
||||||
|
GrowingArray<int> calls(0);
|
||||||
|
|
||||||
|
Declaration* from = mFunctions[i];
|
||||||
|
for (int j = 0; j < from->mCalled.Size(); j++)
|
||||||
|
{
|
||||||
|
Declaration* to = from->mCalled[j];
|
||||||
|
|
||||||
|
int k = decs.IndexOf(to);
|
||||||
|
if (k == -1)
|
||||||
|
{
|
||||||
|
decs.Push(to);
|
||||||
|
calls.Push(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
calls[k]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decs.Size() > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < decs.Size(); j++)
|
||||||
|
{
|
||||||
|
printf("CALL %s[%d] -> %d -> %s[%d]\n", from->mIdent->mString, from->mComplexity, calls[j], decs[j]->mIdent->mString, decs[j]->mComplexity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("LEAF %d -> %s[%d]\n", from->mCallers.Size(), from->mIdent->mString, from->mComplexity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::AutoInline(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < mFunctions.Size(); i++)
|
||||||
|
{
|
||||||
|
Declaration* f = mFunctions[i];
|
||||||
|
if (!(f->mFlags & DTF_INLINE) && !(f->mBase->mFlags & DTF_VARIADIC) && !(f->mFlags & DTF_FUNC_VARIABLE) && !(f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_INTRINSIC) && !(f->mFlags & DTF_FUNC_RECURSIVE))
|
||||||
|
{
|
||||||
|
int nparams = 0;
|
||||||
|
Declaration* dec = f->mParams;
|
||||||
|
while (dec)
|
||||||
|
{
|
||||||
|
nparams++;
|
||||||
|
dec = dec->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cost = (f->mComplexity - 20 * nparams);
|
||||||
|
if (cost * (f->mCallers.Size() - 1) <= 0 || (f->mFlags & DTF_REQUEST_INLINE))
|
||||||
|
//if (cost * (f->mCallers.Size() - 1) <= 1000 || (f->mFlags & DTF_REQUEST_INLINE))
|
||||||
|
{
|
||||||
|
printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size());
|
||||||
|
f->mFlags |= DTF_INLINE;
|
||||||
|
for (int j = 0; j < f->mCallers.Size(); j++)
|
||||||
|
{
|
||||||
|
Declaration* cf = f->mCallers[j];
|
||||||
|
|
||||||
|
int sk = 0, dk = 0;
|
||||||
|
while (sk < cf->mCalled.Size())
|
||||||
|
{
|
||||||
|
if (cf->mCalled[sk] == f)
|
||||||
|
{
|
||||||
|
cf->mComplexity += cost;
|
||||||
|
for (int m = 0; m < f->mCalled.Size(); m++)
|
||||||
|
{
|
||||||
|
cf->mCalled.Push(f->mCalled[m]);
|
||||||
|
f->mCalled[m]->mCallers.Push(cf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cf->mCalled[dk++] = cf->mCalled[sk];
|
||||||
|
sk++;
|
||||||
|
}
|
||||||
|
cf->mCalled.SetSize(dk);
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (changed);
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < mFunctions.Size(); i++)
|
||||||
|
{
|
||||||
|
Declaration* f = mFunctions[i];
|
||||||
|
if (!(f->mFlags & DTF_INLINE) && !(f->mBase->mFlags & DTF_VARIADIC) && !(f->mFlags & DTF_FUNC_VARIABLE) && !(f->mFlags & DTF_INTRINSIC) && f->mCalled.Size() == 0)
|
||||||
|
{
|
||||||
|
int nparams = 0;
|
||||||
|
Declaration* dec = f->mParams;
|
||||||
|
while (dec)
|
||||||
|
{
|
||||||
|
nparams += dec->mSize;
|
||||||
|
dec = dec->mNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nparams <= 8)
|
||||||
|
{
|
||||||
|
f->mBase->mFlags |= DTF_FASTCALL;
|
||||||
|
printf("FASTCALL %s\n", f->mIdent->mString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
|
||||||
|
{
|
||||||
|
if (dec->mFlags & DTF_FUNC_ANALYZING)
|
||||||
|
dec->mFlags |= DTF_FUNC_RECURSIVE;
|
||||||
|
|
||||||
|
if (!(dec->mFlags & DTF_ANALYZED))
|
||||||
|
{
|
||||||
|
dec->mFlags |= DTF_FUNC_ANALYZING;
|
||||||
|
|
||||||
|
mFunctions.Push(dec);
|
||||||
|
|
||||||
|
dec->mFlags |= DTF_ANALYZED;
|
||||||
|
if (dec->mFlags & DTF_INTRINSIC)
|
||||||
|
;
|
||||||
|
else if (dec->mFlags & DTF_DEFINED)
|
||||||
|
Analyze(exp, dec);
|
||||||
|
else
|
||||||
|
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mIdent->mString);
|
||||||
|
|
||||||
|
dec->mFlags &= ~DTF_FUNC_ANALYZING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
|
||||||
|
{
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
if (procDec)
|
||||||
|
procDec->mComplexity += 2;
|
||||||
|
|
||||||
|
if (exp->mLeft)
|
||||||
|
{
|
||||||
|
Declaration* adec = exp->mLeft->mDecValue;
|
||||||
|
if (adec->mType == DT_LABEL_REF)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_VARIABLE_REF)
|
||||||
|
{
|
||||||
|
if (adec->mBase->mFlags & DTF_GLOBAL)
|
||||||
|
AnalyzeGlobalVariable(adec->mBase);
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_LABEL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_VARIABLE)
|
||||||
|
{
|
||||||
|
if (adec->mFlags & DTF_GLOBAL)
|
||||||
|
AnalyzeGlobalVariable(adec);
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_FUNCTION_REF)
|
||||||
|
{
|
||||||
|
AnalyzeProcedure(adec->mBase->mValue, adec->mBase);
|
||||||
|
RegisterProc(adec->mBase);
|
||||||
|
}
|
||||||
|
else if (adec->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
AnalyzeProcedure(adec->mValue, adec);
|
||||||
|
RegisterCall(adec, procDec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exp = exp->mRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec)
|
||||||
|
{
|
||||||
|
if (!(dec->mFlags & DTF_ANALYZED))
|
||||||
|
{
|
||||||
|
dec->mFlags |= DTF_ANALYZED;
|
||||||
|
|
||||||
|
if (dec->mValue)
|
||||||
|
{
|
||||||
|
Analyze(dec->mValue, dec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
|
||||||
|
{
|
||||||
|
Declaration* ldec, * rdec;
|
||||||
|
|
||||||
|
procDec->mComplexity += 10;
|
||||||
|
|
||||||
|
switch (exp->mType)
|
||||||
|
{
|
||||||
|
case EX_ERROR:
|
||||||
|
case EX_VOID:
|
||||||
|
break;
|
||||||
|
case EX_CONSTANT:
|
||||||
|
if (exp->mDecValue->mType == DT_CONST_FUNCTION)
|
||||||
|
AnalyzeProcedure(exp->mDecValue->mValue, exp->mDecValue);
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_STRUCT)
|
||||||
|
{
|
||||||
|
Declaration* mdec = exp->mDecValue->mParams;
|
||||||
|
while (mdec)
|
||||||
|
{
|
||||||
|
if (mdec->mValue)
|
||||||
|
RegisterProc(Analyze(mdec->mValue, mdec));
|
||||||
|
mdec = mdec->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_POINTER)
|
||||||
|
{
|
||||||
|
RegisterProc(Analyze(exp->mDecValue->mValue, procDec));
|
||||||
|
}
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_ASSEMBLER)
|
||||||
|
{
|
||||||
|
AnalyzeAssembler(exp->mDecValue->mValue, procDec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp->mDecValue;
|
||||||
|
case EX_VARIABLE:
|
||||||
|
return exp->mDecValue;
|
||||||
|
case EX_ASSIGNMENT:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
RegisterProc(rdec);
|
||||||
|
break;
|
||||||
|
case EX_BINARY:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_RELATIONAL:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
return TheBoolTypeDeclaration;
|
||||||
|
case EX_PREINCDEC:
|
||||||
|
return Analyze(exp->mLeft, procDec);
|
||||||
|
case EX_PREFIX:
|
||||||
|
break;
|
||||||
|
case EX_POSTFIX:
|
||||||
|
break;
|
||||||
|
case EX_POSTINCDEC:
|
||||||
|
return Analyze(exp->mLeft, procDec);
|
||||||
|
case EX_INDEX:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
return ldec->mBase;
|
||||||
|
case EX_QUALIFY:
|
||||||
|
Analyze(exp->mLeft, procDec);
|
||||||
|
return exp->mDecValue->mBase;
|
||||||
|
case EX_CALL:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
RegisterCall(procDec, ldec);
|
||||||
|
if (exp->mRight)
|
||||||
|
RegisterProc(Analyze(exp->mRight, procDec));
|
||||||
|
break;
|
||||||
|
case EX_LIST:
|
||||||
|
RegisterProc(Analyze(exp->mLeft, procDec));
|
||||||
|
return Analyze(exp->mRight, procDec);
|
||||||
|
case EX_RETURN:
|
||||||
|
if (exp->mLeft)
|
||||||
|
RegisterProc(Analyze(exp->mLeft, procDec));
|
||||||
|
break;
|
||||||
|
case EX_SEQUENCE:
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
exp = exp->mRight;
|
||||||
|
} while (exp);
|
||||||
|
break;
|
||||||
|
case EX_WHILE:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_IF:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight->mLeft, procDec);
|
||||||
|
if (exp->mRight->mRight)
|
||||||
|
rdec = Analyze(exp->mRight->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_ELSE:
|
||||||
|
break;
|
||||||
|
case EX_FOR:
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
ldec = Analyze(exp->mLeft->mRight, procDec);
|
||||||
|
if (exp->mLeft->mLeft->mLeft)
|
||||||
|
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
if (exp->mLeft->mLeft->mRight)
|
||||||
|
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_DO:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_BREAK:
|
||||||
|
case EX_CONTINUE:
|
||||||
|
break;
|
||||||
|
case EX_TYPE:
|
||||||
|
break;
|
||||||
|
case EX_TYPECAST:
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_AND:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_OR:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
rdec = Analyze(exp->mRight, procDec);
|
||||||
|
break;
|
||||||
|
case EX_LOGICAL_NOT:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
break;
|
||||||
|
case EX_ASSEMBLER:
|
||||||
|
procDec->mFlags |= DTF_FUNC_ASSEMBLER;
|
||||||
|
AnalyzeAssembler(exp, procDec);
|
||||||
|
break;
|
||||||
|
case EX_UNDEFINED:
|
||||||
|
break;
|
||||||
|
case EX_SWITCH:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
exp = exp->mRight;
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
rdec = Analyze(exp->mLeft->mRight, procDec);
|
||||||
|
exp = exp->mRight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EX_CASE:
|
||||||
|
break;
|
||||||
|
case EX_DEFAULT:
|
||||||
|
break;
|
||||||
|
case EX_CONDITIONAL:
|
||||||
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
RegisterProc(Analyze(exp->mRight->mLeft, procDec));
|
||||||
|
RegisterProc(Analyze(exp->mRight->mRight, procDec));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TheVoidTypeDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::RegisterCall(Declaration* from, Declaration* to)
|
||||||
|
{
|
||||||
|
if (from)
|
||||||
|
{
|
||||||
|
if (to->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
if (to->mCallers.Size() == 0)
|
||||||
|
mCalledFunctions.Push(to);
|
||||||
|
to->mCallers.Push(from);
|
||||||
|
if (from->mCalled.Size() == 0)
|
||||||
|
mCallingFunctions.Push(from);
|
||||||
|
from->mCalled.Push(to);
|
||||||
|
}
|
||||||
|
else if (to->mType == DT_TYPE_FUNCTION)
|
||||||
|
{
|
||||||
|
if (from->mCalled.Size() == 0)
|
||||||
|
mCallingFunctions.Push(from);
|
||||||
|
from->mCalled.Push(to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalAnalyzer::RegisterProc(Declaration* to)
|
||||||
|
{
|
||||||
|
if (to->mType == DT_CONST_FUNCTION)
|
||||||
|
{
|
||||||
|
to->mFlags |= DTF_FUNC_VARIABLE;
|
||||||
|
mVariableFunctions.Push(to);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Declaration.h"
|
||||||
|
#include "Linker.h"
|
||||||
|
|
||||||
|
class GlobalAnalyzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GlobalAnalyzer(Errors* errors, Linker* linker);
|
||||||
|
~GlobalAnalyzer(void);
|
||||||
|
|
||||||
|
void DumpCallGraph(void);
|
||||||
|
void AutoInline(void);
|
||||||
|
|
||||||
|
void AnalyzeProcedure(Expression* exp, Declaration* procDec);
|
||||||
|
void AnalyzeAssembler(Expression* exp, Declaration* procDec);
|
||||||
|
void AnalyzeGlobalVariable(Declaration* dec);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Errors* mErrors;
|
||||||
|
Linker* mLinker;
|
||||||
|
|
||||||
|
GrowingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions;
|
||||||
|
|
||||||
|
Declaration* Analyze(Expression* exp, Declaration* procDec);
|
||||||
|
|
||||||
|
void RegisterCall(Declaration* from, Declaration* to);
|
||||||
|
void RegisterProc(Declaration* to);
|
||||||
|
};
|
||||||
|
|
|
@ -673,6 +673,8 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
|
||||||
case IT_POINTER:
|
case IT_POINTER:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
assert(ins->mSrc[1].mType == IT_INT8 || ins->mSrc[1].mType == IT_INT16 || ins->mSrc[1].mType == IT_INT32);
|
||||||
|
|
||||||
if (ins->mSrc[1].mTemp >= 0 && tvalue[ins->mSrc[1].mTemp] && tvalue[ins->mSrc[1].mTemp]->mCode == IC_CONSTANT &&
|
if (ins->mSrc[1].mTemp >= 0 && tvalue[ins->mSrc[1].mTemp] && tvalue[ins->mSrc[1].mTemp]->mCode == IC_CONSTANT &&
|
||||||
ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
|
ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
|
||||||
{
|
{
|
||||||
|
@ -1199,10 +1201,12 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte
|
||||||
switch (mCode)
|
switch (mCode)
|
||||||
{
|
{
|
||||||
case IC_LOAD:
|
case IC_LOAD:
|
||||||
|
case IC_CALL:
|
||||||
|
case IC_CALL_NATIVE:
|
||||||
if (mSrc[0].mTemp >= 0 && ctemps[mSrc[0].mTemp])
|
if (mSrc[0].mTemp >= 0 && ctemps[mSrc[0].mTemp])
|
||||||
{
|
{
|
||||||
InterInstruction* ains = ctemps[mSrc[0].mTemp];
|
InterInstruction* ains = ctemps[mSrc[0].mTemp];
|
||||||
mSrc[0].mIntConst = ains->mConst.mIntConst;
|
mSrc[0].mIntConst += ains->mConst.mIntConst;
|
||||||
mSrc[0].mLinkerObject = ains->mConst.mLinkerObject;
|
mSrc[0].mLinkerObject = ains->mConst.mLinkerObject;
|
||||||
mSrc[0].mVarIndex = ains->mConst.mVarIndex;
|
mSrc[0].mVarIndex = ains->mConst.mVarIndex;
|
||||||
mSrc[0].mMemory = ains->mConst.mMemory;
|
mSrc[0].mMemory = ains->mConst.mMemory;
|
||||||
|
@ -1214,7 +1218,7 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte
|
||||||
if (mSrc[1].mTemp >= 0 && ctemps[mSrc[1].mTemp])
|
if (mSrc[1].mTemp >= 0 && ctemps[mSrc[1].mTemp])
|
||||||
{
|
{
|
||||||
InterInstruction* ains = ctemps[mSrc[1].mTemp];
|
InterInstruction* ains = ctemps[mSrc[1].mTemp];
|
||||||
mSrc[1].mIntConst = ains->mConst.mIntConst;
|
mSrc[1].mIntConst += ains->mConst.mIntConst;
|
||||||
mSrc[1].mLinkerObject = ains->mConst.mLinkerObject;
|
mSrc[1].mLinkerObject = ains->mConst.mLinkerObject;
|
||||||
mSrc[1].mVarIndex = ains->mConst.mVarIndex;
|
mSrc[1].mVarIndex = ains->mConst.mVarIndex;
|
||||||
mSrc[1].mMemory = ains->mConst.mMemory;
|
mSrc[1].mMemory = ains->mConst.mMemory;
|
||||||
|
@ -1732,6 +1736,11 @@ InterCodeBasicBlock::~InterCodeBasicBlock(void)
|
||||||
|
|
||||||
void InterCodeBasicBlock::Append(InterInstruction * code)
|
void InterCodeBasicBlock::Append(InterInstruction * code)
|
||||||
{
|
{
|
||||||
|
if (code->mCode == IC_BINARY_OPERATOR)
|
||||||
|
{
|
||||||
|
assert(code->mSrc[1].mType != IT_POINTER);
|
||||||
|
}
|
||||||
|
|
||||||
assert(!(code->mInUse));
|
assert(!(code->mInUse));
|
||||||
code->mInUse = true;
|
code->mInUse = true;
|
||||||
this->mInstructions.Push(code);
|
this->mInstructions.Push(code);
|
||||||
|
@ -1843,7 +1852,7 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
|
||||||
|
|
||||||
if (ains->mCode == IC_CONSTANT)
|
if (ains->mCode == IC_CONSTANT)
|
||||||
{
|
{
|
||||||
ins->mSrc[offset].mIntConst = ains->mConst.mIntConst;
|
ins->mSrc[offset].mIntConst += ains->mConst.mIntConst;
|
||||||
ins->mSrc[offset].mLinkerObject = ains->mConst.mLinkerObject;
|
ins->mSrc[offset].mLinkerObject = ains->mConst.mLinkerObject;
|
||||||
ins->mSrc[offset].mVarIndex = ains->mConst.mVarIndex;
|
ins->mSrc[offset].mVarIndex = ains->mConst.mVarIndex;
|
||||||
ins->mSrc[offset].mMemory = ains->mConst.mMemory;
|
ins->mSrc[offset].mMemory = ains->mConst.mMemory;
|
||||||
|
@ -1851,16 +1860,18 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
|
||||||
}
|
}
|
||||||
else if (ains->mCode == IC_LEA && ains->mSrc[0].mTemp < 0 && ains->mSrc[1].mTemp >= 0 && tvalue[ains->mSrc[1].mTemp])
|
else if (ains->mCode == IC_LEA && ains->mSrc[0].mTemp < 0 && ains->mSrc[1].mTemp >= 0 && tvalue[ains->mSrc[1].mTemp])
|
||||||
{
|
{
|
||||||
ins->mSrc[offset].mIntConst = ains->mSrc[0].mIntConst;
|
ins->mSrc[offset].mIntConst += ains->mSrc[0].mIntConst;
|
||||||
ins->mSrc[offset].mTemp = ains->mSrc[1].mTemp;
|
ins->mSrc[offset].mTemp = ains->mSrc[1].mTemp;
|
||||||
}
|
}
|
||||||
else if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0 && ains->mSrc[1].mTemp >= 0 && tvalue[ains->mSrc[1].mTemp] && ains->mSrc[0].mIntConst >= 0)
|
else if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0 && ains->mSrc[1].mTemp >= 0 && tvalue[ains->mSrc[1].mTemp] && ains->mSrc[0].mIntConst >= 0)
|
||||||
{
|
{
|
||||||
|
assert(false);
|
||||||
ins->mSrc[offset].mIntConst = ains->mSrc[0].mIntConst;
|
ins->mSrc[offset].mIntConst = ains->mSrc[0].mIntConst;
|
||||||
ins->mSrc[offset].mTemp = ains->mSrc[1].mTemp;
|
ins->mSrc[offset].mTemp = ains->mSrc[1].mTemp;
|
||||||
}
|
}
|
||||||
else if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[1].mTemp < 0 && ains->mSrc[0].mTemp >= 0 && tvalue[ains->mSrc[0].mTemp] && ains->mSrc[1].mIntConst >= 0)
|
else if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[1].mTemp < 0 && ains->mSrc[0].mTemp >= 0 && tvalue[ains->mSrc[0].mTemp] && ains->mSrc[1].mIntConst >= 0)
|
||||||
{
|
{
|
||||||
|
assert(false);
|
||||||
ins->mSrc[offset].mIntConst = ains->mSrc[1].mIntConst;
|
ins->mSrc[offset].mIntConst = ains->mSrc[1].mIntConst;
|
||||||
ins->mSrc[offset].mTemp = ains->mSrc[0].mTemp;
|
ins->mSrc[offset].mTemp = ains->mSrc[0].mTemp;
|
||||||
}
|
}
|
||||||
|
@ -3263,7 +3274,7 @@ void InterCodeBasicBlock::MapVariables(GrowingVariableArray& globalVars, Growing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterCodeBasicBlock::CollectOuterFrame(int level, int& size, bool &inner, bool &inlineAssembler)
|
void InterCodeBasicBlock::CollectOuterFrame(int level, int& size, bool &inner, bool &inlineAssembler, bool &byteCodeCall)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -3295,10 +3306,12 @@ void InterCodeBasicBlock::CollectOuterFrame(int level, int& size, bool &inner, b
|
||||||
}
|
}
|
||||||
else if (mInstructions[i]->mCode == IC_ASSEMBLER)
|
else if (mInstructions[i]->mCode == IC_ASSEMBLER)
|
||||||
inlineAssembler = true;
|
inlineAssembler = true;
|
||||||
|
else if (mInstructions[i]->mCode == IC_CALL)
|
||||||
|
byteCodeCall = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump) mTrueJump->CollectOuterFrame(level, size, inner, inlineAssembler);
|
if (mTrueJump) mTrueJump->CollectOuterFrame(level, size, inner, inlineAssembler, byteCodeCall);
|
||||||
if (mFalseJump) mFalseJump->CollectOuterFrame(level, size, inner, inlineAssembler);
|
if (mFalseJump) mFalseJump->CollectOuterFrame(level, size, inner, inlineAssembler, byteCodeCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3450,6 +3463,14 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
||||||
|
|
||||||
if (mLoopHead && mNumEntries == 2 && (mTrueJump == this || mFalseJump == this))
|
if (mLoopHead && mNumEntries == 2 && (mTrueJump == this || mFalseJump == this))
|
||||||
{
|
{
|
||||||
|
bool hasCall = false;
|
||||||
|
for (int i = 0; i < mInstructions.Size(); i++)
|
||||||
|
{
|
||||||
|
InterInstruction* ins = mInstructions[i];
|
||||||
|
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE)
|
||||||
|
hasCall = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mInstructions.Size(); i++)
|
for (int i = 0; i < mInstructions.Size(); i++)
|
||||||
{
|
{
|
||||||
InterInstruction* ins = mInstructions[i];
|
InterInstruction* ins = mInstructions[i];
|
||||||
|
@ -3463,6 +3484,10 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
||||||
{
|
{
|
||||||
ins->mInvariant = false;
|
ins->mInvariant = false;
|
||||||
}
|
}
|
||||||
|
else if (ins->mSrc[0].mMemory == IM_GLOBAL && hasCall)
|
||||||
|
{
|
||||||
|
ins->mInvariant = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int j = 0; j < mInstructions.Size(); j++)
|
for (int j = 0; j < mInstructions.Size(); j++)
|
||||||
|
@ -4159,12 +4184,13 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
mHasDynamicStack = false;
|
mHasDynamicStack = false;
|
||||||
mHasInlineAssembler = false;
|
mHasInlineAssembler = false;
|
||||||
|
mCallsByteCode = false;
|
||||||
if (!mLeafProcedure)
|
if (!mLeafProcedure)
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler);
|
mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode);
|
||||||
mCommonFrameSize = size;
|
mCommonFrameSize = size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4458,6 +4484,20 @@ bool InterCodeProcedure::GlobalConstantPropagation(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CollectConstTemps(ctemps, assignedTemps);
|
mEntryBlock->CollectConstTemps(ctemps, assignedTemps);
|
||||||
|
|
||||||
|
FILE* file;
|
||||||
|
fopen_s(&file, "r:\\cldiss.txt", "a");
|
||||||
|
|
||||||
|
for (int i = 0; i < assignedTemps.Size(); i++)
|
||||||
|
{
|
||||||
|
if (assignedTemps[i])
|
||||||
|
{
|
||||||
|
if (ctemps[i])
|
||||||
|
fprintf(file, "%d, ", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(file, "\n");
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
return mEntryBlock->PropagateConstTemps(ctemps);
|
return mEntryBlock->PropagateConstTemps(ctemps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -483,7 +483,7 @@ public:
|
||||||
void CollectVariables(GrowingVariableArray & globalVars, GrowingVariableArray & localVars);
|
void CollectVariables(GrowingVariableArray & globalVars, GrowingVariableArray & localVars);
|
||||||
void MapVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars);
|
void MapVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars);
|
||||||
|
|
||||||
void CollectOuterFrame(int level, int& size, bool& inner, bool& inlineAssembler);
|
void CollectOuterFrame(int level, int& size, bool& inner, bool& inlineAssembler, bool& byteCodeCall);
|
||||||
|
|
||||||
bool IsLeafProcedure(void);
|
bool IsLeafProcedure(void);
|
||||||
|
|
||||||
|
@ -511,7 +511,7 @@ public:
|
||||||
GrowingTypeArray mTemporaries;
|
GrowingTypeArray mTemporaries;
|
||||||
GrowingIntArray mTempOffset, mTempSizes;
|
GrowingIntArray mTempOffset, mTempSizes;
|
||||||
int mTempSize, mCommonFrameSize, mCallerSavedTemps;
|
int mTempSize, mCommonFrameSize, mCallerSavedTemps;
|
||||||
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler;
|
bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode;
|
||||||
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
GrowingInterCodeProcedurePtrArray mCalledFunctions;
|
||||||
|
|
||||||
InterCodeModule * mModule;
|
InterCodeModule * mModule;
|
||||||
|
|
|
@ -756,7 +756,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
if (inlineMapper)
|
if (inlineMapper)
|
||||||
{
|
{
|
||||||
ins->mConst.mMemory = IM_LOCAL;
|
ins->mConst.mMemory = IM_LOCAL;
|
||||||
ins->mConst.mVarIndex = inlineMapper->mParams[dec->mOffset];
|
ins->mConst.mVarIndex = inlineMapper->mParams[dec->mVarIndex];
|
||||||
}
|
}
|
||||||
else if (procType->mFlags & DTF_FASTCALL)
|
else if (procType->mFlags & DTF_FASTCALL)
|
||||||
ins->mConst.mMemory = IM_FPARAM;
|
ins->mConst.mMemory = IM_FPARAM;
|
||||||
|
@ -1298,13 +1298,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
block->Append(cins);
|
block->Append(cins);
|
||||||
|
|
||||||
ains->mCode = IC_BINARY_OPERATOR;
|
InterType ttype = InterTypeOf(vdl.mType);
|
||||||
ains->mOperator = IA_ADD;
|
if (ttype == IT_POINTER)
|
||||||
|
{
|
||||||
|
ains->mCode = IC_LEA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ains->mCode = IC_BINARY_OPERATOR;
|
||||||
|
ains->mOperator = IA_ADD;
|
||||||
|
}
|
||||||
ains->mSrc[0].mType = cins->mDst.mType;
|
ains->mSrc[0].mType = cins->mDst.mType;
|
||||||
ains->mSrc[0].mTemp = cins->mDst.mTemp;
|
ains->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
ains->mSrc[1].mType = InterTypeOf(vdl.mType);
|
ains->mSrc[1].mType = ttype;
|
||||||
ains->mSrc[1].mTemp = vdl.mTemp;
|
ains->mSrc[1].mTemp = vdl.mTemp;
|
||||||
ains->mDst.mType = ains->mSrc[1].mType;
|
ains->mDst.mType = ttype;
|
||||||
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
|
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
|
||||||
block->Append(ains);
|
block->Append(ains);
|
||||||
|
|
||||||
|
@ -1349,14 +1357,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric value or pointer");
|
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric value or pointer");
|
||||||
block->Append(cins);
|
block->Append(cins);
|
||||||
|
|
||||||
ains->mCode = IC_BINARY_OPERATOR;
|
InterType ttype = InterTypeOf(vdl.mType);
|
||||||
ains->mOperator = IA_ADD;
|
if (ttype == IT_POINTER)
|
||||||
|
{
|
||||||
|
ains->mCode = IC_LEA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ains->mCode = IC_BINARY_OPERATOR;
|
||||||
|
ains->mOperator = IA_ADD;
|
||||||
|
}
|
||||||
ains->mSrc[0].mType = cins->mDst.mType;
|
ains->mSrc[0].mType = cins->mDst.mType;
|
||||||
ains->mSrc[0].mTemp = cins->mDst.mTemp;
|
ains->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
ains->mSrc[1].mType = InterTypeOf(vdl.mType);
|
ains->mSrc[1].mType = ttype;
|
||||||
ains->mSrc[1].mTemp = vdl.mTemp;
|
ains->mSrc[1].mTemp = vdl.mTemp;
|
||||||
ains->mDst.mType = ains->mSrc[1].mType;
|
ains->mDst.mType = ttype;
|
||||||
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
|
ains->mDst.mTemp = proc->AddTemporary(ttype);
|
||||||
block->Append(ains);
|
block->Append(ains);
|
||||||
|
|
||||||
sins->mCode = IC_STORE;
|
sins->mCode = IC_STORE;
|
||||||
|
@ -1588,7 +1604,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
return ExValue(TheVoidTypeDeclaration);
|
return ExValue(TheVoidTypeDeclaration);
|
||||||
}
|
}
|
||||||
else if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INLINE) && !(inlineMapper && inlineMapper->mDepth > 3))
|
else if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10))
|
||||||
{
|
{
|
||||||
Declaration* fdec = exp->mLeft->mDecValue;
|
Declaration* fdec = exp->mLeft->mDecValue;
|
||||||
Expression* fexp = fdec->mValue;
|
Expression* fexp = fdec->mValue;
|
||||||
|
@ -1965,13 +1981,18 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
Declaration* vdec = refvars[i];
|
Declaration* vdec = refvars[i];
|
||||||
if (vdec->mType == DT_ARGUMENT)
|
if (vdec->mType == DT_ARGUMENT)
|
||||||
{
|
{
|
||||||
if (procType->mFlags & DTF_FASTCALL)
|
vins->mConst.mVarIndex = vdec->mVarIndex;
|
||||||
|
if (inlineMapper)
|
||||||
|
{
|
||||||
|
vins->mConst.mMemory = IM_LOCAL;
|
||||||
|
vins->mConst.mVarIndex = inlineMapper->mParams[vdec->mVarIndex];
|
||||||
|
}
|
||||||
|
else if (procType->mFlags & DTF_FASTCALL)
|
||||||
vins->mConst.mMemory = IM_FPARAM;
|
vins->mConst.mMemory = IM_FPARAM;
|
||||||
else
|
else
|
||||||
vins->mConst.mMemory = IM_PARAM;
|
vins->mConst.mMemory = IM_PARAM;
|
||||||
vins->mConst.mOperandSize = vdec->mSize;
|
vins->mConst.mOperandSize = vdec->mSize;
|
||||||
vins->mConst.mIntConst = vdec->mOffset;
|
vins->mConst.mIntConst = vdec->mOffset;
|
||||||
vins->mConst.mVarIndex = vdec->mVarIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
block->Append(vins);
|
block->Append(vins);
|
||||||
|
|
|
@ -15,9 +15,10 @@ static const uint32 LIVE_CPU_REG_C = 0x00000008;
|
||||||
static const uint32 LIVE_CPU_REG_Z = 0x00000010;
|
static const uint32 LIVE_CPU_REG_Z = 0x00000010;
|
||||||
static const uint32 LIVE_MEM = 0x00000020;
|
static const uint32 LIVE_MEM = 0x00000020;
|
||||||
|
|
||||||
|
static int GlobalValueNumber = 0;
|
||||||
|
|
||||||
NativeRegisterData::NativeRegisterData(void)
|
NativeRegisterData::NativeRegisterData(void)
|
||||||
: mMode(NRDM_UNKNOWN)
|
: mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +26,7 @@ NativeRegisterData::NativeRegisterData(void)
|
||||||
void NativeRegisterData::Reset(void)
|
void NativeRegisterData::Reset(void)
|
||||||
{
|
{
|
||||||
mMode = NRDM_UNKNOWN;
|
mMode = NRDM_UNKNOWN;
|
||||||
|
mValue = GlobalValueNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeRegisterDataSet::Reset(void)
|
void NativeRegisterDataSet::Reset(void)
|
||||||
|
@ -39,10 +41,57 @@ void NativeRegisterDataSet::ResetZeroPage(int addr)
|
||||||
for (int i = 0; i < NUM_REGS; i++)
|
for (int i = 0; i < NUM_REGS; i++)
|
||||||
{
|
{
|
||||||
if (mRegs[i].mMode == NRDM_ZERO_PAGE && mRegs[i].mValue == addr)
|
if (mRegs[i].mMode == NRDM_ZERO_PAGE && mRegs[i].mValue == addr)
|
||||||
mRegs[i].mMode = NRDM_UNKNOWN;
|
mRegs[i].Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeRegisterDataSet::Intersect(const NativeRegisterDataSet& set)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_REGS; i++)
|
||||||
|
{
|
||||||
|
if (mRegs[i].mMode == NRDM_UNKNOWN)
|
||||||
|
{
|
||||||
|
if (set.mRegs[i].mMode != NRDM_UNKNOWN || mRegs[i].mValue != set.mRegs[i].mValue)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
else if (mRegs[i].mMode == NRDM_IMMEDIATE)
|
||||||
|
{
|
||||||
|
if (set.mRegs[i].mMode != NRDM_IMMEDIATE || mRegs[i].mValue != set.mRegs[i].mValue)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
else if (mRegs[i].mMode == NRDM_IMMEDIATE_ADDRESS)
|
||||||
|
{
|
||||||
|
if (set.mRegs[i].mMode != NRDM_IMMEDIATE_ADDRESS || mRegs[i].mValue != set.mRegs[i].mValue || mRegs[i].mLinkerObject != set.mRegs[i].mLinkerObject || mRegs[i].mFlags != set.mRegs[i].mFlags)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_REGS; i++)
|
||||||
|
{
|
||||||
|
if (mRegs[i].mMode == NRDM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
if (set.mRegs[i].mMode != NRDM_ZERO_PAGE || mRegs[i].mValue != set.mRegs[i].mValue)
|
||||||
|
{
|
||||||
|
mRegs[i].Reset();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (mRegs[mRegs[i].mValue].mValue != set.mRegs[set.mRegs[i].mValue].mValue)
|
||||||
|
{
|
||||||
|
mRegs[i].Reset();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (changed);
|
||||||
|
}
|
||||||
|
|
||||||
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags)
|
NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, LinkerObject* linkerObject, uint32 flags)
|
||||||
: mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags)
|
: mType(type), mMode(mode), mAddress(address), mLinkerObject(linkerObject), mFlags(flags)
|
||||||
{}
|
{}
|
||||||
|
@ -448,7 +497,7 @@ bool NativeCodeInstruction::ChangesAccuAndFlag(void) const
|
||||||
return
|
return
|
||||||
mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
|
mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA ||
|
||||||
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
|
mType == ASMIT_ORA || mType == ASMIT_AND || mType == ASMIT_EOR ||
|
||||||
mType == ASMIT_SBC || mType == ASMIT_ADC;
|
mType == ASMIT_SBC || mType == ASMIT_ADC || mType == ASMIT_JSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeCodeInstruction::RequiresYReg(void) const
|
bool NativeCodeInstruction::RequiresYReg(void) const
|
||||||
|
@ -463,9 +512,26 @@ bool NativeCodeInstruction::RequiresYReg(void) const
|
||||||
|
|
||||||
bool NativeCodeInstruction::ChangesYReg(void) const
|
bool NativeCodeInstruction::ChangesYReg(void) const
|
||||||
{
|
{
|
||||||
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY;
|
return mType == ASMIT_TAY || mType == ASMIT_LDY || mType == ASMIT_INY || mType == ASMIT_DEY || mType == ASMIT_JSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeInstruction::ChangesZeroPage(int address) const
|
||||||
|
{
|
||||||
|
if (mMode == ASMIM_ZERO_PAGE && mAddress == address)
|
||||||
|
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeInstruction::ChangesGlobalMemory(void) const
|
||||||
|
{
|
||||||
|
if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
|
||||||
|
return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR || mType == ASMIT_STA || mType == ASMIT_STX || mType == ASMIT_STY || mType == ASMIT_JSR;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NativeCodeInstruction::RequiresAccu(void) const
|
bool NativeCodeInstruction::RequiresAccu(void) const
|
||||||
{
|
{
|
||||||
if (mMode == ASMIM_IMPLIED)
|
if (mMode == ASMIM_IMPLIED)
|
||||||
|
@ -578,6 +644,11 @@ bool NativeCodeInstruction::ApplySimulation(const NativeRegisterDataSet& data)
|
||||||
case ASMIT_CMP:
|
case ASMIT_CMP:
|
||||||
case ASMIT_CPX:
|
case ASMIT_CPX:
|
||||||
case ASMIT_CPY:
|
case ASMIT_CPY:
|
||||||
|
case ASMIT_ADC:
|
||||||
|
case ASMIT_SBC:
|
||||||
|
case ASMIT_AND:
|
||||||
|
case ASMIT_ORA:
|
||||||
|
case ASMIT_EOR:
|
||||||
if (mMode == ASMIM_ZERO_PAGE && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
if (mMode == ASMIM_ZERO_PAGE && data.mRegs[mAddress].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mMode = ASMIM_IMMEDIATE;
|
mMode = ASMIM_IMMEDIATE;
|
||||||
|
@ -1314,6 +1385,25 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASMIT_ADC:
|
case ASMIT_ADC:
|
||||||
|
if (data.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_C].mValue == 0)
|
||||||
|
{
|
||||||
|
if (mMode == ASMIM_IMMEDIATE && mAddress == 0)
|
||||||
|
{
|
||||||
|
mType = ASMIT_ORA;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0)
|
||||||
|
{
|
||||||
|
mType = ASMIT_LDA;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.mRegs[CPU_REG_A].Reset();
|
||||||
|
data.mRegs[CPU_REG_C].Reset();
|
||||||
|
data.mRegs[CPU_REG_Z].Reset();
|
||||||
|
break;
|
||||||
|
|
||||||
case ASMIT_SBC:
|
case ASMIT_SBC:
|
||||||
data.mRegs[CPU_REG_A].Reset();
|
data.mRegs[CPU_REG_A].Reset();
|
||||||
data.mRegs[CPU_REG_C].Reset();
|
data.mRegs[CPU_REG_C].Reset();
|
||||||
|
@ -1377,6 +1467,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
||||||
data.mRegs[CPU_REG_A].mValue = mAddress;
|
data.mRegs[CPU_REG_A].mValue = mAddress;
|
||||||
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
data.mRegs[CPU_REG_Z].mMode = NRDM_IMMEDIATE;
|
||||||
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0)
|
else if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0)
|
||||||
{
|
{
|
||||||
|
@ -1391,6 +1482,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
||||||
mMode = ASMIM_IMMEDIATE;
|
mMode = ASMIM_IMMEDIATE;
|
||||||
mAddress = 0;
|
mAddress = 0;
|
||||||
}
|
}
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1715,6 +1807,13 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mMode == ASMIM_INDIRECT_Y)
|
||||||
|
{
|
||||||
|
if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress + 1].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress].mValue + 1 == data.mRegs[mAddress + 1].mValue)
|
||||||
|
{
|
||||||
|
mAddress = data.mRegs[mAddress].mValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
@ -1968,7 +2067,7 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
|
||||||
{
|
{
|
||||||
if (mType == ASMIT_BYTE)
|
if (mType == ASMIT_BYTE)
|
||||||
block->PutByte(mAddress);
|
block->PutByte(mAddress);
|
||||||
else if (mType == ASMIT_JSR && (mLinkerObject->mFlags & LOBJF_INLINE))
|
else if (mType == ASMIT_JSR && mLinkerObject && (mLinkerObject->mFlags & LOBJF_INLINE))
|
||||||
{
|
{
|
||||||
int pos = block->mCode.Size();
|
int pos = block->mCode.Size();
|
||||||
for (int i = 0; i < mLinkerObject->mSize - 1; i++)
|
for (int i = 0; i < mLinkerObject->mSize - 1; i++)
|
||||||
|
@ -3769,6 +3868,7 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
|
||||||
|
|
||||||
switch (lmul)
|
switch (lmul)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
case 1:
|
case 1:
|
||||||
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
||||||
return BC_REG_ACCU;
|
return BC_REG_ACCU;
|
||||||
|
@ -3806,7 +3906,47 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
||||||
return BC_REG_ACCU;
|
return BC_REG_ACCU;
|
||||||
#if 0
|
case 7:
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
||||||
|
return BC_REG_ACCU;
|
||||||
|
case 9:
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_TXA, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
||||||
|
return BC_REG_ACCU;
|
||||||
|
#if 1
|
||||||
case 25:
|
case 25:
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||||
|
@ -3836,6 +3976,7 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
|
||||||
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
ShiftRegisterLeft(proc, BC_REG_ACCU, lshift);
|
||||||
return BC_REG_ACCU;
|
return BC_REG_ACCU;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul));
|
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul));
|
||||||
|
@ -6320,6 +6461,9 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void)
|
||||||
|
|
||||||
void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
|
void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
|
||||||
{
|
{
|
||||||
|
if (mVisiting)
|
||||||
|
mLoopHead = true;
|
||||||
|
|
||||||
if (mNumEntries == 0)
|
if (mNumEntries == 0)
|
||||||
mFromJump = fromJump;
|
mFromJump = fromJump;
|
||||||
else
|
else
|
||||||
|
@ -6329,11 +6473,14 @@ void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
mVisiting = true;
|
||||||
|
|
||||||
if (mTrueJump)
|
if (mTrueJump)
|
||||||
mTrueJump->CountEntries(this);
|
mTrueJump->CountEntries(this);
|
||||||
if (mFalseJump)
|
if (mFalseJump)
|
||||||
mFalseJump->CountEntries(this);
|
mFalseJump->CountEntries(this);
|
||||||
|
|
||||||
|
mVisiting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6408,15 +6555,15 @@ void NativeCodeBasicBlock::BuildEntryDataSet(const NativeRegisterDataSet& set)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
|
||||||
NativeRegisterDataSet nset = mEntryRegisterDataSet;
|
mNDataSet = mEntryRegisterDataSet;
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
mIns[i].Simulate(nset);
|
mIns[i].Simulate(mNDataSet);
|
||||||
|
|
||||||
if (mTrueJump)
|
if (mTrueJump)
|
||||||
mTrueJump->BuildEntryDataSet(nset);
|
mTrueJump->BuildEntryDataSet(mNDataSet);
|
||||||
if (mFalseJump)
|
if (mFalseJump)
|
||||||
mFalseJump->BuildEntryDataSet(nset);
|
mFalseJump->BuildEntryDataSet(mNDataSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6428,13 +6575,13 @@ bool NativeCodeBasicBlock::ApplyEntryDataSet(void)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
|
||||||
NativeRegisterDataSet nset = mEntryRegisterDataSet;
|
mNDataSet = mEntryRegisterDataSet;
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].ApplySimulation(nset))
|
if (mIns[i].ApplySimulation(mNDataSet))
|
||||||
changed = true;
|
changed = true;
|
||||||
mIns[i].Simulate(nset);
|
mIns[i].Simulate(mNDataSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTrueJump && mTrueJump->ApplyEntryDataSet())
|
if (mTrueJump && mTrueJump->ApplyEntryDataSet())
|
||||||
|
@ -6627,6 +6774,35 @@ bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& bre
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
|
||||||
|
{
|
||||||
|
int j = at - 1;
|
||||||
|
while (j > 0)
|
||||||
|
{
|
||||||
|
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress)
|
||||||
|
{
|
||||||
|
mIns.Insert(j + 1, mIns[at + 1]);
|
||||||
|
mIns.Insert(j + 2, mIns[at + 3]);
|
||||||
|
mIns[at + 4].mType = ASMIT_NOP;
|
||||||
|
mIns[at + 4].mMode = ASMIM_IMPLIED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIns[j].ChangesYReg())
|
||||||
|
return false;
|
||||||
|
if (mIns[j].ChangesZeroPage(mIns[at].mAddress))
|
||||||
|
return false;
|
||||||
|
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress))
|
||||||
|
return false;
|
||||||
|
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
|
||||||
{
|
{
|
||||||
int j = at;
|
int j = at;
|
||||||
|
@ -6664,16 +6840,37 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
||||||
|
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mNDataSet = data;
|
||||||
|
|
||||||
NativeRegisterDataSet ndata(data);
|
if (mLoopHead)
|
||||||
|
{
|
||||||
if (mNumEntries != 1)
|
mNDataSet.Reset();
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if (mNumEntries != 1)
|
||||||
|
{
|
||||||
ndata.Reset();
|
ndata.Reset();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (mNumEntries > 0)
|
||||||
|
{
|
||||||
|
if (mNumEntered > 0)
|
||||||
|
mNDataSet.Intersect(mDataSet);
|
||||||
|
|
||||||
|
mNumEntered++;
|
||||||
|
|
||||||
|
if (mNumEntered < mNumEntries)
|
||||||
|
{
|
||||||
|
mDataSet = mNDataSet;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].ValueForwarding(ndata))
|
if (mIns[i].ValueForwarding(mNDataSet))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6682,60 +6879,60 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
||||||
switch (mBranch)
|
switch (mBranch)
|
||||||
{
|
{
|
||||||
case ASMIT_BCS:
|
case ASMIT_BCS:
|
||||||
if (ndata.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if (!ndata.mRegs[CPU_REG_C].mValue)
|
if (!mNDataSet.mRegs[CPU_REG_C].mValue)
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_BCC:
|
case ASMIT_BCC:
|
||||||
if (ndata.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if (ndata.mRegs[CPU_REG_C].mValue)
|
if (mNDataSet.mRegs[CPU_REG_C].mValue)
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_BNE:
|
case ASMIT_BNE:
|
||||||
if (ndata.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if (!ndata.mRegs[CPU_REG_Z].mValue)
|
if (!mNDataSet.mRegs[CPU_REG_Z].mValue)
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_BEQ:
|
case ASMIT_BEQ:
|
||||||
if (ndata.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if (ndata.mRegs[CPU_REG_Z].mValue)
|
if (mNDataSet.mRegs[CPU_REG_Z].mValue)
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_BPL:
|
case ASMIT_BPL:
|
||||||
if (ndata.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if ((ndata.mRegs[CPU_REG_Z].mValue & 0x80))
|
if ((mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_BMI:
|
case ASMIT_BMI:
|
||||||
if (ndata.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
|
||||||
{
|
{
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
if (!(ndata.mRegs[CPU_REG_Z].mValue & 0x80))
|
if (!(mNDataSet.mRegs[CPU_REG_Z].mValue & 0x80))
|
||||||
mTrueJump = mFalseJump;
|
mTrueJump = mFalseJump;
|
||||||
mFalseJump = nullptr;
|
mFalseJump = nullptr;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -6744,9 +6941,9 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->mTrueJump && this->mTrueJump->ValueForwarding(ndata))
|
if (this->mTrueJump && this->mTrueJump->ValueForwarding(mNDataSet))
|
||||||
changed = true;
|
changed = true;
|
||||||
if (this->mFalseJump && this->mFalseJump->ValueForwarding(ndata))
|
if (this->mFalseJump && this->mFalseJump->ValueForwarding(mNDataSet))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7074,6 +7271,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// move load - store (),y up to initial store
|
||||||
|
//
|
||||||
|
|
||||||
|
for (int i = 2; i + 2 < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].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)
|
||||||
|
{
|
||||||
|
if (MoveIndirectLoadStoreUp(i))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
// shorten x/y register livetime
|
// shorten x/y register livetime
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -7267,6 +7480,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (mIns[i + 1].mType == ASMIT_ORA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && mIns[i].ChangesAccuAndFlag())
|
||||||
|
{
|
||||||
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 1].mType == ASMIT_CMP && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && mIns[i].ChangesAccuAndFlag() && !(mIns[i + 1].mLive & LIVE_CPU_REG_C))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress &&
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress &&
|
||||||
(mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR))
|
(mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR))
|
||||||
|
@ -7376,6 +7601,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
mIns[i + 1].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].ChangesAccuAndFlag() &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STA &&
|
||||||
|
mIns[i + 2].mType == ASMIT_CMP && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0 && !(mIns[i + 2].mLive & LIVE_CPU_REG_C))
|
||||||
|
{
|
||||||
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 0].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
||||||
|
mIns[i + 1].mLive |= mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z);
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||||
(mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR) &&
|
(mIns[i + 1].mType == ASMIT_ASL || mIns[i + 1].mType == ASMIT_LSR || mIns[i + 1].mType == ASMIT_ROL || mIns[i + 1].mType == ASMIT_ROR) &&
|
||||||
|
@ -7879,6 +8114,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
|
int tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
|
||||||
int stackExpand = tempSave + proc->mLocalSize;
|
int stackExpand = tempSave + proc->mLocalSize;
|
||||||
|
int commonFrameSize = proc->mCommonFrameSize;
|
||||||
|
|
||||||
|
if (proc->mCallsByteCode || commonFrameSize > 0)
|
||||||
|
commonFrameSize += 2;
|
||||||
|
|
||||||
mFrameOffset = 0;
|
mFrameOffset = 0;
|
||||||
mNoFrame = (stackExpand + proc->mCommonFrameSize) < 64 && !proc->mHasDynamicStack && !(proc->mHasInlineAssembler && !proc->mLeafProcedure);
|
mNoFrame = (stackExpand + proc->mCommonFrameSize) < 64 && !proc->mHasDynamicStack && !(proc->mHasInlineAssembler && !proc->mLeafProcedure);
|
||||||
|
@ -7966,16 +8205,19 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
if (!proc->mLeafProcedure)
|
if (!proc->mLeafProcedure)
|
||||||
{
|
{
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
if (commonFrameSize > 0)
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
{
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (proc->mCommonFrameSize + 2) & 0xff));
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED));
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ((proc->mCommonFrameSize + 2) >> 8) & 0xff));
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
||||||
|
entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
|
}
|
||||||
|
|
||||||
if (mNoFrame)
|
if (mNoFrame)
|
||||||
mFrameOffset = proc->mCommonFrameSize + tempSave + 2;
|
mFrameOffset = commonFrameSize + tempSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
entryBlock->mFrameOffset = mFrameOffset;
|
entryBlock->mFrameOffset = mFrameOffset;
|
||||||
|
@ -7985,14 +8227,14 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
exitBlock = AllocateBlock();
|
exitBlock = AllocateBlock();
|
||||||
mBlocks.Push(exitBlock);
|
mBlocks.Push(exitBlock);
|
||||||
|
|
||||||
if (!proc->mLeafProcedure)
|
if (!proc->mLeafProcedure && commonFrameSize > 0)
|
||||||
{
|
{
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (proc->mCommonFrameSize + 2) & 0xff));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, commonFrameSize & 0xff));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ((proc->mCommonFrameSize + 2) >> 8) & 0xff));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (commonFrameSize >> 8) & 0xff));
|
||||||
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8060,6 +8302,8 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
|
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
int step = 0;
|
||||||
|
|
||||||
bool changed;
|
bool changed;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -8067,6 +8311,8 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
for (int i = 0; i < mBlocks.Size(); i++)
|
for (int i = 0; i < mBlocks.Size(); i++)
|
||||||
{
|
{
|
||||||
mBlocks[i]->mNumEntries = 0;
|
mBlocks[i]->mNumEntries = 0;
|
||||||
|
mBlocks[i]->mVisiting = false;
|
||||||
|
mBlocks[i]->mLoopHead = false;
|
||||||
mBlocks[i]->mFromJump = nullptr;
|
mBlocks[i]->mFromJump = nullptr;
|
||||||
}
|
}
|
||||||
entryBlock->CountEntries(nullptr);
|
entryBlock->CountEntries(nullptr);
|
||||||
|
@ -8101,9 +8347,12 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
mBlocks[i]->mEntryBlocks.SetSize(0);
|
mBlocks[i]->mEntryBlocks.SetSize(0);
|
||||||
entryBlock->CollectEntryBlocks(nullptr);
|
entryBlock->CollectEntryBlocks(nullptr);
|
||||||
|
|
||||||
ResetVisited();
|
if (step > 2)
|
||||||
if (entryBlock->JoinTailCodeSequences())
|
{
|
||||||
changed = true;
|
ResetVisited();
|
||||||
|
if (entryBlock->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
NativeRegisterDataSet data;
|
NativeRegisterDataSet data;
|
||||||
|
@ -8113,6 +8362,11 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
if (entryBlock->ApplyEntryDataSet())
|
if (entryBlock->ApplyEntryDataSet())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
if (!changed && step < 4)
|
||||||
|
{
|
||||||
|
step++;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
} while (changed);
|
} while (changed);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8198,7 +8452,10 @@ void NativeCodeProcedure::ResetVisited(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < mBlocks.Size(); i++)
|
for (i = 0; i < mBlocks.Size(); i++)
|
||||||
|
{
|
||||||
mBlocks[i]->mVisited = false;
|
mBlocks[i]->mVisited = false;
|
||||||
|
mBlocks[i]->mNumEntered = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8517,6 +8774,9 @@ NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* i
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < mRuntime.Size() && mRuntime[i].mIdent != ident)
|
while (i < mRuntime.Size() && mRuntime[i].mIdent != ident)
|
||||||
i++;
|
i++;
|
||||||
|
Location loc;
|
||||||
|
if (i == mRuntime.Size() || !mRuntime[i].mLinkerObject)
|
||||||
|
mErrors->Error(loc, EERR_RUNTIME_CODE, "Undefied runtime function", ident->mString);
|
||||||
return mRuntime[i];
|
return mRuntime[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct NativeRegisterDataSet
|
||||||
|
|
||||||
void Reset(void);
|
void Reset(void);
|
||||||
void ResetZeroPage(int addr);
|
void ResetZeroPage(int addr);
|
||||||
|
void Intersect(const NativeRegisterDataSet& set);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +71,8 @@ public:
|
||||||
bool RequiresAccu(void) const;
|
bool RequiresAccu(void) const;
|
||||||
bool RequiresYReg(void) const;
|
bool RequiresYReg(void) const;
|
||||||
bool ChangesYReg(void) const;
|
bool ChangesYReg(void) const;
|
||||||
|
bool ChangesZeroPage(int address) const;
|
||||||
|
bool ChangesGlobalMemory(void) const;
|
||||||
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
|
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
|
||||||
bool IsSame(const NativeCodeInstruction& ins) const;
|
bool IsSame(const NativeCodeInstruction& ins) const;
|
||||||
bool IsCommutative(void) const;
|
bool IsCommutative(void) const;
|
||||||
|
@ -92,8 +95,10 @@ public:
|
||||||
|
|
||||||
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
int mOffset, mSize, mNumEntries, mFrameOffset;
|
int mOffset, mSize, mNumEntries, mNumEntered, mFrameOffset;
|
||||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited;
|
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting;
|
||||||
|
|
||||||
|
NativeRegisterDataSet mDataSet, mNDataSet;
|
||||||
|
|
||||||
int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
|
int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
|
||||||
int PutJump(NativeCodeProcedure* proc, int offset);
|
int PutJump(NativeCodeProcedure* proc, int offset);
|
||||||
|
@ -147,8 +152,10 @@ public:
|
||||||
|
|
||||||
void CountEntries(NativeCodeBasicBlock* fromJump);
|
void CountEntries(NativeCodeBasicBlock* fromJump);
|
||||||
bool MergeBasicBlocks(void);
|
bool MergeBasicBlocks(void);
|
||||||
|
void MarkLoopHead(void);
|
||||||
|
|
||||||
bool MoveLoadStoreUp(int at);
|
bool MoveLoadStoreUp(int at);
|
||||||
|
bool MoveIndirectLoadStoreUp(int at);
|
||||||
bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);
|
bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);
|
||||||
bool FindGlobalAddress(int at, int reg, int& apos);
|
bool FindGlobalAddress(int at, int reg, int& apos);
|
||||||
bool FindGlobalAddressSumY(int at, int reg, const NativeCodeInstruction * & ains, int& ireg);
|
bool FindGlobalAddressSumY(int at, int reg, const NativeCodeInstruction * & ains, int& ireg);
|
||||||
|
|
|
@ -704,13 +704,7 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
||||||
|
|
||||||
if (mScanner->mToken == TK_INLINE)
|
if (mScanner->mToken == TK_INLINE)
|
||||||
{
|
{
|
||||||
storageFlags |= DTF_INLINE;
|
storageFlags |= DTF_REQUEST_INLINE;
|
||||||
mScanner->NextToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mScanner->mToken == TK_FASTCALL)
|
|
||||||
{
|
|
||||||
typeFlags |= DTF_FASTCALL;
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,6 +779,18 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
||||||
|
|
||||||
ndec = pdec;
|
ndec = pdec;
|
||||||
}
|
}
|
||||||
|
else if ((ndec->mFlags & DTF_EXTERN) || (pdec->mFlags & DTF_EXTERN))
|
||||||
|
{
|
||||||
|
if (!ndec->mBase->IsSame(pdec->mBase))
|
||||||
|
{
|
||||||
|
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Variable declaration differs");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ndec->mFlags & DTF_EXTERN))
|
||||||
|
pdec->mFlags &= ~DTF_EXTERN;
|
||||||
|
|
||||||
|
ndec = pdec;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate variable declaration", ndec->mIdent->mString);
|
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate variable declaration", ndec->mIdent->mString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ const char* TokenNames[] = {
|
||||||
"'static'",
|
"'static'",
|
||||||
"'extern'",
|
"'extern'",
|
||||||
"'inline'",
|
"'inline'",
|
||||||
"'__fastcall'",
|
|
||||||
|
|
||||||
"__asm",
|
"__asm",
|
||||||
|
|
||||||
|
@ -1152,8 +1151,6 @@ void Scanner::NextRawToken(void)
|
||||||
mToken = TK_EXTERN;
|
mToken = TK_EXTERN;
|
||||||
else if (!strcmp(tkident, "inline"))
|
else if (!strcmp(tkident, "inline"))
|
||||||
mToken = TK_INLINE;
|
mToken = TK_INLINE;
|
||||||
else if (!strcmp(tkident, "__fastcall"))
|
|
||||||
mToken = TK_FASTCALL;
|
|
||||||
else if (!strcmp(tkident, "__asm"))
|
else if (!strcmp(tkident, "__asm"))
|
||||||
mToken = TK_ASM;
|
mToken = TK_ASM;
|
||||||
else
|
else
|
||||||
|
|
|
@ -45,7 +45,6 @@ enum Token
|
||||||
TK_STATIC,
|
TK_STATIC,
|
||||||
TK_EXTERN,
|
TK_EXTERN,
|
||||||
TK_INLINE,
|
TK_INLINE,
|
||||||
TK_FASTCALL,
|
|
||||||
|
|
||||||
TK_ASM,
|
TK_ASM,
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,7 @@
|
||||||
<ClCompile Include="Disassembler.cpp" />
|
<ClCompile Include="Disassembler.cpp" />
|
||||||
<ClCompile Include="Emulator.cpp" />
|
<ClCompile Include="Emulator.cpp" />
|
||||||
<ClCompile Include="Errors.cpp" />
|
<ClCompile Include="Errors.cpp" />
|
||||||
|
<ClCompile Include="GlobalAnalyzer.cpp" />
|
||||||
<ClCompile Include="Ident.cpp" />
|
<ClCompile Include="Ident.cpp" />
|
||||||
<ClCompile Include="InterCode.cpp" />
|
<ClCompile Include="InterCode.cpp" />
|
||||||
<ClCompile Include="InterCodeGenerator.cpp" />
|
<ClCompile Include="InterCodeGenerator.cpp" />
|
||||||
|
@ -171,6 +172,7 @@
|
||||||
<ClInclude Include="Disassembler.h" />
|
<ClInclude Include="Disassembler.h" />
|
||||||
<ClInclude Include="Emulator.h" />
|
<ClInclude Include="Emulator.h" />
|
||||||
<ClInclude Include="Errors.h" />
|
<ClInclude Include="Errors.h" />
|
||||||
|
<ClInclude Include="GlobalAnalyzer.h" />
|
||||||
<ClInclude Include="Ident.h" />
|
<ClInclude Include="Ident.h" />
|
||||||
<ClInclude Include="InterCode.h" />
|
<ClInclude Include="InterCode.h" />
|
||||||
<ClInclude Include="InterCodeGenerator.h" />
|
<ClInclude Include="InterCodeGenerator.h" />
|
||||||
|
|
|
@ -69,6 +69,9 @@
|
||||||
<ClCompile Include="Disassembler.cpp">
|
<ClCompile Include="Disassembler.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GlobalAnalyzer.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Array.h">
|
<ClInclude Include="Array.h">
|
||||||
|
@ -137,6 +140,9 @@
|
||||||
<ClInclude Include="Disassembler.h">
|
<ClInclude Include="Disassembler.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="GlobalAnalyzer.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="oscar64.rc">
|
<ResourceCompile Include="oscar64.rc">
|
||||||
|
|
Loading…
Reference in New Issue