From 93b6aca8a3b6a6c74eff5a42c1be99a66c49efab Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 11 Sep 2021 15:01:32 +0200 Subject: [PATCH] More native code generator --- README.md | 13 +- autotest/autotest.bat | 3 + autotest/bitshifttest.c | 94 ++++ autotest/floatstringtest.c | 25 + include/crt.c | 36 ++ include/crt.h | 4 +- include/math.c | 2 +- include/stdlib.c | 85 +++ include/stdlib.h | 2 + oscar64/ByteCodeGenerator.cpp | 25 +- oscar64/ByteCodeGenerator.h | 4 +- oscar64/Compiler.cpp | 8 +- oscar64/InterCode.cpp | 4 + oscar64/InterCodeGenerator.cpp | 56 +- oscar64/InterCodeGenerator.h | 2 +- oscar64/NativeCodeGenerator.cpp | 865 ++++++++++++++++++++++++++----- oscar64/NativeCodeGenerator.h | 15 +- oscar64/Parser.cpp | 12 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 14 +- 20 files changed, 1083 insertions(+), 194 deletions(-) create mode 100644 autotest/bitshifttest.c create mode 100644 autotest/floatstringtest.c diff --git a/README.md b/README.md index 48f6827..0fc4f9b 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ The first release of the compiler is severely limited considering it is only two * Missing livetime reduction of intermediates * No block domination analysis * No register use for arguments +* Auto variables places on fixed stack for known call sequence ### Intermediate code generation @@ -59,7 +60,8 @@ The first release of the compiler is severely limited considering it is only two ### Native code generation -* Missing +* Calling non native functions missing +* More byte operation optimisation required ## Implementation Details @@ -109,6 +111,15 @@ The intermediate code generator assumes a large number of registers so the zero * **0x43-0x52** caller saved registers * **0x53-0x8f** callee saved registers +Routines can be marked to be compiled to 6502 machine code with the native pragma: + + void Plot(int x, int y) + { + (*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7); + } + + #pragma native(Plot) + diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 874bcea..9523364 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -39,6 +39,9 @@ if %errorlevel% neq 0 goto :error ..\release\oscar64 -i=../include -rt=../include/crt.c -e testint16cmp.c if %errorlevel% neq 0 goto :error +..\release\oscar64 -i=../include -rt=../include/crt.c -e floatstringtest.c +if %errorlevel% neq 0 goto :error + exit /b 0 :error echo Failed with error #%errorlevel%. diff --git a/autotest/bitshifttest.c b/autotest/bitshifttest.c new file mode 100644 index 0000000..38f8a77 --- /dev/null +++ b/autotest/bitshifttest.c @@ -0,0 +1,94 @@ +#include + +unsigned shl1b(int n) +{ + return 1 << n; +} + +unsigned shl1n(int n) +{ + return 1 << n; +} + +#pragma native(shl1n) + +unsigned shr1b(int n) +{ + return 0x8000 >> n; +} + +unsigned shr1n(int n) +{ + return 0x8000 >> n; +} + +#pragma native(shr1n) + +unsigned shl4b(int n) +{ + return 0x0010 << n; +} + +unsigned shl4n(int n) +{ + return 0x0010 << n; +} + +#pragma native(shl4n) + +unsigned shr4b(int n) +{ + return 0x0800 >> n; +} + +unsigned shr4n(int n) +{ + return 0x0800 >> n; +} + +#pragma native(shr4n) + + +unsigned shl8b(int n) +{ + return 0x0100 << n; +} + +unsigned shl8n(int n) +{ + return 0x0100 << n; +} + +#pragma native(shl8n) + +unsigned shr8b(int n) +{ + return 0x0080 >> n; +} + +unsigned shr8n(int n) +{ + return 0x0080 >> n; +} + +#pragma native(shr8n) + +int main(void) +{ + for(int i=0; i<32; i++) + { + printf("1: %.4x : %.4x | %.4x : %.4x\n", shl1b(i), shl1n(i), shr1b(i), shr1n(i)); + } + + for(int i=0; i<32; i++) + { + printf("4: %.4x : %.4x | %.4x : %.4x\n", shl4b(i), shl4n(i), shr4b(i), shr4n(i)); + } + + for(int i=0; i<32; i++) + { + printf("8: %.4x : %.4x | %.4x : %.4x\n", shl8b(i), shl8n(i), shr8b(i), shr8n(i)); + } + + return 0; +} diff --git a/autotest/floatstringtest.c b/autotest/floatstringtest.c new file mode 100644 index 0000000..6cd20a3 --- /dev/null +++ b/autotest/floatstringtest.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int main(void) +{ + float x = 1.0, y = 1.0; + + char xb[20], yb[20]; + for(int i=0; i<40; i++) + { + ftoa(x, xb); float xr = atof(xb); + ftoa(y, yb); float yr = atof(yb); + +// printf("%20g (%s) %20g : %20g (%s) %20g : %10f %10f \n", x, xb, xr, y, yb, y, fabs(x - xr) / x, fabs(y - yr) / y); + + if (fabs(x - xr) / x > 0.00001 || fabs(y - yr) / y > 0.00001) + return -1; + + x *= 2.5; + y *= 0.8; + } + + return 0; +} diff --git a/include/crt.c b/include/crt.c index 0613c56..5355904 100644 --- a/include/crt.c +++ b/include/crt.c @@ -294,6 +294,30 @@ P1: jmp startup.exec } #pragma bytecode(BC_JSR, inp_jsr) + +__asm inp_native +{ + tya + clc + adc ip + sta P1 + 1 + lda ip + 1 + adc #0 + sta P1 + 2 +P1: + jsr $0000 + + ldy #0 + lda (sp), y + sta ip + iny + lda (sp), y + sta ip + 1 + dey + jmp startup.exec +} + +#pragma bytecode(BC_NATIVE, inp_native) __asm inp_const_p8 { @@ -2532,6 +2556,18 @@ __asm inp_op_abs_f32 unsigned char ubitmask[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; +unsigned char bitshift[56] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#pragma runtime(bitshift, bitshift) + __asm fround { ffloor: bit accu + 3 diff --git a/include/crt.h b/include/crt.h index 5483cdc..c173e41 100644 --- a/include/crt.h +++ b/include/crt.h @@ -145,7 +145,9 @@ enum ByteCode BC_JSR, BC_COPY, - BC_COPY_LONG + BC_COPY_LONG, + + BC_NATIVE = 0x75 }; #pragma compile("crt.c") diff --git a/include/math.c b/include/math.c index fcda6ef..64aa9ca 100644 --- a/include/math.c +++ b/include/math.c @@ -176,7 +176,7 @@ float log10(float f) float pow(float p, float q) { - return exp(p * log(q)); + return exp(q * log(p)); } float sqrt(float f) diff --git a/include/stdlib.c b/include/stdlib.c index ec1ff19..0370209 100644 --- a/include/stdlib.c +++ b/include/stdlib.c @@ -1,6 +1,7 @@ #include "stdlib.h" #include "string.h" #include "stdio.h" +#include "math.h" void itoa(int n, char * s, int radix) { @@ -164,6 +165,90 @@ int atoi(const char * s) return v; } +const float tpow10[7] = {1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0}; + +float atof(const char * s) +{ + char c; + while ((c = *s++) <= ' ') + if (!c) return 0; + + bool neg = false; + if (c == '-') + { + neg = true; + c = *s++; + } + else if (c == '+') + c = *s++; + + float v = 0; + while (c >= '0' && c <= '9') + { + v = v * 10 + (c - '0'); + c = *s++; + } + + if (c == '.') + { + float d = 1.0; + c = *s++; + while (c >= '0' && c <= '9') + { + v = v * 10 + (c - '0'); + d = d * 10; + c = *s++; + } + + v /= d; + } + + if (c == 'e' || c == 'E') + { + c = *s++; + bool eneg = false; + if (c == '-') + { + eneg = true; + c = *s++; + } + else if (c == '+') + c = *s++; + + int e = 0; + while (c >= '0' && c <= '9') + { + e = e * 10 + (c - '0'); + c = *s++; + } + + if (eneg) + { + while (e > 6) + { + v /= 1000000.0; + e -= 6; + } + v /= tpow10[e]; + } + else + { + while (e > 6) + { + v *= 1000000.0; + e -= 6; + } + v *= tpow10[e]; + } + + } + + if (neg) + v = -v; + + return v; +} + void exit(int status) { __asm { diff --git a/include/stdlib.h b/include/stdlib.h index 8074ef4..444a626 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -9,6 +9,8 @@ void ftoa(float f, char * s); int atoi(const char * s); +float atof(const char * s); + void exit(int status); void * malloc(unsigned int size); diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 0efad35..ee18d54 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -1556,6 +1556,7 @@ void ByteCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInst bins.mRelocate = true; bins.mVIndex = ins.mVarIndex; bins.mFunction = ins.mMemory == IM_PROCEDURE; + bins.mValue = ins.mSIntConst[0]; mIns.Push(bins); } @@ -3546,51 +3547,51 @@ void ByteCodeGenerator::WriteAsmFile(FILE * file, Address & addr) switch (d.mMode) { case ASMIM_IMPLIED: - fprintf(file, "%04x : %02x __ __ %s\n", iip, mMemory[ip], AsmInstructionNames[d.mType]); + fprintf(file, "%04x : %02x __ __ %s\n", iip, mMemory[iip], AsmInstructionNames[d.mType]); break; case ASMIM_IMMEDIATE: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s #$%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s #$%02x\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE_X: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s $%02x,x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s $%02x,x\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ZERO_PAGE_Y: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s $%02x,y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s $%02x,y\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_ABSOLUTE: addr = mMemory[ip] + 256 * mMemory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x %02x %s $%04x\n", iip, mMemory[iip], mMemory[iip + 1], mMemory[iip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_ABSOLUTE_X: addr = mMemory[ip] + 256 * mMemory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x,x\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x %02x %s $%04x,x\n", iip, mMemory[iip], mMemory[iip + 1], mMemory[iip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_ABSOLUTE_Y: addr = mMemory[ip] + 256 * mMemory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x,y\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x %02x %s $%04x,y\n", iip, mMemory[iip], mMemory[iip + 1], mMemory[iip + 2], AsmInstructionNames[d.mType], addr); ip += 2; break; case ASMIM_INDIRECT: addr = mMemory[ip] + 256 * mMemory[ip + 1]; ip += 2; - fprintf(file, "%04x : %02x %02x %02x %s ($%04x)\n", iip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x %02x %s ($%04x)\n", iip, mMemory[iip], mMemory[iip + 1], mMemory[iip + 2], AsmInstructionNames[d.mType], addr); break; case ASMIM_INDIRECT_X: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s ($%02x,x)\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s ($%02x,x)\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_INDIRECT_Y: addr = mMemory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s ($%02x),y\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s ($%02x),y\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; case ASMIM_RELATIVE: addr = mMemory[ip++]; @@ -3598,7 +3599,7 @@ void ByteCodeGenerator::WriteAsmFile(FILE * file, Address & addr) addr = addr + ip - 256; else addr = addr + ip; - fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr); + fprintf(file, "%04x : %02x %02x __ %s $%02x\n", iip, mMemory[iip], mMemory[iip + 1], AsmInstructionNames[d.mType], addr); break; } } diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index 66e5eea..95048e2 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -134,7 +134,9 @@ enum ByteCode BC_JSR, BC_COPY, - BC_COPY_LONG + BC_COPY_LONG, + + BC_NATIVE = 0x75 }; class ByteCodeProcedure; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 162404d..e8e42a1 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -143,7 +143,13 @@ bool Compiler::GenerateCode(void) index = bcdec->mBase->mVarIndex; offset = bcdec->mInteger; } - + else if (bcdec->mType == DT_VARIABLE) + { + if (bcdec->mBase->mVarIndex < 0) + mInterCodeGenerator->InitGlobalVariable(mInterCodeModule, bcdec); + index = bcdec->mVarIndex; + offset = bcdec->mOffset + mByteCodeGenerator->mRelocations[i].mOffset; + } assert(index > 0); mInterCodeModule->UseGlobal(index); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 690a38e..e5f81e2 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1593,6 +1593,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction& ins, const GrowingIn ins.mMemory = tvalue[ins.mSTemp[0]]->mMemory; ins.mVarIndex = tvalue[ins.mSTemp[0]]->mVarIndex; ins.mOperandSize = tvalue[ins.mSTemp[0]]->mOperandSize; + ins.mSIntConst[0] = tvalue[ins.mSTemp[0]]->mIntValue; ins.mSTemp[0] = -1; } @@ -2708,6 +2709,9 @@ static bool CanBypassStore(const InterInstruction& sins, const InterInstruction& return false; } + if (sins.mMemory == IM_FRAME && (bins.mCode == IC_PUSH_FRAME || bins.mCode == IC_POP_FRAME)) + return false; + // Side effects if (bins.mCode == IC_CALL || bins.mCode == IC_JSR) return false; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index ef20108..3bcd2bb 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -341,9 +341,17 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins.mTType = InterTypeOf(dec->mBase); ins.mTTemp = proc->AddTemporary(ins.mTType); if (ins.mTType == IT_SIGNED) + { + if (dec->mInteger < -32768 || dec->mInteger > 32767) + mErrors->Warning(dec->mLocation, "Integer constant truncated"); ins.mIntValue = short(dec->mInteger); + } else + { + if (dec->mInteger < 0 || dec->mInteger > 65535) + mErrors->Warning(dec->mLocation, "Unsigned integer constant truncated"); ins.mIntValue = unsigned short(dec->mInteger); + } block->Append(ins); return ExValue(dec->mBase, ins.mTTemp); @@ -597,32 +605,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - if (vll.mType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_FLOAT2INT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = InterTypeOf(vll.mType); - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheSignedIntTypeDeclaration; - block->Append(cins); - } - else if (vll.mType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) - { - InterInstruction cins; - cins.mCode = IC_CONVERSION_OPERATOR; - cins.mOperator = IA_INT2FLOAT; - cins.mSType[0] = InterTypeOf(vr.mType); - cins.mSTemp[0] = vr.mTemp; - cins.mTType = InterTypeOf(vll.mType);; - cins.mTTemp = proc->AddTemporary(cins.mTType); - vr.mTemp = cins.mTTemp; - vr.mType = TheFloatTypeDeclaration; - block->Append(cins); - } + vr = CoerceType(proc, block, vr, vll.mType); InterInstruction oins; oins.mCode = IC_BINARY_OPERATOR; @@ -1406,7 +1389,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLocation, "Not enough arguments for function call"); InterInstruction cins; - if (exp->mLeft->mDecValue->mFlags & DTF_NATIVE) + if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mFlags & DTF_NATIVE) cins.mCode = IC_JSR; else cins.mCode = IC_CALL; @@ -2139,10 +2122,27 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int __int64 t = cast.i; for (int i = 0; i < 4; i++) { - dp[i] = t & 0xff; + dp[offset + i] = t & 0xff; t >>= 8; } } + else if (data->mType == DT_CONST_FUNCTION) + { + if (data->mVarIndex < 0) + { + InterCodeProcedure* cproc = this->TranslateProcedure(mod, data->mValue, data); + cproc->ReduceTemporaries(); + } + + InterVariable::Reference ref; + ref.mAddr = offset; + ref.mLower = true; + ref.mUpper = true; + ref.mFunction = true; + ref.mIndex = data->mVarIndex; + ref.mOffset = 0; + references.Push(ref); + } else if (data->mType == DT_CONST_POINTER) { Expression* exp = data->mValue; diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index dc9082a..68af623 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -22,6 +22,7 @@ public: InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec); void TranslateAssembler(InterCodeModule* mod, Expression * exp); + void InitGlobalVariable(InterCodeModule* mod, Declaration* dec); protected: Errors* mErrors; @@ -30,7 +31,6 @@ protected: ExValue CoerceType(InterCodeProcedure* proc, InterCodeBasicBlock*& block, ExValue v, Declaration * type); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp); - void InitGlobalVariable(InterCodeModule* mod, Declaration* dec); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, GrowingArray & references); }; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index cd1114d..d6ce189 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -37,11 +37,15 @@ void NativeRegisterDataSet::ResetZeroPage(int addr) } NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, int address, int varIndex, bool lower, bool upper) - : mType(type), mMode(mode), mAddress(address), mVarIndex(varIndex), mLower(lower), mUpper(upper), mRuntime(nullptr) + : mType(type), mMode(mode), mAddress(address), mVarIndex(varIndex), mLower(lower), mUpper(upper), mRuntime(nullptr), mFunction(false) {} NativeCodeInstruction::NativeCodeInstruction(const char* runtime) - : mType(ASMIT_JSR), mMode(ASMIM_ABSOLUTE), mAddress(0), mVarIndex(0), mLower(true), mUpper(true), mRuntime(runtime) + : mType(ASMIT_JSR), mMode(ASMIM_ABSOLUTE), mAddress(0), mVarIndex(0), mLower(true), mUpper(true), mRuntime(runtime), mFunction(false) +{} + +NativeCodeInstruction::NativeCodeInstruction(AsmInsType type, AsmInsMode mode, const char* runtime, int address, bool lower, bool upper) + : mType(type), mMode(mode), mAddress(address), mVarIndex(0), mLower(lower), mUpper(upper), mRuntime(runtime), mFunction(false) {} bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) @@ -80,6 +84,9 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) return true; } + if (mType == ASMIT_BYTE) + return true; + // check side effects switch (mType) @@ -399,6 +406,20 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) return false; } +bool NativeCodeInstruction::LoadsAccu(void) const +{ + return mType == ASMIT_LDA || mType == ASMIT_TXA || mType == ASMIT_TYA || mType == ASMIT_JSR; +} + +bool NativeCodeInstruction::ChangesAddress(void) const +{ + if (mMode != ASMIM_IMPLIED) + return mType == ASMIT_INC || mType == ASMIT_DEC || mType == ASMIT_ASL || mType == ASMIT_LSR || mType == ASMIT_ROL || mType == ASMIT_ROR; + else + return false; +} + + bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) { bool changed = false; @@ -532,6 +553,12 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) mMode = ASMIM_IMMEDIATE; changed = true; } + else if (data.mRegs[mAddress].mZeroPage) + { + data.mRegs[CPU_REG_A] = data.mRegs[mAddress]; + mAddress = data.mRegs[CPU_REG_A].mValue; + changed = true; + } else { data.mRegs[CPU_REG_A].Reset(); @@ -606,6 +633,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) } break; + case ASMIT_ADC: + case ASMIT_SBC: + case ASMIT_AND: + case ASMIT_ORA: + case ASMIT_EOR: + case ASMIT_CMP: + case ASMIT_CPX: + case ASMIT_CPY: + if (data.mRegs[mAddress].mImmediate) + { + mAddress = data.mRegs[mAddress].mValue; + mMode = ASMIM_IMMEDIATE; + changed = true; + } + else if (data.mRegs[mAddress].mZeroPage) + { + mAddress = data.mRegs[mAddress].mValue; + changed = true; + } + break; + case ASMIT_STA: data.ResetZeroPage(mAddress); if (data.mRegs[CPU_REG_A].mImmediate) @@ -613,6 +661,11 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data) data.mRegs[mAddress].mImmediate = true; data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue; } + else if (data.mRegs[CPU_REG_A].mZeroPage) + { + data.mRegs[mAddress].mZeroPage = true; + data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue; + } else { data.mRegs[CPU_REG_A].mZeroPage = true; @@ -903,76 +956,81 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet& void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block) { - block->PutByte(AsmInsOpcodes[mType][mMode]); - - switch (mMode) + if (mType == ASMIT_BYTE) + block->PutByte(mAddress); + else { - case ASMIM_IMPLIED: - break; - case ASMIM_ZERO_PAGE: - case ASMIM_ZERO_PAGE_X: - case ASMIM_ZERO_PAGE_Y: - case ASMIM_INDIRECT_X: - case ASMIM_INDIRECT_Y: - block->PutByte(uint8(mAddress)); - break; - case ASMIM_IMMEDIATE: - if (mVarIndex != -1) + block->PutByte(AsmInsOpcodes[mType][mMode]); + + switch (mMode) { - ByteCodeRelocation rl; - rl.mAddr = block->mCode.Size(); - rl.mFunction = false; - rl.mLower = mLower; - rl.mUpper = mUpper; - rl.mIndex = mVarIndex; - rl.mOffset = mAddress; - rl.mRuntime = nullptr; - block->mRelocations.Push(rl); - block->PutByte(0); + case ASMIM_IMPLIED: + break; + case ASMIM_ZERO_PAGE: + case ASMIM_ZERO_PAGE_X: + case ASMIM_ZERO_PAGE_Y: + case ASMIM_INDIRECT_X: + case ASMIM_INDIRECT_Y: + block->PutByte(uint8(mAddress)); + break; + case ASMIM_IMMEDIATE: + if (mVarIndex != -1) + { + ByteCodeRelocation rl; + rl.mAddr = block->mCode.Size(); + rl.mFunction = false; + rl.mLower = mLower; + rl.mUpper = mUpper; + rl.mIndex = mVarIndex; + rl.mOffset = mAddress; + rl.mRuntime = nullptr; + block->mRelocations.Push(rl); + block->PutByte(0); + } + else + { + block->PutByte(uint16(mAddress)); + } + break; + case ASMIM_ABSOLUTE: + case ASMIM_INDIRECT: + case ASMIM_ABSOLUTE_X: + case ASMIM_ABSOLUTE_Y: + if (mRuntime) + { + ByteCodeRelocation rl; + rl.mAddr = block->mCode.Size(); + rl.mFunction = mFunction; + rl.mLower = true; + rl.mUpper = true; + rl.mIndex = -1; + rl.mOffset = mAddress; + rl.mRuntime = mRuntime; + block->mRelocations.Push(rl); + block->PutWord(0); + } + else if (mVarIndex != -1) + { + ByteCodeRelocation rl; + rl.mAddr = block->mCode.Size(); + rl.mFunction = mFunction;; + rl.mLower = true; + rl.mUpper = true; + rl.mIndex = mVarIndex; + rl.mOffset = mAddress; + rl.mRuntime = nullptr; + block->mRelocations.Push(rl); + block->PutWord(0); + } + else + { + block->PutWord(uint16(mAddress)); + } + break; + case ASMIM_RELATIVE: + block->PutByte(uint8(mAddress)); + break; } - else - { - block->PutByte(uint16(mAddress)); - } - break; - case ASMIM_ABSOLUTE: - case ASMIM_INDIRECT: - case ASMIM_ABSOLUTE_X: - case ASMIM_ABSOLUTE_Y: - if (mRuntime) - { - ByteCodeRelocation rl; - rl.mAddr = block->mCode.Size(); - rl.mFunction = false; - rl.mLower = true; - rl.mUpper = true; - rl.mIndex = -1; - rl.mOffset = 0; - rl.mRuntime = mRuntime; - block->mRelocations.Push(rl); - block->PutWord(0); - } - else if (mVarIndex != - 1) - { - ByteCodeRelocation rl; - rl.mAddr = block->mCode.Size(); - rl.mFunction = false; - rl.mLower = true; - rl.mUpper = true; - rl.mIndex = mVarIndex; - rl.mOffset = mAddress; - rl.mRuntime = nullptr; - block->mRelocations.Push(rl); - block->PutWord(0); - } - else - { - block->PutWord(uint16(mAddress)); - } - break; - case ASMIM_RELATIVE: - block->PutByte(uint8(mAddress)); - break; } } @@ -1066,37 +1124,37 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, AsmInsType code, } } -void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins) +void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction & ins, InterType type, int reg) { - if (ins.mTType == IT_FLOAT) + if (type == IT_FLOAT) { union { float f; unsigned int v; } cc; cc.f = ins.mFloatValue; mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 2)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 3)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3)); } - else if (ins.mTType == IT_POINTER) + else if (type == IT_POINTER) { if (ins.mMemory == IM_GLOBAL) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue, ins.mVarIndex, true, false)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue, ins.mVarIndex, false, true)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_ABSOLUTE) { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mIntValue >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_LOCAL || ins.mMemory == IM_PARAM) { @@ -1111,11 +1169,11 @@ void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterIns mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, mNoFrame ? BC_REG_STACK : BC_REG_LOCALS)); if (index != 0) mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, (mNoFrame ? BC_REG_STACK : BC_REG_LOCALS) + 1)); if (index != 0) mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } else if (ins.mMemory == IM_PROCEDURE) { @@ -1124,13 +1182,18 @@ void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterIns else { mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mIntValue & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mIntValue >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } +void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins) +{ + LoadConstantToReg(proc, ins, ins.mTType, BC_REG_TMP + proc->mTempOffset[ins.mTTemp]); +} + void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstruction& ins) { if (ins.mSType[0] == IT_FLOAT) @@ -1187,6 +1250,20 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y,BC_REG_STACK)); } } else @@ -1245,6 +1322,20 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 2)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 3)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } } @@ -1325,6 +1416,14 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } else @@ -1360,6 +1459,14 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } } @@ -1458,6 +1565,14 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } } @@ -1489,6 +1604,11 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } else if (ins.mOperandSize == 2) @@ -1524,6 +1644,14 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr } else if (ins.mMemory == IM_FRAME) { + int index = ins.mVarIndex + ins.mSIntConst[1] + 2; + + mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, index)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); } } } @@ -1922,6 +2050,114 @@ bool NativeCodeBasicBlock::CheckPredAccuStore(int reg) return true; } +void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift) +{ + if (shift == 0) + { + + } + else if (shift == 1) + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, reg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 0)); + for (int i = 0; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, reg + 1)); + } + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0)); + } +} + +int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction* sins, int index, int mul) +{ + if (sins) + LoadValueToReg(proc, *sins, BC_REG_ACCU, nullptr, nullptr); + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[index]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[index]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + + int lshift = 0, lmul = mul; + while (!(lmul & 1)) + { + lmul >>= 1; + lshift++; + } + + switch (lmul) + { + case 1: + ShiftRegisterLeft(proc, BC_REG_ACCU, lshift); + return BC_REG_ACCU; + case 3: + 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_TAY, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_TXA, 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_TYA, ASMIM_IMPLIED)); + 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; + case 5: + 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_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; + default: + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); + + mIns.Push(NativeCodeInstruction("mul16by8")); + + return BC_REG_WORK + 2; + } +} + +static bool IsPowerOf2(unsigned n) +{ + return (n & (n - 1)) == 0; +} + +static int Binlog(unsigned n) +{ + int k = -1; + + while (n) + { + n >>= 1; + k++; + } + + return k; +} void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction * sins1, const InterInstruction * sins0) { int treg = BC_REG_TMP + proc->mTempOffset[ins.mTTemp]; @@ -2215,39 +2451,11 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterI if (ins.mOperator == IA_MUL && ins.mSTemp[1] < 0 && (ins.mSIntConst[1] & ~0xff) == 0) { - if (sins0) - LoadValueToReg(proc, *sins0, BC_REG_ACCU, nullptr, nullptr); - else - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - } - - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); - - mIns.Push(NativeCodeInstruction("mul16by8")); - reg = BC_REG_WORK + 2; + reg = ShortMultiply(proc, ins, sins0, 0, ins.mSIntConst[1] & 0xff); } else if (ins.mOperator == IA_MUL && ins.mSTemp[0] < 0 && (ins.mSIntConst[0] & ~0xff) == 0) { - if (sins1) - LoadValueToReg(proc, *sins1, BC_REG_ACCU, nullptr, nullptr); - else - { - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - } - - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); - - mIns.Push(NativeCodeInstruction("mul16by8")); - reg = BC_REG_WORK + 2; + reg = ShortMultiply(proc, ins, sins1, 1, ins.mSIntConst[0] & 0xff); } else { @@ -2315,6 +2523,9 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterI } break; case IA_SHL: { + if (sins1) LoadValueToReg(proc, *sins1, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]], nullptr, nullptr); + if (sins0) LoadValueToReg(proc, *sins0, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]], nullptr, nullptr); + if (ins.mSTemp[0] < 0) { int shift = ins.mSIntConst[0] & 15; @@ -2356,6 +2567,7 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterI } else { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); } mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); @@ -2367,6 +2579,160 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterI mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } + else if (ins.mSTemp[1] < 0 && IsPowerOf2(ins.mSIntConst[1] & 0xffff)) + { + int l = Binlog(ins.mSIntConst[1] & 0xffff); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + if (l < 8) + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 8 + l)); + else + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + if (ins.mSTemp[1] < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + } + else if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2)); + + mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2))); + + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } break; + case IA_SHR: + { + if (sins1) LoadValueToReg(proc, *sins1, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]], nullptr, nullptr); + if (sins0) LoadValueToReg(proc, *sins0, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]], nullptr, nullptr); + + if (ins.mSTemp[0] < 0) + { + int shift = ins.mSIntConst[0] & 15; + if (shift == 0) + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + } + else if (shift == 1) + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); + } + } + else + { + if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1)); + } + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED)); + for (int i = 1; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED)); + } + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg )); + } + } + else if (ins.mSTemp[1] < 0 && IsPowerOf2(ins.mSIntConst[1] & 0xffff)) + { + int l = Binlog(ins.mSIntConst[1] & 0xffff); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 39 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 47 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); + mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); + mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); + + if (ins.mSTemp[1] < 0) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[1] >> 8) & 0xff)); + } + else if (ins.mSTemp[1] != ins.mTTemp) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]])); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[1]] + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1)); + } + + mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 2 + 1 + 1 + 2)); + + mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -(2 + 1 + 1 + 2))); + + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } break; case IA_SAR: { @@ -2409,23 +2775,31 @@ void NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterI mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } - else if (ins.mSTemp[1] < 0 && ins.mSIntConst[1] < 0x100) + else if (ins.mSTemp[1] < 0 && IsPowerOf2(ins.mSIntConst[1] & 0xffff)) { + int l = Binlog(ins.mSIntConst[1] & 0xffff); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]])); mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[1] & 0xff)); - - mIns.Push(NativeCodeInstruction(ASMIT_CPX, ASMIM_IMMEDIATE, 0x00)); - mIns.Push(NativeCodeInstruction(ASMIT_BEQ, ASMIM_RELATIVE, 4)); - - mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_DEX, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, -4)); - - mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, treg + 1)); + if (l == 15) + { + mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_ABSOLUTE_X, "bitshift", 39 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 47 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 39 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ABSOLUTE_X, "bitshift", 47 - l)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } else { @@ -2815,6 +3189,77 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); } +void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, const InterInstruction& ins) +{ +#if 0 + if (ins.mSTemp[0] < 0) + { + ByteCodeInstruction bins(BC_LEA_ABS); + bins.mRelocate = true; + bins.mFunction = true; + bins.mVIndex = ins.mVarIndex; + bins.mValue = 0; + bins.mRegister = BC_REG_ADDR; + mIns.Push(bins); + } + else + { + ByteCodeInstruction bins(BC_ADDR_REG); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins.mSTemp[0]]; + bins.mRegisterFinal = ins.mSFinal[0]; + mIns.Push(bins); + } + + ByteCodeInstruction cins(BC_CALL); + mIns.Push(cins); + + 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); + } + } +#endif +} + +void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction& ins) +{ + NativeCodeInstruction ains(ASMIT_JSR, ASMIM_ABSOLUTE, ins.mSIntConst[0], ins.mVarIndex, true, true); + ains.mFunction = ins.mMemory == IM_PROCEDURE; + mIns.Push(ains); + + if (ins.mTTemp >= 0) + { + if (ins.mTType == IT_FLOAT) + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 2)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 3)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins.mTTemp] + 1)); + } + } +} + void NativeCodeBasicBlock::BuildLocalRegSets(void) { int i; @@ -2960,6 +3405,35 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void) return changed; } +bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) +{ + int j = at; + while (j > 0 && !((mIns[j - 1].mType == ASMIT_STA || mIns[j - 1].mType == ASMIT_LDA) && mIns[j - 1].mMode == ASMIM_ZERO_PAGE && mIns[j - 1].mAddress == mIns[at].mAddress)) + { + j--; + if ((mIns[j].mMode == ASMIM_ZERO_PAGE || mIns[j].mMode == ASMIM_INDIRECT ) && mIns[j].mAddress == mIns[at + 1].mAddress) + return false; + if (mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress && mIns[j].ChangesAddress()) + return false; + if (mIns[j].mType == ASMIT_JSR) + return false; + } + + if (j > 0 && j < at) + { + for (int i = at; i > j; i--) + { + mIns[i] = mIns[i - 1]; + } + mIns[j] = mIns[at + 1]; + mIns[at + 1].mType = ASMIT_NOP; + + return true; + } + + return false; +} + void NativeCodeBasicBlock::PeepHoleOptimizer(void) { if (!mVisited) @@ -2973,6 +3447,14 @@ void NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i].ValueForwarding(data); } + // move load store pairs 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_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].LoadsAccu()) + MoveLoadStoreUp(i); + } + bool progress = false; do { progress = false; @@ -3033,6 +3515,21 @@ void NativeCodeBasicBlock::PeepHoleOptimizer(void) mIns[i + 1].mType = ASMIT_NOP; progress = true; } + else if (mIns[i].mType == ASMIT_AND && mIns[i + 1].mType == ASMIT_AND && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE) + { + mIns[i].mAddress &= mIns[i + 1].mAddress; + mIns[i + 1].mType = ASMIT_NOP; + } + else if (mIns[i].mType == ASMIT_ORA && mIns[i + 1].mType == ASMIT_ORA && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE) + { + mIns[i].mAddress |= mIns[i + 1].mAddress; + mIns[i + 1].mType = ASMIT_NOP; + } + else if (mIns[i].mType == ASMIT_EOR && mIns[i + 1].mType == ASMIT_EOR && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mMode == ASMIM_IMMEDIATE) + { + mIns[i].mAddress ^= mIns[i + 1].mAddress; + mIns[i + 1].mType = ASMIT_NOP; + } } if (i + 2 < mIns.Size()) @@ -3043,6 +3540,21 @@ void NativeCodeBasicBlock::PeepHoleOptimizer(void) progress = true; } } + + if (i + 4 < mIns.Size()) + { + if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 3].mAddress && + mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_LDA) + { + // Flip arguments of ADC if second parameter in accu at entry + + mIns[i + 3] = mIns[i + 2]; + mIns[i + 3].mType = ASMIT_ADC; + mIns[i + 2].mMode = ASMIM_ZERO_PAGE; + mIns[i + 2].mAddress = mIns[i + 0].mAddress; + } + } } } while (progress); @@ -3337,6 +3849,10 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu entryBlock->mNoFrame = mNoFrame; entryBlock->mIndex = 0; + generator->mByteCodeUsed[BC_NATIVE] = true; + + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, BC_NATIVE * 2)); + if (!mNoFrame) { entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); @@ -3347,15 +3863,18 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (stackExpand >> 8) & 0xff)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); - entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); + + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, tempSave + 2)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS)); - entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); - entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_LOCALS + 1)); @@ -3367,15 +3886,37 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_STACK)); entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BNE, ASMIM_RELATIVE, - 8)); } - } + if (!proc->mLeafProcedure) + { + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + 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_STA, 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, ((proc->mCommonFrameSize + 2) >> 8) & 0xff)); + entryBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + + tblocks[0] = entryBlock; exitBlock = new NativeCodeBasicBlock(); exitBlock->mNoFrame = mNoFrame; mBlocks.Push(exitBlock); + if (!proc->mLeafProcedure) + { + 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_ADC, ASMIM_IMMEDIATE, (proc->mCommonFrameSize + 2) & 0xff)); + 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_ADC, ASMIM_IMMEDIATE, ((proc->mCommonFrameSize + 2) >> 8) & 0xff)); + exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + if (!mNoFrame) { exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, tempSave)); @@ -3412,6 +3953,7 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu CompileInterBlock(proc, proc->mBlocks[0], entryBlock); +#if 1 do { ResetVisited(); @@ -3423,6 +3965,7 @@ void NativeCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedu ResetVisited(); entryBlock->PeepHoleOptimizer(); +#endif entryBlock->Assemble(); @@ -3600,16 +4143,30 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode block->LoadConstant(iproc, ins); break; case IC_CALL: - // CallFunction(iproc, ins); + block->CallFunction(iproc, ins); break; case IC_JSR: - // CallAssembler(iproc, ins); + block->CallAssembler(iproc, ins); break; case IC_PUSH_FRAME: { + block->mIns.Push(NativeCodeInstruction(ASMIT_SEC, ASMIM_IMPLIED)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + block->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, (ins.mIntValue + 2) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_SBC, ASMIM_IMMEDIATE, ((ins.mIntValue + 2) >> 8) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); } break; case IC_POP_FRAME: { + block->mIns.Push(NativeCodeInstruction(ASMIT_CLC, ASMIM_IMPLIED)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + block->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins.mIntValue + 2) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, ((ins.mIntValue + 2) >> 8) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); } break; case IC_RELATIONAL_OPERATOR: @@ -3643,10 +4200,44 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode case IC_RETURN_VALUE: { - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + if (ins.mSTemp[0] < 0) + { + if (ins.mSType[0] == IT_FLOAT) + { + union { float f; unsigned int v; } cc; + cc.f = ins.mSFloatConst[0]; + + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + } + else + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, ins.mSIntConst[0] & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins.mSIntConst[0] >> 8) & 0xff)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + } + else + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]])); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 1)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + if (ins.mSType[0] == IT_FLOAT) + { + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 2)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins.mSTemp[0]] + 3)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3)); + } + } block->Close(exitBlock, nullptr, ASMIT_JMP); return; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index c34e585..66b63d4 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -28,19 +28,23 @@ 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(AsmInsType type, AsmInsMode mode, const char* runtime, int address = 0, bool lower = true, bool upper = true); NativeCodeInstruction(const char* runtime); AsmInsType mType; AsmInsMode mMode; int mAddress, mVarIndex; - bool mLower, mUpper; + bool mLower, mUpper, mFunction; const char * mRuntime; void Assemble(NativeCodeBasicBlock* block); void FilterRegUsage(NumberSet& requiredTemps, NumberSet& providedTemps); bool IsUsedResultInstructions(NumberSet& requiredTemps); bool ValueForwarding(NativeRegisterDataSet& data); + + bool LoadsAccu(void) const; + bool ChangesAddress(void) const; }; class NativeCodeBasicBlock @@ -77,6 +81,7 @@ public: void PutWord(uint16 code); void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction& ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh); + void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction& ins, InterType type, int reg); void LoadConstant(InterCodeProcedure* proc, const InterInstruction& ins); void StoreValue(InterCodeProcedure* proc, const InterInstruction& ins); @@ -88,6 +93,12 @@ public: void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction& ins); void NumericConversion(InterCodeProcedure* proc, const InterInstruction& ins); + void CallAssembler(InterCodeProcedure* proc, const InterInstruction& ins); + void CallFunction(InterCodeProcedure* proc, const InterInstruction& ins); + + void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift); + int ShortMultiply(InterCodeProcedure* proc, const InterInstruction& ins, const InterInstruction* sins, int index, int mul); + bool CheckPredAccuStore(int reg); NumberSet mLocalRequiredRegs, mLocalProvidedRegs; @@ -98,6 +109,8 @@ public: void BuildGlobalProvidedRegSet(NumberSet fromProvidedTemps); bool BuildGlobalRequiredRegSet(NumberSet& fromRequiredTemps); bool RemoveUnusedResultInstructions(void); + + bool MoveLoadStoreUp(int at); }; class NativeCodeProcedure diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 1b714a3..de12cc1 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -804,11 +804,11 @@ Expression* Parser::ParseSimpleExpression(void) break; case TK_INTEGER: dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + dec->mInteger = mScanner->mTokenInteger; if (dec->mInteger < 32768) dec->mBase = TheSignedIntTypeDeclaration; else dec->mBase = TheUnsignedIntTypeDeclaration; - dec->mInteger = mScanner->mTokenInteger; exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = dec; exp->mDecType = dec->mBase; @@ -993,6 +993,8 @@ Expression* Parser::ParsePostfixExpression(void) else mErrors->Error(mScanner->mLocation, "']' expected"); nexp->mDecType = exp->mDecType->mBase; + if (!nexp->mDecType) + nexp->mDecType = TheVoidTypeDeclaration; exp = nexp; } else if (mScanner->mToken == TK_OPEN_PARENTHESIS) @@ -2224,9 +2226,13 @@ void Parser::ParsePragma(void) } if (rtident) - { mCompilationUnits->mRuntimeScope->Insert(rtident, dec); - } + } + else if (dec && dec->mType == DT_VARIABLE && (dec->mFlags & DTF_GLOBAL)) + { + if (rtident) + mCompilationUnits->mRuntimeScope->Insert(rtident, dec); + mScanner->NextToken(); } else { diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 7d845a0..fec06e7 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,23,0 - PRODUCTVERSION 1,0,23,0 + FILEVERSION 1,0,24,0 + PRODUCTVERSION 1,0,24,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.0.23.0" + VALUE "FileVersion", "1.0.24.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.0.23.0" + VALUE "ProductVersion", "1.0.24.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 168647f..ce300b0 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -147,6 +147,14 @@ "PrerequisitesLocation" = "2:1" "Url" = "8:" "ComponentsUrl" = "8:" + "Items" + { + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2" + { + "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)" + "ProductCode" = "8:.NETFramework,Version=v4.7.2" + } + } } } } @@ -496,15 +504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{468390A3-2F63-4CA4-9043-3B1AEEA1852F}" - "PackageCode" = "8:{A55AE2BA-C814-4AD7-BBB6-00042C360D73}" + "ProductCode" = "8:{B20D936B-B9E1-4135-B9AA-8C367043CF71}" + "PackageCode" = "8:{63E1E188-3AB3-4767-B84A-CDB7F9FC9E10}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.0.23" + "ProductVersion" = "8:1.0.24" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"