|
by Michael
Smith
Start ý Register
Comparison ý Memory Access ý Modify
and Volatile Registers ý Length and Base
Registers ý Hardware and Software ý
Interrupt Handling ý Sources
and PDF
HARDWARE AND SOFTWARE
Things get interesting with the SHARCýs
C programming model when the programmer attempts to pass the fourth
parameter to the subroutine. On a register-windowed processor, such
as the SPARC or the 29K RISC, this wouldnýt be a problem. The 29K
has 128 registers for parameter passing. However, the SHARC has no
other allocable volatile registers, and the fourth parameter must
be passed another way.
It will do you no good to try to do the
68K-trick, passing the parameter above the return address on the stack.
The standard place for the 21K return address is on a specialized
high-speed PC stack. This hardware is provided without access to the
data registers and can only hold a few values!
There are a number of other problems,
as well. A characteristic of the C program is the presence of subroutines
calling other subroutines. The innermost subroutine in a program could
easily be nested 8 or 10 subroutines deep inside the main function.
This type of operation cannot be handled with a shallow hardware stack
using the standard SHARC subroutine CALL and RTS instructions.
Also, thereýs the problem of all the variables and arrays declared
inside the C function, or interrupt handling, when copious material
must go onto the stack.
The approach taken on the SHARC brings
back fond memories of my early days developing embedded systems with
microprogrammable chips. If you didnýt have the required instructions,
you either added ýem or faked ýem.
In the SHARC C programming model, index
registers I6 and I7 are set up as a frame pointer and a C-top-of-stack
pointer, respectively. These registers function essentially in the
same way as the 68K frame (A6) and stack pointer (A7). However, the
SHARC I7 register points to the next empty stack location, whereas
the 68K A7 register points to the current valid value on the stack.
Several modify registers are initialized
to values 0, 1, and ý1 to speed address stack operations on their
way in the SHARC in the C. Of course, to prevent surprises, avoid
introducing a C-stack with circular buffer characteristics. Remember
to keep length registers L6 and L7 at zero, especially when interrupts
are active.
The final touch is to provide some C-specific
instructions to the SHARC instruction set. CJUMP is used when
getting into a C-callable subroutine, and RFRAME when leaving.
Youýll have to search the SHARC Technical Reference Guide because
these instructions are not detailed in the standard SHARC user manual.
The SHARC CJUMP instruction, together
with other instructions hidden in the branch delay slots, is equivalent
to the combined 68K instructions:
JSR with LINK #0, FP
The technical guide states, "CJUMP
combines a direct or PC-relative jump with register transfer operations
that save the frame and stack pointers."
However, the registers are not saved
on the stack. There are some unfortunate things happening with register
R2 in this instruction, but should not cause a problem if you remember
that R2 is designated as a volatile register. Nothing useful should
be stored there during a subroutine call.
The RFRAME instruction is used
as part of the return sequence from an assembly language routine back
to a C-calling program. This is equivalent to the 68K UNLK
instruction, including that instructionýs memory access.
Fortunately, the necessary instructions
for returning to a C-calling function from assembly code are always
the same and can be cut and pasted into a macro DO_MAGIC. In
this macro, the return address from the C-stack is fetched. As part
of the indirect jump, using a program data memory volatile index register,
the return address is tweaked by an instruction to get it pointing
in the proper direction. Finally, the RFRAME instruction causes
the C-top-of-stack to be copied from the frame pointer and the old
frame pointer recovered from the C-stack during the branch delay slots.
#define DO_MAGIC \
I12 = dm(-1, I6); \ //
GET RETURN ADDRESS
JUMP(1, I12) (DB); \ //
ADJUST ADDRESS A LITTLE
nop; \
RFRAME; //
ADJUST FRAM AND TOP-OF-STACK POINTERS
PREVIOUS
NEXT
Circuit Cellar provides up-to-date information for engineers. Visit
www.circuitcellar.com for
more information and additional articles.
For subscription information, call (860) 875-2199, subscribe@circuitcellar.com
or subscribe online.
ýCircuit Cellar, the Magazine for Computer Applications. Posted with
permission. |