May 12, 2025

Sun 3/60 - ROM - calls without a stack

I discovered and documented this back when I was working on the Sun 3/80 ROM. The usual scheme with the m68k is to use the jsr (or bsr) instruction to call subroutines, and the rts instruction to return.

A section of code in the bootrom uses another scheme.

I am going to mark these as Xsubroutine and Xcall in the sun 3/60 annotation (I called these "ODD" in the sun 3/80).

The idea is to place the return address into the fp register, and then use a jmp instruction to return. Here is a typical example that calls a printf routine of this flavor:

fefe73f4:   49fa 037e       lea %pc@(0xfefe7774),%a4
fefe73f8:   4dfa 0008       lea %pc@(0xfefe7402),%fp
fefe73fc:   60ff 0000 2fd6  bral 0xfefea3d4

fefe7402:   6000 0002       braw 0xfefe7406

It seems that the a4 register is always used for subroutine arguments.

The first instruction loads the address of the string we want "printf" to print into the a4 register. The second loads the address that we want to return to into the fp register. Both of these use PC relative addressing to generate those addresses. This is neither here nor there really, and in the first case would be done that way even with the usual "jsr" style calls. Then we do a branch to the routine we want to call. Note that the address placed into fp is the address of the instruction we want to return to.

Why take these pains? The reason is to avoid using the stack. This code is used during the testing of RAM memory, and the bootrom wants to test all of it, and that would conflict with use of some of it for the stack.

Note also that these scheme does not allow subroutines to be recursive. In fact it requires all subroutines to be leaf routines, and we cannot call other subroutines from a subroutine. The strings used by this section of code always have "\r\n" in them. The normal printf only will have "\n" and uses a recursion to expand it to "\r\n" as is often done.

The return from subroutines coded to use this scheme look like:

fefe9628:   4ed6            jmp %fp@
A jump to the address saved in the "fp" register.

Mixing regular calls and Xcalls

I see some routines where regular subroutine (that use rts to return) make calls using the Xcall method to other routine. There is nothing wrong with that I suppose as long as registers don't get stomped on.

Tricky returns

Looking at the bootrom code, there are a fair number of cases where the "return address" placed into fp is not the next instruction after the branch. In these cases, the programmer has done some hand optimization and rather than returning to simply do a jump, he has placed the jump address into fp and done away with a double jump. These are the kind of interesting things that confirm that this was not compiler generated code (unless Sun had a very special compiler).
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org