Clemson University -- CPSC 231 -- Fall 2009 example SPARC code for subroutine void prt_sum( int x[], int n ){ register int i, sum = 0; for( i = 0; i < n; i++ ){ sum = sum + x[i]; } printf("%d\n",sum); } Observations: (1) cannot be written as a leaf procedure since it calls printf() (2) input parameters available in %i0 and %i1 after save instruction (3) cannot refer to actual parameter names given in the call (4) must pass format string address and value of sum in %o0 and %o1 to printf() (5) no return value to be passed back in %o0 by prt_sum The SPARC code for this subroutine can be written several ways; two possible approaches are given below. (The 'X's in the center line indicate the differences between the two approaches.) (Note: compare the readability of these examples with examples using m4 to name local registers by usage, e.g., %ptr_r, %sum_r, etc.) /* prt_sum | /* prt_sum /* | /* /* input parameters (after save) | /* input parameters (after save) /* %i0 - address of array of ints | /* %i0 - address of array of ints /* %i1 - number of array elements | /* %i1 - number of array elements /* | /* /* return value | /* return value /* none | /* none /* | /* /* effect/output | /* effect/output /* sum of array elements is | /* sum of array elements is /* calculated and printed | /* calculated and printed /* | /* /* method | /* method /* ptr traverses array to access X /* array elements accessed using /* elements (ptr incr = 4) X /* scaled index (index incr = 1) /* | /* /* local register usage | /* local register usage /* %l0 - loop count X /* %l0 - index i /* %l1 - sum | /* %l1 - sum /* %l2 - ptr to array element X /* %l2 - scaled index */ | */ | .global prt_sum | .global prt_sum prt_sum: | prt_sum: save %sp,-96,%sp | save %sp,-96,%sp | clr %l0 | clr %l0 clr %l1 | clr %l1 mov %i0,%l2 X loop: | loop: cmp %l0,%i1 | cmp %l0,%i1 bge done | bge done nop | nop X sll %l0,2,%l2 ld [%l2],%o0 X ld [%i0+%l2],%o0 add %l1,%o0,%l1 | add %l1,%o0,%l1 add %l2,4,%l2 X inc %l0 | inc %l0 ba loop | ba loop nop | nop done: | done: | /* parameter regs for printf | /* parameter regs for printf /* %o0 - addr of format string | /* %o0 - addr of format string /* %o1 - first value | /* %o1 - first value */ | */ | set fmt,%o0 | set fmt,%o0 mov %l1,%o1 | mov %l1,%o1 call printf | call printf nop | nop | ret | ret restore | restore | | .section ".data" | .section ".data" fmt: .asciz "%d\n" | fmt: .asciz "%d\n" Design note: the example is artificially constrained -- a better design would separate concerns (split the summation from the printing) and instead define a sum() function that returns the sum in %o0. Thus, the caller could use: int sum( int x[], int n ){ register int i, s = 0; for( i = 0; i < n; i++ ){ s = s + x[i]; } return s; } printf( "%d\n", sum(a,A_SIZE) ); and sum() could then be written as a leaf routine. /* input parameters /* %o0 - address of array or ints /* %o1 - number of array elements /* /* return value /* %o0 - sum of array elements /* /* global register usage /* %g1 - index /* %g2 - sum /* %g3 - scaled index /* %g4 - array element value */ define(base_r,o0) define(count_r,o1) define(index_r,g1) define(sum_r,g2) define(offset_r,g3) define(value_r,g4) .global sum sum: clr %index_r clr %sum_r loop: cmp %index_r, %count_r bge done nop sll %index_r, 2, %offset_r ld [ %base_r + %offset_r ], %value_r add %sum_r, %value_r, %sum_r inc %index_r ba loop nop done: mov %sum_r, %o0 retl nop Defensive programming hint: the programmer of prt_sum() should consider checking that the input count parameter 'n' (in %i1) is > 0. Convenience for caller: when feasible, a programmer shouldn't change the values of the input parameters - this allows reuse of these values by the caller (as might be desirable when the caller calls a series of subroutines that have identical actual parameter lists).