Loading libacc/acc.cpp +60 −15 Original line number Original line Diff line number Diff line Loading @@ -46,8 +46,11 @@ #define LOG_API(...) do {} while(0) #define LOG_API(...) do {} while(0) // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY #define LOG_STACK(...) do {} while(0) // #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY // #define PROVIDE_TRACE_CODEGEN // #define PROVIDE_TRACE_CODEGEN namespace acc { namespace acc { Loading Loading @@ -399,27 +402,38 @@ class Compiler : public ErrorSink { class ARMCodeGenerator : public CodeGenerator { class ARMCodeGenerator : public CodeGenerator { public: public: ARMCodeGenerator() {} ARMCodeGenerator() {} virtual ~ARMCodeGenerator() {} virtual ~ARMCodeGenerator() {} /* returns address to patch with local variable size /* returns address to patch with local variable size */ */ virtual int functionEntry(int argCount) { virtual int functionEntry(int argCount) { LOG_API("functionEntry(%d);\n", argCount); LOG_API("functionEntry(%d);\n", argCount); mStackUse = 0; // sp -> arg4 arg5 ... // sp -> arg4 arg5 ... // Push our register-based arguments back on the stack // Push our register-based arguments back on the stack if (argCount > 0) { if (argCount > 0) { int regArgCount = argCount <= 4 ? argCount : 4; int regArgCount = argCount <= 4 ? argCount : 4; o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {} o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {} mStackUse += regArgCount * 4; } } // sp -> arg0 arg1 ... // sp -> arg0 arg1 ... o4(0xE92D4800); // stmfd sp!, {fp, lr} o4(0xE92D4800); // stmfd sp!, {fp, lr} mStackUse += 2 * 4; // sp, fp -> oldfp, retadr, arg0 arg1 .... // sp, fp -> oldfp, retadr, arg0 arg1 .... o4(0xE1A0B00D); // mov fp, sp o4(0xE1A0B00D); // mov fp, sp LOG_STACK("functionEntry: %d\n", mStackUse); return o4(0xE24DD000); // sub sp, sp, # <local variables> return o4(0xE24DD000); // sub sp, sp, # <local variables> // We don't know how many local variables we are going to use, // but we will round the allocation up to a multiple of // STACK_ALIGNMENT, so it won't affect the stack alignment. } } virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); // Round local variable size up to a multiple of stack alignment localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) * STACK_ALIGNMENT; // Patch local variable allocation code: // Patch local variable allocation code: if (localVariableSize < 0 || localVariableSize > 255) { if (localVariableSize < 0 || localVariableSize > 255) { error("localVariables out of range: %d", localVariableSize); error("localVariables out of range: %d", localVariableSize); Loading Loading @@ -547,11 +561,6 @@ class Compiler : public ErrorSink { error("Unimplemented op %d\n", op); error("Unimplemented op %d\n", op); break; break; } } #if 0 o(decodeOp(op)); if (op == OP_MOD) o(0x92); /* xchg %edx, %eax */ #endif } } virtual void clearR1() { virtual void clearR1() { Loading @@ -562,11 +571,15 @@ class Compiler : public ErrorSink { virtual void pushR0() { virtual void pushR0() { LOG_API("pushR0();\n"); LOG_API("pushR0();\n"); o4(0xE92D0001); // stmfd sp!,{r0} o4(0xE92D0001); // stmfd sp!,{r0} mStackUse += 4; LOG_STACK("pushR0: %d\n", mStackUse); } } virtual void popR1() { virtual void popR1() { LOG_API("popR1();\n"); LOG_API("popR1();\n"); o4(0xE8BD0002); // ldmfd sp!,{r1} o4(0xE8BD0002); // ldmfd sp!,{r1} mStackUse -= 4; LOG_STACK("popR1: %d\n", mStackUse); } } virtual void storeR0ToR1(bool isInt) { virtual void storeR0ToR1(bool isInt) { Loading Loading @@ -690,15 +703,31 @@ class Compiler : public ErrorSink { virtual void endFunctionCallArguments(int a, int l) { virtual void endFunctionCallArguments(int a, int l) { LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l); LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l); if (l < 0 || l > 0x3FC) { error("L out of range for stack adjustment: 0x%08x", l); } * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 int argCount = l >> 2; int argCount = l >> 2; int argumentStackUse = l; if (argCount > 0) { if (argCount > 0) { int regArgCount = argCount > 4 ? 4 : argCount; int regArgCount = argCount > 4 ? 4 : argCount; argumentStackUse -= regArgCount * 4; o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} } } mStackUse += argumentStackUse; // Align stack. int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT) * STACK_ALIGNMENT); mStackAlignmentAdjustment = 0; if (missalignment > 0) { mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment; } l += mStackAlignmentAdjustment; if (l < 0 || l > 0x3FC) { error("L out of range for stack adjustment: 0x%08x", l); } * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 mStackUse += mStackAlignmentAdjustment; LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n", mStackUse, mStackAlignmentAdjustment); } } virtual int callForward(int symbol) { virtual int callForward(int symbol) { Loading Loading @@ -727,7 +756,7 @@ class Compiler : public ErrorSink { LOG_API("callIndirect(%d);\n", l); LOG_API("callIndirect(%d);\n", l); int argCount = l >> 2; int argCount = l >> 2; int poppedArgs = argCount > 4 ? 4 : argCount; int poppedArgs = argCount > 4 ? 4 : argCount; int adjustedL = l - (poppedArgs << 2); int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment; if (adjustedL < 0 || adjustedL > 4096-4) { if (adjustedL < 0 || adjustedL > 4096-4) { error("l out of range for stack offset: 0x%08x", l); error("l out of range for stack offset: 0x%08x", l); } } Loading @@ -739,12 +768,15 @@ class Compiler : public ErrorSink { LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect); LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect); int argCount = l >> 2; int argCount = l >> 2; int stackArgs = argCount > 4 ? argCount - 4 : 0; int stackArgs = argCount > 4 ? argCount - 4 : 0; int stackUse = stackArgs + (isIndirect ? 1 : 0); int stackUse = stackArgs + (isIndirect ? 1 : 0) + (mStackAlignmentAdjustment >> 2); if (stackUse) { if (stackUse) { if (stackUse < 0 || stackUse > 255) { if (stackUse < 0 || stackUse > 255) { error("L out of range for stack adjustment: 0x%08x", l); error("L out of range for stack adjustment: 0x%08x", l); } } o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 mStackUse -= stackUse * 4; LOG_STACK("adjustStackAfterCall: %d\n", mStackUse); } } } } Loading Loading @@ -858,6 +890,13 @@ class Compiler : public ErrorSink { static int runtime_MOD(int a, int b) { static int runtime_MOD(int a, int b) { return b % a; return b % a; } } static const int STACK_ALIGNMENT = 8; int mStackUse; // This variable holds the amount we adjusted the stack in the most // recent endFunctionCallArguments call. It's examined by the // following adjustStackAfterCall call. int mStackAlignmentAdjustment; }; }; #endif // PROVIDE_ARM_CODEGEN #endif // PROVIDE_ARM_CODEGEN Loading Loading @@ -981,8 +1020,10 @@ class Compiler : public ErrorSink { if (isIndirect) { if (isIndirect) { l += 4; l += 4; } } if (l > 0) { oad(0xc481, l); /* add $xxx, %esp */ oad(0xc481, l); /* add $xxx, %esp */ } } } virtual int jumpOffset() { virtual int jumpOffset() { return 5; return 5; Loading Loading @@ -2315,7 +2356,6 @@ class Compiler : public ErrorSink { } else { } else { pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset()); pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset()); } } if (l | (n == 1)) pGen->adjustStackAfterCall(l, n == 1); pGen->adjustStackAfterCall(l, n == 1); } } } } Loading Loading @@ -3025,6 +3065,11 @@ void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, script->compiler.getPragmas(actualStringCount, maxStringCount, strings); script->compiler.getPragmas(actualStringCount, maxStringCount, strings); } } extern "C" void accDisassemble(ACCscript* script) { script->compiler.disassemble(stderr); } } // namespace acc } // namespace acc libacc/tests/main.cpp +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,11 @@ int run(MainPtr mainFunc, int argc, char** argv) { return mainFunc(argc, argv); return mainFunc(argc, argv); } } // Private API for development: extern "C" void accDisassemble(ACCscript* script); int main(int argc, char** argv) { int main(int argc, char** argv) { const char* inFile = NULL; const char* inFile = NULL; bool printListing; bool printListing; Loading Loading @@ -109,6 +114,10 @@ int main(int argc, char** argv) { } } } } if (printListing) { accDisassemble(script); } if (runResults) { if (runResults) { accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); Loading Loading
libacc/acc.cpp +60 −15 Original line number Original line Diff line number Diff line Loading @@ -46,8 +46,11 @@ #define LOG_API(...) do {} while(0) #define LOG_API(...) do {} while(0) // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY #define LOG_STACK(...) do {} while(0) // #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY // #define PROVIDE_TRACE_CODEGEN // #define PROVIDE_TRACE_CODEGEN namespace acc { namespace acc { Loading Loading @@ -399,27 +402,38 @@ class Compiler : public ErrorSink { class ARMCodeGenerator : public CodeGenerator { class ARMCodeGenerator : public CodeGenerator { public: public: ARMCodeGenerator() {} ARMCodeGenerator() {} virtual ~ARMCodeGenerator() {} virtual ~ARMCodeGenerator() {} /* returns address to patch with local variable size /* returns address to patch with local variable size */ */ virtual int functionEntry(int argCount) { virtual int functionEntry(int argCount) { LOG_API("functionEntry(%d);\n", argCount); LOG_API("functionEntry(%d);\n", argCount); mStackUse = 0; // sp -> arg4 arg5 ... // sp -> arg4 arg5 ... // Push our register-based arguments back on the stack // Push our register-based arguments back on the stack if (argCount > 0) { if (argCount > 0) { int regArgCount = argCount <= 4 ? argCount : 4; int regArgCount = argCount <= 4 ? argCount : 4; o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {} o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {} mStackUse += regArgCount * 4; } } // sp -> arg0 arg1 ... // sp -> arg0 arg1 ... o4(0xE92D4800); // stmfd sp!, {fp, lr} o4(0xE92D4800); // stmfd sp!, {fp, lr} mStackUse += 2 * 4; // sp, fp -> oldfp, retadr, arg0 arg1 .... // sp, fp -> oldfp, retadr, arg0 arg1 .... o4(0xE1A0B00D); // mov fp, sp o4(0xE1A0B00D); // mov fp, sp LOG_STACK("functionEntry: %d\n", mStackUse); return o4(0xE24DD000); // sub sp, sp, # <local variables> return o4(0xE24DD000); // sub sp, sp, # <local variables> // We don't know how many local variables we are going to use, // but we will round the allocation up to a multiple of // STACK_ALIGNMENT, so it won't affect the stack alignment. } } virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); // Round local variable size up to a multiple of stack alignment localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) * STACK_ALIGNMENT; // Patch local variable allocation code: // Patch local variable allocation code: if (localVariableSize < 0 || localVariableSize > 255) { if (localVariableSize < 0 || localVariableSize > 255) { error("localVariables out of range: %d", localVariableSize); error("localVariables out of range: %d", localVariableSize); Loading Loading @@ -547,11 +561,6 @@ class Compiler : public ErrorSink { error("Unimplemented op %d\n", op); error("Unimplemented op %d\n", op); break; break; } } #if 0 o(decodeOp(op)); if (op == OP_MOD) o(0x92); /* xchg %edx, %eax */ #endif } } virtual void clearR1() { virtual void clearR1() { Loading @@ -562,11 +571,15 @@ class Compiler : public ErrorSink { virtual void pushR0() { virtual void pushR0() { LOG_API("pushR0();\n"); LOG_API("pushR0();\n"); o4(0xE92D0001); // stmfd sp!,{r0} o4(0xE92D0001); // stmfd sp!,{r0} mStackUse += 4; LOG_STACK("pushR0: %d\n", mStackUse); } } virtual void popR1() { virtual void popR1() { LOG_API("popR1();\n"); LOG_API("popR1();\n"); o4(0xE8BD0002); // ldmfd sp!,{r1} o4(0xE8BD0002); // ldmfd sp!,{r1} mStackUse -= 4; LOG_STACK("popR1: %d\n", mStackUse); } } virtual void storeR0ToR1(bool isInt) { virtual void storeR0ToR1(bool isInt) { Loading Loading @@ -690,15 +703,31 @@ class Compiler : public ErrorSink { virtual void endFunctionCallArguments(int a, int l) { virtual void endFunctionCallArguments(int a, int l) { LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l); LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l); if (l < 0 || l > 0x3FC) { error("L out of range for stack adjustment: 0x%08x", l); } * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 int argCount = l >> 2; int argCount = l >> 2; int argumentStackUse = l; if (argCount > 0) { if (argCount > 0) { int regArgCount = argCount > 4 ? 4 : argCount; int regArgCount = argCount > 4 ? 4 : argCount; argumentStackUse -= regArgCount * 4; o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} } } mStackUse += argumentStackUse; // Align stack. int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT) * STACK_ALIGNMENT); mStackAlignmentAdjustment = 0; if (missalignment > 0) { mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment; } l += mStackAlignmentAdjustment; if (l < 0 || l > 0x3FC) { error("L out of range for stack adjustment: 0x%08x", l); } * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 mStackUse += mStackAlignmentAdjustment; LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n", mStackUse, mStackAlignmentAdjustment); } } virtual int callForward(int symbol) { virtual int callForward(int symbol) { Loading Loading @@ -727,7 +756,7 @@ class Compiler : public ErrorSink { LOG_API("callIndirect(%d);\n", l); LOG_API("callIndirect(%d);\n", l); int argCount = l >> 2; int argCount = l >> 2; int poppedArgs = argCount > 4 ? 4 : argCount; int poppedArgs = argCount > 4 ? 4 : argCount; int adjustedL = l - (poppedArgs << 2); int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment; if (adjustedL < 0 || adjustedL > 4096-4) { if (adjustedL < 0 || adjustedL > 4096-4) { error("l out of range for stack offset: 0x%08x", l); error("l out of range for stack offset: 0x%08x", l); } } Loading @@ -739,12 +768,15 @@ class Compiler : public ErrorSink { LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect); LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect); int argCount = l >> 2; int argCount = l >> 2; int stackArgs = argCount > 4 ? argCount - 4 : 0; int stackArgs = argCount > 4 ? argCount - 4 : 0; int stackUse = stackArgs + (isIndirect ? 1 : 0); int stackUse = stackArgs + (isIndirect ? 1 : 0) + (mStackAlignmentAdjustment >> 2); if (stackUse) { if (stackUse) { if (stackUse < 0 || stackUse > 255) { if (stackUse < 0 || stackUse > 255) { error("L out of range for stack adjustment: 0x%08x", l); error("L out of range for stack adjustment: 0x%08x", l); } } o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 mStackUse -= stackUse * 4; LOG_STACK("adjustStackAfterCall: %d\n", mStackUse); } } } } Loading Loading @@ -858,6 +890,13 @@ class Compiler : public ErrorSink { static int runtime_MOD(int a, int b) { static int runtime_MOD(int a, int b) { return b % a; return b % a; } } static const int STACK_ALIGNMENT = 8; int mStackUse; // This variable holds the amount we adjusted the stack in the most // recent endFunctionCallArguments call. It's examined by the // following adjustStackAfterCall call. int mStackAlignmentAdjustment; }; }; #endif // PROVIDE_ARM_CODEGEN #endif // PROVIDE_ARM_CODEGEN Loading Loading @@ -981,8 +1020,10 @@ class Compiler : public ErrorSink { if (isIndirect) { if (isIndirect) { l += 4; l += 4; } } if (l > 0) { oad(0xc481, l); /* add $xxx, %esp */ oad(0xc481, l); /* add $xxx, %esp */ } } } virtual int jumpOffset() { virtual int jumpOffset() { return 5; return 5; Loading Loading @@ -2315,7 +2356,6 @@ class Compiler : public ErrorSink { } else { } else { pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset()); pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset()); } } if (l | (n == 1)) pGen->adjustStackAfterCall(l, n == 1); pGen->adjustStackAfterCall(l, n == 1); } } } } Loading Loading @@ -3025,6 +3065,11 @@ void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, script->compiler.getPragmas(actualStringCount, maxStringCount, strings); script->compiler.getPragmas(actualStringCount, maxStringCount, strings); } } extern "C" void accDisassemble(ACCscript* script) { script->compiler.disassemble(stderr); } } // namespace acc } // namespace acc
libacc/tests/main.cpp +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,11 @@ int run(MainPtr mainFunc, int argc, char** argv) { return mainFunc(argc, argv); return mainFunc(argc, argv); } } // Private API for development: extern "C" void accDisassemble(ACCscript* script); int main(int argc, char** argv) { int main(int argc, char** argv) { const char* inFile = NULL; const char* inFile = NULL; bool printListing; bool printListing; Loading Loading @@ -109,6 +114,10 @@ int main(int argc, char** argv) { } } } } if (printListing) { accDisassemble(script); } if (runResults) { if (runResults) { accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); Loading