Motorola 88K Subroutines

Mark Smotherman. Last updated September 2002.


The M88K family was a 32-bit RISC design from Motorola in the 1980s. The first generation implementation consisted of the 88100 CPU and 88200 MMU. The second generation implementation was called the 88110, and several ISA changes were introduced. The M88K family was discontinued when Motorola switched over to the PowerPC. (PowerPC has both 32-bit and 64-bit programming models.)

The 88110 had 32 32-bit general registers, r0-r31, and 32 80-bit floating-point registers, x0-x31. r0 and x0 were both hardwired to zero, and r1 was dedicated to holding the return address.

Register conventions

        r0       - constant 0 (hardware)
        r1       - return address (set by hardware)
        r2-r9    - called procedure parameter registers
        r10-r13  - called procedure temporary registers (scratch)
        r14-r25  - calling procedure reserved registers (preserved by
                   callee, if used)
        r26-r29  - reserved by linker
        r30 (fp) - frame pointer
        r31 (sp) - stack pointer

An ABI called the 88open BCS (binary compatibility standard) was defined.

Subroutine instructions

        bsr displ     r1 <- address of first instruction after bsr;
                      pc <- address of bsr + displ<<2
        jsr reg       r1 <- address of first instruction after bsr;
                      pc <- contents of register
        jmp reg       pc <- contents of register

    delayed branch forms

        bsr.n displ   r1 <- address of second instruction after bsr
                      pc <- address of bsr + displ<<2
        jsr.n reg     r1 <- address of second instruction after bsr
                      pc <- contents of register
        jmp.n reg     pc <- contents of register

Parameter passing

Up to eight parameter are passed in the registers r2-r9. Additional parameters are passed on the memory stack (although some systems apparently allowed up to twelve register-allocated parameters in r2-r13).

Calling program structure


           ... place parameters in r2-r9 ...

           bsr   subr            ! save return address in r1


Subroutine structure (non-leaf)

                                 ! prolog:
           subu  #r31,#r31,48    ! adjust stack pointer by size of frame
           st    #r1,#r31,36     ! save return address in M[sp+36]
           st    #r30,#r31,32    ! save caller's fp in M[sp+32]
           addu  #r30,#r31,32    ! move fp to point to old fp

           ... body of subroutine ...

                                 ! epilog:
           subu  #r31,#r30,32    ! reset sp to top of frame
           ld    #r1,#r31,36     ! restore return address
           ld    #r30,#r31,32    ! restore caller's fp
           addu  #r31,#r31,48    ! restore caller's sp
           jmp   #r1             ! return
(this is example code generated by DG/UX gcc)

[History of subroutines page] [Mark's homepage] [CPSC homepage] [Clemson Univ. homepage]