It would be nice if there were a standard interface for calling a PASM2 routine from a high level language; a "pasmcall" calling convention, for lack of a better word. Such a calling convention would generally be in addition to the normal calling convention for the high level language.
The benefit is that we could re-use PASM2 hubexec code for common routines without having to re-invent the wheel. For example, it'd be nice to have a standard floating point library that could be plugged in to different languages. I'm not suggesting that this is the only way to do PASM2, or that it's a solution that works in all cases. I'm just proposing that it be an optional language feature that, if supported, would allow programmers to re-use their code in many places.
With that caveat in mind, what would such a calling convention look like? I can think of a few basic principles:
(a) The _ret_ instruction prefix is incredibly useful, but it means that the call would be via a standard "call" instruction (not "calla" or "calld"). Again, this would apply only to "pasmcall" functions; the normal language calling convention might require a stack for recursion, for example, and so be based on one of those other call instructions.
(b) The "pa" and "pb" registers are clearly designed to accept arguments, so lets pass the first two parameters in those. Return values could come back in "pa". Additional parameters would either go in the COG scratch registers (see below) or on the stack, if we can agree on what the stack looks like
. Or, we could limit pasmcall functions to having at most 2 parameters.
(c) The function would need some scratch registers in COG memory, and/or some stack space to save registers in. We could specify that COG memory registers $1e8-$1ef are temporary registers that may be modified in pasmcall routines. It'd also be nice to have some standard for the stack, but that could be harder to reach agreement on (does the stack grow up or down? which register holds the stack pointer?).
Here's the stack usage I'm aware of at present:
(1) All the fastspin languages use ptra as the stack pointer, and the stack grows up.
(2) p2gcc uses COG memory location $27 (?) as the stack pointer, and the stack grows down
(3) Risc-V gcc uses COG location $02 as the stack pointer, and the stack grows down.
(4) Catalina uses a COG location as the stack pointer (I think it may vary with mode?) and the stack grows down
(5) In traditional Spin the stack grows up, so I expect the Spin2 interpreter will do this as well
(6) TAQOZ seems to store its stack in LUT memory rather than HUB, and the stack grows up
It'd be nice if we all agreed to make HUB stacks grow down from the top of memory (I'm willing to change fastspin to do this). But if that's not feasible, then we could define that pasmcall routines would always get a pointer to some scratch memory in HUB that they could use. This memory could come from the stack, or a static area. I think it should be passed in ptra or ptrb