Memora8 Application Binary Interface
Document version: 1.0
Status: Specification
Compiler implementation baseline: SekuraJS 6dd5716
This document describes the function-call and data-layout conventions used by the SekuraJS Memora8 backend. It defines how compatible functions exchange scalar arguments and results, preserve registers, and use the stack. It supplements the Memora8 ISA specification; it does not change instruction behavior.
Data model
| Property | Convention |
|---|---|
| General-purpose register width | 32 bits |
| ABI word size | 4 bytes |
| Pointer size | 4 bytes |
| Stack alignment at function boundaries | 4 bytes |
| Stack direction | Grows toward lower addresses |
The compiler’s integer scalar types are i8, u8, i16, u16, i32, and u32. Their storage sizes and natural alignments are 1, 2, or 4 bytes. Pointers occupy 4 bytes. Structure fields are placed at their natural alignment, and the complete structure size is rounded up to the greatest field alignment. Arrays contain consecutive elements.
Register conventions
| Registers | ABI role | Preservation |
|---|---|---|
r0 |
Constant zero | Always reads as zero; writes have no effect |
r1 |
Function result | Caller-saved; also used for return values |
r2–r7 |
First six scalar arguments (a0–a5) |
Caller-saved |
r8–r18 |
Temporary / scratch registers | Caller-saved |
r19–r25 |
Saved registers (s0–s6) |
Callee-saved |
r26 |
Reserved by the compiler backend | Do not use for general values |
r27 |
No general calling-convention role is assigned by this backend | Treat as unspecified |
r28 |
Module base in compiler-generated module code | Reserved while executing that code |
r29 |
Stack pointer (SP) |
Callee restores it before returning |
r30 |
Frame pointer (FP) |
Callee restores the caller’s value |
r31 |
Link register (LR) |
A function that makes calls saves and restores it |
A caller that needs a value in r1–r18 after a function call must save it before the call. A callee must restore any r19–r25 register it uses. r28 is used by module-mode code to address module data and function tables; code in that mode must preserve its module-base role.
Function arguments
The first six scalar arguments are passed in registers, in order:
| Argument | Register |
|---|---|
| 1 | r2 |
| 2 | r3 |
| 3 | r4 |
| 4 | r5 |
| 5 | r6 |
| 6 | r7 |
Additional scalar arguments are passed on the stack. The caller places them in right-to-left order, one 4-byte argument slot per argument. At callee entry, after establishing its frame pointer, the first stack argument is at [FP + 4], the next at [FP + 8], and so on. The caller removes the stack arguments after the call returns.
SekuraJS launchers that enter a module use the same initial argument registers r2–r7. The launch configuration can set those values; its syntax is documented in the mr8sim launch configuration reference.
Return values and calls
A scalar function result is returned in r1. A function call writes its return address to r31, conventionally using JAL r31, target or JALR r31, base, offset. A returning function transfers control to the address in r31, conventionally with JALR r0, r31, 0.
The value in r1 is the result of the most recent call. A caller should copy it to another register or memory before making another call if it must remain live.
Stack frames
The stack grows downward. The compiler-generated function prologue saves the previous frame pointer at [FP + 0] and sets r30 to that location. If the function makes calls, it saves its incoming link register at [FP - 4]; local variables, spills, and saved registers occupy stack storage below the frame pointer. A function that does not make calls can use [FP - 4] for its first local storage.
Before returning, the callee restores any saved registers, restores r31 when it has made calls, restores the previous r30, and releases its frame so the caller’s stack pointer is recovered. The required stack alignment at call boundaries is 4 bytes.
The exact placement of local variables and register spills is compiler-generated and is not a stable interface between independently compiled functions. Functions should exchange values through the argument and return conventions above rather than relying on another function’s local frame layout.
Data layout
Integer objects use their declared widths: 8-bit, 16-bit, or 32-bit. Structure members are aligned to their natural size, with an overall structure alignment equal to the greatest member alignment. The compiler inserts padding as needed between members and at the end of a structure. Pointers are 32-bit values.
This ABI description covers scalar function arguments and scalar return values. Passing or returning structures by value, variadic calls, and interoperability with non-SekuraJS toolchains require a separately specified convention before they can be treated as compatible interfaces.
Versioning
This document describes the calling and data-layout conventions implemented by SekuraJS baseline 6dd5716. Changes to register roles, argument placement, stack layout at call boundaries, return-value placement, or data layout require an ABI version review.