More native code compiler additions
This commit is contained in:
parent
056df56eef
commit
fcedf69aff
|
@ -36,6 +36,9 @@ if %errorlevel% neq 0 goto :error
|
|||
..\release\oscar64 -i=../include -rt=../include/crt.c -e array2stringinittest.c
|
||||
if %errorlevel% neq 0 goto :error
|
||||
|
||||
..\release\oscar64 -i=../include -rt=../include/crt.c -e testint16cmp.c
|
||||
if %errorlevel% neq 0 goto :error
|
||||
|
||||
exit /b 0
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
bool beq(int a, int b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
bool blt(int a, int b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
bool bgt(int a, int b)
|
||||
{
|
||||
return a > b;
|
||||
}
|
||||
|
||||
bool ble(int a, int b)
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
bool bge(int a, int b)
|
||||
{
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
bool neq(int a, int b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
#pragma native(neq)
|
||||
|
||||
bool nlt(int a, int b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
#pragma native(nlt)
|
||||
|
||||
bool ngt(int a, int b)
|
||||
{
|
||||
return a > b;
|
||||
}
|
||||
|
||||
#pragma native(ngt)
|
||||
|
||||
bool nle(int a, int b)
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
#pragma native(nlt)
|
||||
|
||||
bool nge(int a, int b)
|
||||
{
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
#pragma native(ngt)
|
||||
|
||||
void cmp(int a, int b)
|
||||
{
|
||||
bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = blt(a, b), bgef = bgt(a, b);
|
||||
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nlt(a, b), ngef = ngt(a, b);
|
||||
|
||||
// printf("BYTE %d, %d : EQ %d LT %d GT %d\r", a, b, beqf, bltf, bgtf);
|
||||
// printf("NATIVE %d, %d : EQ %d LT %d GT %d\r", a, b, neqf, nltf, ngtf);
|
||||
|
||||
assert(beqf == neqf);
|
||||
assert(bltf == nltf);
|
||||
assert(bgtf == ngtf);
|
||||
assert(blef == nlef);
|
||||
assert(bgef == ngef);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
cmp( 0, 1);
|
||||
cmp( 0, -1);
|
||||
cmp( 1, 0);
|
||||
cmp(-1, 0);
|
||||
|
||||
cmp(1, 1);
|
||||
cmp(1, 2);
|
||||
cmp(2, 1);
|
||||
|
||||
cmp(-1, -1);
|
||||
cmp(-1, -2);
|
||||
cmp(-2, -1);
|
||||
|
||||
cmp( 1, -1);
|
||||
cmp( 1, -2);
|
||||
cmp( 2, -1);
|
||||
|
||||
cmp(-1, 1);
|
||||
cmp(-1, 2);
|
||||
cmp(-2, 1);
|
||||
|
||||
|
||||
cmp( 0, 10000);
|
||||
cmp( 0, -10000);
|
||||
cmp( 10000, 0);
|
||||
cmp(-10000, 0);
|
||||
|
||||
cmp(10000, 10000);
|
||||
cmp(10000, 20000);
|
||||
cmp(20000, 10000);
|
||||
|
||||
cmp(-10000, -10000);
|
||||
cmp(-10000, -20000);
|
||||
cmp(-20000, -10000);
|
||||
|
||||
cmp( 10000, -10000);
|
||||
cmp( 10000, -20000);
|
||||
cmp( 20000, -10000);
|
||||
|
||||
cmp(-10000, 10000);
|
||||
cmp(-10000, 20000);
|
||||
cmp(-20000, 10000);
|
||||
|
||||
cmp( 0, 1024);
|
||||
cmp( 0, -1024);
|
||||
cmp( 1024, 0);
|
||||
cmp(-1024, 0);
|
||||
|
||||
cmp(1024, 1024);
|
||||
cmp(1024, 1025);
|
||||
cmp(1025, 1024);
|
||||
|
||||
cmp(-1024, -1024);
|
||||
cmp(-1024, -1025);
|
||||
cmp(-1025, -1024);
|
||||
|
||||
cmp( 1024, -1024);
|
||||
cmp( 1024, -1025);
|
||||
cmp( 1025, -1024);
|
||||
|
||||
cmp(-1024, 1024);
|
||||
cmp(-1024, 1025);
|
||||
cmp(-1025, 1024);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
121
include/crt.c
121
include/crt.c
|
@ -38,7 +38,31 @@ incip:
|
|||
|
||||
#pragma startup(startup)
|
||||
|
||||
// divide accu by tmp
|
||||
__asm negaccu
|
||||
{
|
||||
sec
|
||||
lda #0
|
||||
sbc accu
|
||||
sta accu
|
||||
lda #0
|
||||
sbc accu + 1
|
||||
sta accu + 1
|
||||
rts
|
||||
}
|
||||
|
||||
__asm negtmp
|
||||
{
|
||||
sec
|
||||
lda #0
|
||||
sbc tmp
|
||||
sta tmp
|
||||
lda #0
|
||||
sbc tmp + 1
|
||||
sta tmp + 1
|
||||
rts
|
||||
}
|
||||
|
||||
// divide accu by tmp result in accu, remainder in tmp + 2
|
||||
|
||||
__asm divmod
|
||||
{
|
||||
|
@ -68,6 +92,77 @@ W1: dey
|
|||
ldy tmpy
|
||||
rts
|
||||
}
|
||||
|
||||
// Multiply accu by tmp result in tmp + 2
|
||||
|
||||
__asm mul16
|
||||
{
|
||||
lda #0
|
||||
sta tmp + 2
|
||||
sta tmp + 3
|
||||
|
||||
ldx #16
|
||||
L1: lsr tmp + 1
|
||||
ror tmp
|
||||
bcc W1
|
||||
clc
|
||||
lda tmp + 2
|
||||
adc accu
|
||||
sta tmp + 2
|
||||
lda tmp + 3
|
||||
adc accu + 1
|
||||
sta tmp + 3
|
||||
W1: asl accu
|
||||
rol accu + 1
|
||||
dex
|
||||
bne L1
|
||||
rts
|
||||
}
|
||||
|
||||
__asm divs16
|
||||
{
|
||||
bit accu + 1
|
||||
bpl L1
|
||||
jsr negaccu
|
||||
bit tmp + 1
|
||||
bpl L2
|
||||
jsr negtmp
|
||||
L3: jmp divmod
|
||||
L1: bit tmp + 1
|
||||
bpl L3
|
||||
jsr negtmp
|
||||
L2: jsr divmod
|
||||
jmp negaccu
|
||||
}
|
||||
|
||||
__asm mods16
|
||||
{
|
||||
bit accu + 1
|
||||
bpl L1
|
||||
jsr negaccu
|
||||
bit tmp + 1
|
||||
bpl L2
|
||||
jsr negtmp
|
||||
L3: jmp divmod
|
||||
L1: bit tmp + 1
|
||||
bpl L3
|
||||
jsr negtmp
|
||||
L2: jsr divmod
|
||||
sec
|
||||
lda #0
|
||||
sbc tmp + 2
|
||||
sta tmp + 2
|
||||
lda #0
|
||||
sbc tmp + 3
|
||||
sta tmp + 3
|
||||
rts
|
||||
}
|
||||
|
||||
#pragma runtime(mul16, mul16);
|
||||
#pragma runtime(divu16, divmod);
|
||||
#pragma runtime(modu16, divmod);
|
||||
#pragma runtime(divs16, divs16);
|
||||
#pragma runtime(mods16, mods16);
|
||||
|
||||
/*
|
||||
!align 255, 0
|
||||
|
@ -983,30 +1078,6 @@ __asm inp_binop_modr_u16
|
|||
|
||||
#pragma bytecode(BC_BINOP_MODR_U16, inp_binop_modr_u16)
|
||||
|
||||
__asm negaccu
|
||||
{
|
||||
sec
|
||||
lda #0
|
||||
sbc accu
|
||||
sta accu
|
||||
lda #0
|
||||
sbc accu + 1
|
||||
sta accu + 1
|
||||
rts
|
||||
}
|
||||
|
||||
__asm negtmp
|
||||
{
|
||||
sec
|
||||
lda #0
|
||||
sbc tmp
|
||||
sta tmp
|
||||
lda #0
|
||||
sbc tmp + 1
|
||||
sta tmp + 1
|
||||
rts
|
||||
}
|
||||
|
||||
__asm inp_binop_divr_s16
|
||||
{
|
||||
lda (ip), y
|
||||
|
|
|
@ -187,6 +187,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
|||
rl.mUpper = true;
|
||||
rl.mIndex = mVIndex;
|
||||
rl.mOffset = mValue;
|
||||
rl.mRuntime = nullptr;
|
||||
block->mRelocations.Push(rl);
|
||||
block->PutWord(0);
|
||||
}
|
||||
|
@ -233,6 +234,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
|||
rl.mUpper = true;
|
||||
rl.mIndex = mVIndex;
|
||||
rl.mOffset = mValue;
|
||||
rl.mRuntime = nullptr;
|
||||
block->mRelocations.Push(rl);
|
||||
block->PutWord(0);
|
||||
}
|
||||
|
@ -253,6 +255,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
|||
rl.mUpper = true;
|
||||
rl.mIndex = mVIndex;
|
||||
rl.mOffset = mValue;
|
||||
rl.mRuntime = nullptr;
|
||||
block->mRelocations.Push(rl);
|
||||
block->PutWord(0);
|
||||
}
|
||||
|
@ -410,6 +413,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
|||
rl.mUpper = true;
|
||||
rl.mIndex = mVIndex;
|
||||
rl.mOffset = 0;
|
||||
rl.mRuntime = nullptr;
|
||||
block->mRelocations.Push(rl);
|
||||
|
||||
block->PutWord(0);
|
||||
|
@ -1484,6 +1488,22 @@ void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInst
|
|||
bins.mFunction = ins.mMemory == IM_PROCEDURE;
|
||||
mIns.Push(bins);
|
||||
}
|
||||
|
||||
if (ins.mTTemp >= 0)
|
||||
{
|
||||
if (ins.mTType == IT_FLOAT)
|
||||
{
|
||||
ByteCodeInstruction bins(BC_STORE_REG_32);
|
||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp];
|
||||
mIns.Push(bins);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCodeInstruction bins(BC_STORE_REG_16);
|
||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mTTemp];
|
||||
mIns.Push(bins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins)
|
||||
|
|
|
@ -143,9 +143,10 @@ class ByteCodeGenerator;
|
|||
class ByteCodeRelocation
|
||||
{
|
||||
public:
|
||||
uint16 mAddr;
|
||||
bool mFunction, mLower, mUpper;
|
||||
uint16 mIndex, mOffset;
|
||||
uint16 mAddr;
|
||||
bool mFunction, mLower, mUpper;
|
||||
uint16 mIndex, mOffset;
|
||||
const char * mRuntime;
|
||||
};
|
||||
|
||||
class ByteCodeBasicBlock;
|
||||
|
|
|
@ -9,6 +9,7 @@ CompilationUnits::CompilationUnits(Errors * errors)
|
|||
mCompilationUnits = nullptr;
|
||||
mPendingUnits = nullptr;
|
||||
mScope = new DeclarationScope(nullptr);
|
||||
mRuntimeScope = new DeclarationScope(nullptr);
|
||||
mStartup = nullptr;
|
||||
|
||||
for (int i = 0; i < 128; i++)
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
Declaration* mStartup;
|
||||
Declaration* mByteCodes[128];
|
||||
|
||||
DeclarationScope* mRuntimeScope;
|
||||
|
||||
bool AddUnit(Location & location, const char* name, const char * from);
|
||||
CompilationUnit* PendingUnit(void);
|
||||
protected:
|
||||
|
|
|
@ -120,6 +120,45 @@ bool Compiler::GenerateCode(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Compile used runtime functions
|
||||
|
||||
for (int i = 0; i < mByteCodeGenerator->mRelocations.Size(); i++)
|
||||
{
|
||||
if (mByteCodeGenerator->mRelocations[i].mRuntime)
|
||||
{
|
||||
Declaration* bcdec = mCompilationUnits->mRuntimeScope->Lookup(Ident::Unique(mByteCodeGenerator->mRelocations[i].mRuntime));
|
||||
if (bcdec)
|
||||
{
|
||||
int index = -1, offset = 0;
|
||||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||
{
|
||||
if (bcdec->mVarIndex < 0)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue);
|
||||
index = bcdec->mVarIndex;
|
||||
}
|
||||
else if (bcdec->mType == DT_LABEL)
|
||||
{
|
||||
if (bcdec->mBase->mVarIndex < 0)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue);
|
||||
index = bcdec->mBase->mVarIndex;
|
||||
offset = bcdec->mInteger;
|
||||
}
|
||||
|
||||
assert(index > 0);
|
||||
mInterCodeModule->UseGlobal(index);
|
||||
|
||||
mByteCodeGenerator->mRelocations[i].mIndex = index;
|
||||
mByteCodeGenerator->mRelocations[i].mOffset = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
mErrors->Error(loc, "Missing runtime code implementation", mByteCodeGenerator->mRelocations[i].mRuntime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compile used byte code functions
|
||||
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (mByteCodeGenerator->mByteCodeUsed[i])
|
||||
|
@ -152,8 +191,15 @@ bool Compiler::GenerateCode(void)
|
|||
rel.mUpper = true;
|
||||
rel.mIndex = index;
|
||||
rel.mOffset = offset;
|
||||
rel.mRuntime = nullptr;
|
||||
mByteCodeGenerator->mRelocations.Push(rel);
|
||||
}
|
||||
else
|
||||
{
|
||||
char n[10];
|
||||
sprintf_s(n, "%d", i);
|
||||
mErrors->Error(loc, "Missing byte code implementation", n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +223,7 @@ bool Compiler::GenerateCode(void)
|
|||
rel.mUpper = ref.mUpper;
|
||||
rel.mIndex = ref.mIndex;
|
||||
rel.mOffset = ref.mOffset;
|
||||
rel.mRuntime = nullptr;
|
||||
mByteCodeGenerator->mRelocations.Push(rel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ typedef signed char int8;
|
|||
typedef signed short int16;
|
||||
typedef signed short int32;
|
||||
|
||||
static const uint8 BC_REG_WORK = 0x03;
|
||||
static const uint8 BC_REG_IP = 0x19;
|
||||
static const uint8 BC_REG_ACCU = 0x1b;
|
||||
static const uint8 BC_REG_ADDR = 0x1f;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,12 +10,14 @@ class NativeCodeInstruction
|
|||
{
|
||||
public:
|
||||
NativeCodeInstruction(AsmInsType type = ASMIT_INV, AsmInsMode mode = ASMIM_IMPLIED, int address = 0, int varIndex = -1, bool lower = true, bool upper = true);
|
||||
NativeCodeInstruction(const char* runtime);
|
||||
|
||||
AsmInsType mType;
|
||||
AsmInsMode mMode;
|
||||
|
||||
int mAddress, mVarIndex;
|
||||
bool mLower, mUpper;
|
||||
const char * mRuntime;
|
||||
|
||||
void Assemble(NativeCodeBasicBlock* block);
|
||||
};
|
||||
|
@ -46,17 +48,18 @@ public:
|
|||
|
||||
void CopyCode(NativeCodeProcedure* proc, uint8* target);
|
||||
void Assemble(void);
|
||||
void Compile(InterCodeProcedure* iproc, NativeCodeProcedure* proc, InterCodeBasicBlock* block);
|
||||
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
|
||||
|
||||
void PutByte(uint8 code);
|
||||
void PutWord(uint16 code);
|
||||
|
||||
void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction& ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh);
|
||||
|
||||
void LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
void StoreValue(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
void LoadValue(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
void LoadStoreValue(InterCodeProcedure* proc, const InterInstruction& rins, const InterInstruction& wins);
|
||||
void BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
void BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction* sins1, const InterInstruction* sins0);
|
||||
void UnaryOperator(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
void RelationalOperator(InterCodeProcedure* proc, const InterInstruction& ins, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
|
||||
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins);
|
||||
|
@ -73,12 +76,17 @@ class NativeCodeProcedure
|
|||
|
||||
int mProgStart, mProgSize, mIndex;
|
||||
bool mNoFrame;
|
||||
int mTempBlocks;
|
||||
|
||||
GrowingArray<ByteCodeRelocation> mRelocations;
|
||||
|
||||
void Compile( ByteCodeGenerator * generator, InterCodeProcedure* proc);
|
||||
NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block);
|
||||
NativeCodeBasicBlock* AllocateBlock(void);
|
||||
NativeCodeBasicBlock* TransientBlock(void);
|
||||
|
||||
void CompileInterBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* iblock, NativeCodeBasicBlock*block);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2186,6 +2186,56 @@ void Parser::ParsePragma(void)
|
|||
}
|
||||
ConsumeToken(TK_CLOSE_PARENTHESIS);
|
||||
}
|
||||
else if (!strcmp(mScanner->mTokenIdent->mString, "runtime"))
|
||||
{
|
||||
mScanner->NextToken();
|
||||
ConsumeToken(TK_OPEN_PARENTHESIS);
|
||||
const Ident* rtident = nullptr;
|
||||
|
||||
if (mScanner->mToken == TK_IDENT)
|
||||
{
|
||||
rtident = mScanner->mTokenIdent;
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, "Identifier expected");
|
||||
|
||||
ConsumeToken(TK_COMMA);
|
||||
if (mScanner->mToken == TK_IDENT)
|
||||
{
|
||||
Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent);
|
||||
if (dec && dec->mType == DT_CONST_ASSEMBLER)
|
||||
{
|
||||
mScanner->NextToken();
|
||||
if (ConsumeTokenIf(TK_DOT))
|
||||
{
|
||||
if (mScanner->mToken == TK_IDENT)
|
||||
{
|
||||
Declaration* ndec = dec->mBase->mScope->Lookup(mScanner->mTokenIdent);
|
||||
if (ndec)
|
||||
dec = ndec;
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, "Label not found in assembler code");
|
||||
mScanner->NextToken();
|
||||
}
|
||||
else
|
||||
mErrors->Error(mScanner->mLocation, "Identifier expected");
|
||||
}
|
||||
|
||||
if (rtident)
|
||||
{
|
||||
mCompilationUnits->mRuntimeScope->Insert(rtident, dec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mErrors->Error(mScanner->mLocation, "Runtime function not found");
|
||||
mScanner->NextToken();
|
||||
}
|
||||
|
||||
}
|
||||
ConsumeToken(TK_CLOSE_PARENTHESIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
mScanner->NextToken();
|
||||
|
|
Loading…
Reference in New Issue