This document provides a few suggestions on coding style for developing software in the LXP32 assembly language. These guidelines were tested in a medium-sized commercial project.
Registers
One distinctive feature of the LXP32 processor is the abundance of registers, which can be used not only for parameter passing or temporary storage, but even for long term storage. An example of register allocation:
r0 is used like an accumulator, to store values that are needed immediately, for example, data or code pointers.
r1–r31 are used to pass parameters to procedures, as per the calling convention described in the manual. They are considered caller-saved, meaning that the caller must expect that the called procedure can modify them. These registers can be also used for temporary storage, like r0.
r32–r63 are callee-saved general purpose registers. If a procedure modifies any of them, it must restore their value before return.
r64–r239 are global register variables which can be used by any procedure.
To simplify the use of register variables, global or otherwise, it is recommended to declare them as macros:
#define x r1
#define y r2
#define z r3
Macro definitions for global register variables should be placed in a separate include file with the inc extension.
Identifiers
It is useful to adopt a naming convention to distinguish between various types of identifiers:
use lowercase for macros referring to register variables;
use UPPERCASE for other kinds of macros, such as constants;
Capitalize the first letters of symbol identifiers (labels);
procedure labels should end with _proc, interrupt handler labels – with _handler.
A simple example that calls a procedure 1000 times:
#define ITERATIONS 1000
#define i r32
lcs i, ITERATIONS
Loop:
lcs r0, Do_action_proc
call r0
sub i, i, 1
lcs r0, Loop
cjpmne r0, i, 0
Modules
It is recommended to put every non-trivial procedure to a separate module (source code file). Besides general code clarity, doing so has other advantages:
Avoiding clashes between macros referring to local register variables (since macro definition scope lasts until the end of the module).
The LXP32 linker automatically excludes unused modules from the output binary. However, if at least one symbol of the module is used, that module gets linked in its entirety. Placing procedures to separate modules helps to avoid linkage of unused procedures.