#ifndef __StackFrame_h__ #define __StackFrame_h__ #include #include // template void Push__(uint32_t sp) { static_assert(Bytes == 0, "Invalid Stack Size"); } template void Push__(uint32_t sp, uint16_t value, Args&&... args); template void Push__(uint32_t sp, uint32_t value, Args&&... args); template void Push__(uint32_t sp, uint16_t value, Args&&... args) { memoryWriteWord(value, sp); Push__(sp + 2, std::forward(args)...); } template void Push__(uint32_t sp, uint32_t value, Args&&... args) { memoryWriteLong(value, sp); Push__(sp + 4, std::forward(args)...); } template void Push(Args&&... args) { uint32_t sp = cpuGetAReg(7) - Bytes; cpuSetAReg(7, sp); Push__(sp, std::forward(args)...); } template void ToolReturn(uint32_t sp, uint32_t value) { if (sp == -1) sp = cpuGetAReg(7); static_assert(N == 2 || N == 4, "Invalid Return Size"); if (N == 4) { memoryWriteLong(value, sp); } if (N == 2) { memoryWriteWord(value, sp); } } // pre-define these templates to prevent instantiation errors. template uint32_t StackFrame__(uint32_t sp, uint32_t &x, Args&&... args); template uint32_t StackFrame__(uint32_t sp, uint16_t &x, Args&&... args); template uint32_t StackFrame__(uint32_t sp, uint8_t &x, Args&&... args); template uint32_t StackFrame__(uint32_t sp); template uint32_t StackFrame__(uint32_t sp) { static_assert(Offset == 0, "Invalid Stack Size"); cpuSetAReg(7, sp + Bytes); return sp + Bytes; } template uint32_t StackFrame__(uint32_t sp, uint32_t &x, Args&&... args) { x = memoryReadLong(sp + Offset - 4); return StackFrame__(sp, std::forward(args)...); } template uint32_t StackFrame__(uint32_t sp, uint16_t &x, Args&&... args) { x = memoryReadWord(sp + Offset - 2); return StackFrame__(sp, std::forward(args)...); } template uint32_t StackFrame__(uint32_t sp, uint8_t &x, Args&&... args) { // byte pushes as 2 bytes with 1 garbage byte x = memoryReadByte(sp + Offset - 2); return StackFrame__(sp, std::forward(args)...); } template uint32_t StackFrame(Args&&... args) { uint32_t sp = cpuGetAReg(7); return StackFrame__(sp, std::forward(args)...); } #endif