
178
Evaluating and Programming the 29K RISC Family
result of the code sequence to be held in register space for frequent and fast access.
The trade–off between expression reevaluation and consuming additional register
resources is easily made with the 29K family because of the large number of general
purpose registers available. Code subexpressions need not be large. They may be as
short as an address calculation using a pair of CONST – CONSTH instructions. The
calculation can be done once and the address kept around in a register for reuse.
Moving code out of loops is another technique frequently used to improve per-
formance. However, the typically small number of registers in a CISC processor can
often mean loop invariant code results have to be held in external memory. This can
lead to trade–offs between adding code within a loop or suffering the external
memory access penalties. Again, the large number of general purpose registers in the
29K assist the programmer to achieve improved code.
Branch instructions are to be avoided as their use impacts badly on perfor-
mance. Processors supporting burst–mode addressing operate most efficiently when
instruction bursting is not disrupted with a branch instruction. This is particularly
true for memory systems which have a high first–access latency. The Branch Target
Cache incorporated in some 29K family members can help hide the effects of branch-
ing, but as the number of branch instructions is increased the chance of a hit occurring
in the cache is reduced.
Loop Inversion is a useful technique at reducing the use of branch instructions.
Often programmers will construct loops which have the loop condition test at the
top
of the loop. This requires a branch be used at the bottom of the loop. If the conditional
branch is moved to the bottom of the loop then the number of branch instructions is
reduced
3.3
AVAILABLE REGISTERS
In essence, global registers
gr64–gr95
are reserved for interrupt handlers and
the operating system use. The remaining 32 global registers (
gr96–gr127
) are re-
served for holding User mode program context. The high level language calling con-
vention described in Chapter 2 established this convention. Figure 3-3 illustrates the
partitioning of the global registers among the operating system and user program
tasks. General purpose registers
128–255
are better known as local registers, and ac-
cessed via the registers stack pointer,
gr1
, rather than directly addressed as global
registers. General purpose registers 128–255 can not be accessed like global registers
(
gr96–gr127
); they can only be accessed as local registers or via indirect pointers.
The calling convention goes further than just dividing the register space into two
groups. The user space registers are assigned particular high level language support
tasks. All but four registers (
gr112–gr115
) in user task space will be accessed and mo-
dified by compiler generated code at various times. Most of the registers are used as
compiler temporaries; three registers are used to support memory and register stacks;
and the remaining four registers support the high level language procedure call