Subroutine calls in machine language are characterized by the form of passing parameters and the form of returning to the caller. The PALM processor has no instructions for subroutine mechanisms, so the programmer has to prove his creativity. Subroutine calls and passing parameters are independent from each other so they are described in two separate paragraphs.


A subroutine call consists of storing the current program counter and jumping to another location. At the end of the subroutine a jump back to the origin is performed by jumping to the location indicated by the stored program counter.
A jump instruction is any instruction that modifies register R0. Normally ADD/SUB R0,#xx is used for relative jumps, LWI R0,#xxxx for absolute jumps and MOVE R0,xx resp. MOVE R0,(Rx) for indirect jumps.
The return address is always passed in a register, most commonly in R2. Of course you can calculate another address or point to a different location in the program if it is desired to return somewhere else. But normally a return to the instruction following the subroutine call is desired, so the INC2 instruction is used.
This will look like this:

Address Opcode            Mnemonic
2000    0203              INC2 R2, R0    ; R2 <- $2004
2002    A00B              ADD R0, #12    ; R0 <- $2010
2004    0000              HALT
2010    A500              ADD R5, #1
2012    0024              MOVE R0, R2    ; R0 <- $2004

There are specially created mnemonics for the AS assembler for subroutines and branches:

The disadvantage of passing the return address in a register is obvious when nested or recursive calls are needed because only a limited set of registers may be available. If all registers are used by the program only one single call can be made. Therefore it is advised to create a stack, e.g. with R15 as stack pointer, that will store all return addresses (and other stuff if desired).

Address Opcode            Mnemonic
2000    D401 ABCD         LWI R4, #$ABCD
2004    0203 D021 7654    CALL $7654, R2   ;(INC2 R2, R0; LWI R0, #$7654)
200A    0000              HALT
7654    52F1              MOVE (R15)+, R2  ; push R2 onto stack
7656    D301 0014         LWI R3, #20
7658    0203 0044         CALL (R4), R2    ; jump to $ABCD
765C    FF01              SUB R15, #2      ; decrement SP by two
765E    D0F8              MOVE R0, (R15)   ; return to caller


The most common forms of passing parameters are register values, common memory area or a stack (e.g. with R15 as SP, see above). Implementing these forms is an easy task. Another form that is often found in PALM programs is a parameter list following the call instruction. This is realized in the following manner:

Address Opcode            Mnemonic
2000    0203 D021 3000    CALL $3000, R2
2006    0200 0400 0040    dw $0200, $0400, ' '
200C    0000              HALT
3000    D321              MOVE R3, (R2)+   ; R3 <- $0200
3002    D421              MOVE R4, (R2)+   ; R4 <- $0400
3004    D521              MOVE R5, (R2)+   ; R5 <- ' '
3006    014C              MHL R1, R4
3008    0146              OR R1, R4
300A    C10B              SNZ R1           ; test if R4 is $0000
300C    0024              RET R2           ; MOVE R0, R2
300E    F400              SUB R4, #1
3010    7530              MOVB (R3)+, R5
3012    F00D              BRA $3006

The subroutine fills a memory area with a certain value. This example fills the area from $0200 and a length of $0400 with blanks, so the screen will be cleared. The parameters build a kind of mini-stack that lies directly after the subroutine call. The return address is the "stack pointer" after all parameters have been popped.