Prism 6.0 User's Guide

Chapter 4 Debugging a Program

This chapter discusses how to debug programs in Prism. It also describes how to use events to control the execution of a program. The principles that apply to debugging serial programs also apply to debugging message-passing programs. However, debugging a message-passing program can be considerably more complex than debugging a serial program, since you are in effect debugging multiple individual programs concurrently. MP Prism's concept of psets lets you focus your debugging efforts on the processes that are of particular interest. The following discussions distinguish features (where necessary) that apply exclusively to debugging the processes of message-passing programs:

Overview of Events

A typical approach to debugging is to stop the execution of a program at different points so that you can perform various actions--for example, check the values of variables. You stop execution by setting a breakpoint. If you perform a trace, execution stops, then automatically continues.

Breakpoints and traces are events. You can specify before the execution of a program begins what events are to take place during execution. When an event occurs:

Prism provides various ways of creating these events--for example, by issuing commands, or by using the mouse in the source window. " Setting Breakpoints" describes how to create breakpoint events; " Tracing Program Execution" describes how to create trace events. " Using the Event Table" describes the Event Table, which provides a unified method for listing, creating, editing, and deleting events.

See " Events Taking Pset Qualifiers (MP Prism Only)" for a discussion of events in MP Prism.

You can define events so that they occur:

Such events are referred to as triggering conditions.

In addition, you can qualify an event as follows:

You can include one or more Prism commands as actions that are to take place as part of the event. For example, using Prism commands, you can define an event that tells Prism to stop at line 25, print the value of x, and do a stack trace.

Using the Event Table

The Event Table provides a unified method for controlling the execution of a program. Creating an event in any of the ways discussed later in this chapter adds an event to the list in this table. You can also display the Event Table and use it to:

You display the Event Table by choosing the Event Table selection from the Events menu.

This section describes the general process of using the Event Table.

Description of the Event Table

Figure 4-1 shows the Event Table.

Figure 4-1 Event Table

Graphic

The top area of the Event Table is the event list--a scrollable region in which events are listed. When you execute the program, Prism uses the events in this list to control execution. Each event is listed in a format in which you could type it as a command in the command window. It is prefaced by an ID number assigned by Prism. For example, in Figure 4-1, the events have been assigned the IDs 1 and 2.

The middle area of the Event Table is a series of fields that you fill in when editing or adding an event; only a subset of the fields is relevant to any one event. The fields are:

The buttons beneath these fields are for use in creating and deleting events, and are described below.

The area headed Common Events contains buttons that provide shortcuts for creating certain standard events.

Click on Close or press the Esc key to cancel the Event Table window.

Adding an Event

You can either add an event, editing field by field, or you can use the Common Events buttons to fill in some of the fields for you. You would add an event from the beginning if it weren't similar to any of the categories covered by the Common Events buttons.

To add an event, editing field by field:

  1. Click on the New button.

    All values currently in the fields are cleared.

  2. Fill in the relevant fields to create the event.

  3. Click on the Save button to save the new event.

    It appears in the event list.

To use the Common Events buttons to add an event:

  1. Click on the button for the event you want to add--for example, Print.

    This fills in certain fields (for example, it puts print on dedicated in the Actions field) and highlights the field or fields that you need to fill in (for example, it highlights the Location field when you click on Print, because you have to specify a program location).

  2. Fill in the highlighted field(s). You can also edit other fields, if you like.

  3. Click on Save to add the event to the event list.

Most of these Common Events buttons are also available as separate selections in the Events menu. This lets you add one of these events without having to display the entire Event Table. The menu selections, however, prompt you only for the field(s) you must fill in. You cannot edit other fields.

Individual Common Events buttons are discussed throughout the remainder of this guide.

You can also create a new event by editing an existing event; see " Editing an Existing Event".

Deleting an Existing Event

You can delete events using the Event Table or the Delete selection from the Events menu.

To delete an existing event, using the Event Table:

  1. Click on the line representing the event in the event list, or move to it with the up and down arrow keys.

    This causes the components of the event to be displayed in the appropriate fields beneath the list.

  2. Click on the Delete button.

    You can also choose the Delete selection from the Events menu to display the Event Table. You can then follow the procedure described above.

    Deleting a breakpoint at a program location also deletes the B in the line-number region at that location.

Editing an Existing Event

You can edit an existing event to change it, or to create a new event similar to it.

To edit an existing event:

  1. Click on the line representing the event in the event list, or move to it with the up and down arrow keys.

    This causes the components of the event to be displayed in the appropriate fields beneath the list.

  2. Edit these fields.

    For example, you can change the Location field to specify a different location in the program.

  3. Click on Replace to save the newly edited event in place of the original version of the event.

    Click on the Save button to save the new event in addition to the original version of the event; it is given a new ID and is added to the end of the event list. Clicking on Save is a quick way of creating a new event similar to an event you have already created.

Enabling and Disabling Events

You can disable and enable events. When you disable an event, Prism keeps it in the event list, but it no longer affects execution. You can subsequently enable it when you once again want it to affect execution. This can be more convenient than deleting events and then redefining them.

For example, this sequence of commands displays the event list, then disables an event, then re-displays the event list:

(prism) show events(1) trace
(2) when stopped { print board }
(prism) disable 1
event 1 disabled
(prism) show events
(1) trace (disabled)
(2) when stopped { print board }

Issue the enable command to enable an event that has been disabled. Specify the ID of the disabled event as the argument.

Saving Events

Events that you create for a program are automatically maintained when you reload the same program during a Prism session. This saves you the effort of redefining these events each time you reload a program.

Note these points:

To use Prism commands to save your events to a file, and then execute them from the file rather than individually:

  1. Issue the show events command, which displays the event list.

    Redirect the output to a file. For example,

show events @ primes.events

(See " Redirecting Output" for information on redirecting output.)

  1. Edit this file to remove the ID number at the beginning of each event.

    This leaves you with a list of Prism commands.

  2. Issue the source command when you want to read in and execute the commands from the file.

    For example,

source primes.events

Events Taking Pset Qualifiers (MP Prism Only)

Events in MP Prism can take a pset qualifier. You can specify this in an event field in MP Prism's Event Table, as shown in Figure 4-2.

Figure 4-2 Pset Field in MP Prism's Event Table

Graphic

If you don't supply a pset qualifier, the event applies to the current pset. If you create the event before changing the current set, the event applies to the default set, which is all.

Thus,

stop in receive pset notx

sets a breakpoint in the receive routine for the processes in the set notx. Each process in the set stops when it reaches this routine. It is possible, of course, that some processes may never reach this routine. This becomes an issue when you include actions in an event; see below.

If all the processes in the pset have stopped, you can continue them by issuing a command like

cont pset notx

Here is another example:

stop if x > 10

This command stops execution for any process in the current pset if the process's value for the variable x is greater than 10.

Prism evaluates the expression in the condition locally--that is, separately for each process. Similarly, if a and b are arrays,

stop if sum(a) > sum(b)

stops execution for a process in the current set if the sum of the values of a in that process is greater than the sum of the values of b.

All processes that are stopped at breakpoints are members of the predefined pset break.

Events and Dynamic Psets

If you use a dynamic pset as a qualifier for an event, its membership is evaluated when you issue the command defining the event. Thus, the command

stop at 10 pset interrupted

creates a breakpoint only in the processes that are interrupted at the time the command is issued. If no processes are currently interrupted, you receive an error message.

One result of this is that you cannot define events that involve dynamic psets before the program starts execution.

Events and Variable Psets

If you use a user-defined variable pset as a qualifier, its membership is determined by the most recent eval pset command you issued for that pset.

As is the case with dynamic psets, you cannot define events that involve variable psets before the program starts execution.

Actions in Events

Events in both MP Prism and scalar Prism can take action clauses. For example, in MP Prism the following action clause prints x for the pset foo when the members of foo are stopped at line 10:

stop at 10 {print x} pset foo

Note -

Associating an action with an event forces a global synchronization at the breakpoint or tracepoint. In the example above, every process in pset foo must stop at line 10 before x can be printed. If a member does not stop at line 10, the action never takes place. In a trace event, all processes in the pset must stop at the specified place and synchronize; the action then takes place, and the processes automatically continue execution.


You can include an eval pset command as an event action. For example,

stop in send {eval pset sending}

evaluates the pset sending when all the members of the current pset are stopped in send. You receive error messages if it is impossible to evaluate membership in a pset (for example, because a variable in the set definition is not active).

Note these limitations in using event actions: i:

Displaying Events by Process

Issue the show events command with a process number as an argument to display all events associated with that process. For example,

(prism) show events
(1) trace
(2) when stopped { print board }
(prism) disable 1
event 1 disabled
(prism) show events
(1) trace (disabled)
(2) when stopped { print board }

Issuing show events with no arguments has its standard behavior; that is, it prints out all events.

Events and Deleted Psets

If you create an event that applies to a particular pset, and subsequently delete the pset, the event continues to exist. Its printed representation, however, is changed so that it shows the processes that were members of the pset at the time you deleted the set.

Setting Breakpoints

A breakpoint stops execution of a program when a specific location is reached, if a variable or expression changes its value, or if a certain condition is met. Breakpoints are events that Prism uses to control execution of a program. This section describes the methods available in Prism for setting a breakpoint.

You can set a breakpoint

You'll probably find it most convenient to use the line-number region for setting simple breakpoints; however, the other two methods give you greater flexibility--for example, in setting up a condition under which the breakpoint is to take place.

In all cases, an event is added to the list in the Event Table. If you delete the breakpoint using any of the methods described in this section, the corresponding event is deleted from the event list. If you set a breakpoint at a program location, a B appears next to the line number in the line-number region.

Using the Line-Number Region

To use the line-number region to set a breakpoint, the line at which you want to stop execution must appear in the source window. If it doesn't, you can scroll through the source window (if the line is in the current file), or use the File or Func selection from the File menu to display the source file you are interested in.

To set a breakpoint in the line-number region:

  1. Position the mouse pointer to the right of the line numbers; the pointer turns into a B.

  2. Move the pointer next to the line at which you want to stop execution.

  3. Left-click the mouse.

  4. A B is displayed, indicating that a breakpoint has been set for that line.

    A message appears in the command window confirming the breakpoint, and an event is added to the event list.

    The source line you choose must contain executable code; if it does not, you receive a warning in the command window, and no B appears where you clicked.

    Shift-click on the letter in the line-number region to display the complete event (or events) associated with it.

See " Using the Line-Number Region" for more information on the line-number region.

See " Using the Line-Number Region in MP Prism" for a discussion of the line-number region in MP Prism.

Deleting Breakpoints via the Line-Number Region

To delete the breakpoint, left-click on the B that represents the breakpoint you want to delete. The B disappears; a message appears in the command window, confirming the deletion.

What Happens in a Split Source Window

As described in " Moving Through the Source Code", you can split the source window to display source code and the corresponding assembly code.

You can set a breakpoint in either pane of the split source window. The B appears in the line-number region of both panes, unless you set the breakpoint at an assembly code line for which there is no corresponding source line.

Deleting a breakpoint from one pane of the split source window deletes it from the other pane as well.

Using the Line-Number Region in MP Prism

MP Prism provides variations on the way that the line-number region displays breakpoints and tracepoints. In MP Prism:

If there is a mixture of breakpoints and tracepoints set on the line, Prism uses the B-b-T-t sequence to determine what letter to display. For example, if a line has a breakpoint set in one process and a tracepoint set in all processes, Prism displays a b.

As in scalar Prism, you can shift-click on the letter in the line-number region to display the complete event (or events) associated with it.

Using the Event Table and the Events Menu

To set a breakpoint, choose the Stop <loc> or Stop <var> selection from the Events menu. These choices are also available as Common Events buttons within the Event Table itself; see " Adding an Event".

Figure 4-3 Stop <loc> Dialog Box

Graphic

In addition, Stop <cond> is available as a Common Events button. It prompts for a condition, which can be any expression that evaluates to true or false; see " Writing Expressions in Prism" for more information on expressions. The program stops when the condition is met. This slows execution considerably.

You can also use the Event Table to create combinations of these breakpoints; for example, you can create a breakpoint that stops at a location if a condition is met. In addition, you can use the Actions field of the Event Table to specify the Prism commands that are to be executed when execution stops.

Deleting Breakpoints via the Event Table

To delete a breakpoint, choose the Delete selection from the Events menu, or use the Delete button in the Event Table itself. See " Deleting an Existing Event".

Using Commands

Issue the command stop (or when, which is an alias for stop) from the command line to set a breakpoint. The syntax of the stop command is also used by the stopi, trace, and tracei commands, which are discussed below. The general syntax for all the commands is:

command [variable | at line | in func] [if expr] [{cmd[; cmd...]}] [after n]

where

at "filename":line-number

if a .GT. 1

This form of the command slows execution considerably, unless you combine it with the at line syntax. See " Writing Expressions in Prism" for more information on writing expressions in Prism.

The first option listed (specifying the location or the name of the variable) must come first on the command line; the other options, if you include them, can be in any order.

For the when command, you can use the keyword stopped to specify that the actions are to occur whenever the program stops execution.

When you issue the command, an event is added to the event list. If the command sets a breakpoint at a program location, a B appears in the line-number region next to the location.

Examples

To stop execution the tenth time in function foo and print a:

stop in foo {print a} after 10

To stop at line 17 of file bar if a is equal to 0:

stop at "bar":17 if a == 0

To stop whenever a changes:

stop a

To stop the third time a equals 5:

stop if a .eq. 5 after 3

To print a and do a stack trace every time the program stops execution:

when stopped {print a; where}

For Machine Instructions

To set a breakpoint at a machine instruction, issue the stopi command, using the syntax described above, and specifying a machine address. For example,

stopi at 0x1000

stops execution at address 1000 (hex).

The history region displays the address and the machine instruction. The source pointer moves to the source line being executed.

Deleting Breakpoints via the Command Window

To delete a breakpoint via the command window, first issue the show events command. This prints out the event list. Each event has an ID number associated with it.

To delete one or more of these events, issue the delete command, listing the ID numbers of the events you want to delete; separate multiple IDs with one or more blank spaces. For example,

delete 1 3

deletes the events with IDs 1 and 3. Use the argument all to delete all existing events.

Tracing Program Execution

You can trace program execution by using the Event Table or Events menu, or by issuing commands. All methods add an event to the Event Table. If you trace a source line, Prism displays a T next to the line in the line-number region.

As described earlier, tracing is essentially the same as setting a breakpoint, except that execution continues automatically after the breakpoint is reached. When tracing source lines, Prism steps into procedures if they were compiled with the -g option; otherwise it steps over them as if it had issued a next command.

Using the Event Table and the Events Menu

To trace program execution, choose the Trace, Trace <loc>, or Trace <var> selection from the Events menu. These choices are also available as Common Events buttons within the Event Table itself.

In addition, Trace <cond> is available as a Common Events button. It prompts for a condition, which can be any expression that evaluates to true or false; see " Writing Expressions in Prism" for more information on writing expressions. The program displays a message when the condition is met. This also slows execution considerably.

For variations of these traces, you can create your own event in the Event Table. You can also use the Actions field to specify Prism commands that are to be executed along with the trace.

Deleting Traces via the Event Table

To delete a trace, choose the Delete selection from the Events menu, or use the Delete button in the Event Table. See " Deleting an Existing Event".

Using Commands

Issue the trace command from the command line to trace program execution. Issuing trace with no arguments causes each source line in the program to be displayed in the command window before it is executed.

The trace command uses the same syntax as the stop command; see " Using Commands". For example:

trace {print a}

trace at 17 if a .GT. 10

In addition, Prism interprets

trace line-number

as being the same as

trace at line-number

For Machine Instructions

To trace machine instructions, use the tracei command, specifying a machine address. When tracing machine instructions, Prism follows all procedure calls down. The tracei command has the same syntax as the stop command; see " Using Commands".

The history region displays the address and the machine instruction. The execution pointer moves to the next source line to be executed.

Deleting Traces via the Command Window

To delete a trace, use the show events command to obtain the ID associated with the trace, then issue the delete command with the ID as its argument. See " Using Commands".

Displaying and Moving Through the Call Stack

The call stack is the list of procedures and functions currently active in a program. Prism provides you with methods for examining the contents of the call stack.

See " Where Graph" for a discussion of displaying the call stack in MP Prism.

Displaying the Call Stack

Figure 4-4 Where Window

Graphic

Values of arguments in displayed procedures are shown in the default radix, which is decimal unless you change it via the set $radix command; see " Changing the Default Radix".

Moving Through the Call Stack

Moving up through the call stack means heading toward the main procedure. Moving down through the call stack means heading toward the current stopping point in the program.

Moving through the call stack changes the current function and repositions the source window at this function. It also affects the scope that Prism uses for interpreting the names of variables you specify in expressions and commands.

Prism provides these methods for moving through the call stack:

Scope in MP Prism

In MP Prism, the scope of the current process determines the scope for resolving the names of variables. See " The Current Process" for a discussion of the current process.

If a command applies to a pset other than the current set, Prism uses the scope of that set's current process.

It is possible that other members of the pset will have different scopes from that of the current process, or that its scope level will not even exist in these processes. In these cases, you receive an error message when you try to issue a command (for example, print or display) that requires a consistent scope. To solve the problem, you can do one of the following:

Commands such as pset and process that affect scope print the current function when you issue them.

Where Graph

In scalar Prism, choosing Where from the Debug menu displays the call stack for the program; see " Displaying and Moving Through the Call Stack". A message-passing program, however, can have multiple call stacks, one for each process. To show the relationships among these call stacks, MP Prism provides a Where graph; this window displays a snapshot of the dynamic call graph of the program. Information is displayed for all processes that are not running.

To display the Where graph:

where on dedicated

A window like the one shown in Figure 4-5 is displayed.

Figure 4-5 Where Graph

Graphic

The Where graph centers on the current process of the current pset--that is, the processes related to it are lined up in a single column. In Figure 4-1, process 0 is the current process. If you change the current process, the Where graph rearranges itself. The default zoom level of the Where graph shows the arguments for the current process.

At the bottom of each box are line numbers indicating where processes branch.

Shift-click in each function's box to display a pop-up window showing the numbers of the processes with this function in their call stack, along with their arguments.

Panning and Zooming in the Where Graph

As Figure 4-6 shows, the Where graph can get quite large, so MP Prism provides methods for panning through it and zooming in and out.

The white box in the navigator rectangle at the top of the window shows the position of the display area relative to the entire Where graph. You can either drag the box or click at a spot in the navigator. The box moves to that spot, and the window shows the Where graph in this area of the total display.

To display more of the Where graph at the same time, click on the Zoom down arrow to the right of the navigator. This reduces the size of the boxes representing the functions and removes information. Figure 4-6 shows the Where graph of Figure 4-5, zoomed out one level. Note that the information about the current process's arguments is gone.

Figure 4-6 Where Graph, Zoomed Out One Level

Graphic

Zooming out one more level removes the line numbers, and one more level after that removes the function names, leaving only boxes connected by lines. You can still shift-click on a box to display information about it.

Clicking on the Zoom up arrow increases the size of the function boxes and includes more information in them. Figure 4-7 shows the Where graph of Figure 4-5, zoomed in. In this case, the Where graph shows, for each function, the processes that have that function in their call stack. As in the Psets window, the processes are represented as bitmaps of cells, numbered starting at the upper left, increasing from left to right and then jumping to the next row.

Figure 4-7 Where Graph, Zoomed In

Graphic

Zooming in another level shows all arguments for all processes.

Shrinking Selected Portions of the Where Graph

You can shrink selected portions of the Where graph. This is useful if you want to see the overall structure of the graph, but in addition want to focus on certain functions.

Middle-click on a function to iconify it and all of its children. Middle-click on an iconified function to re-expand it and its children to the current zoom level.

Alternatively, you can click on the (De)iconify Node button next to the Zoom arrows at the top of the Where graph. This changes the mouse pointer to a target. You can then left-click on a function to iconify it and its children. If it is already iconified, left-clicking on it will re-expand it and its children. To cancel the operation, left-click anywhere outside of the boxes surrounding the functions.

Moving Through the Where Graph

When you first display the Where graph, the main function is highlighted. You can left-click on a function to highlight it. Or, you can move through the Where graph via the keyboard:

Making a Function the Current Pset

Pressing the spacebar while in the Where graph does the following:

Issuing the where Command in MP Prism

Issuing the where command by default displays (in the history region) the call stack consecutively for each process in the current set (or in the pset you specify via the pset qualifier).

Issuing the command

where on dedicated

displays the Where graph, as described above.

Issuing the command

where on snapshot

puts the history-region output into a window; it does not create a Where graph.

Combining Debug and Optimization Options

If you use Prism on programs that have been compiled with optimization options, you should expect different behavior from Prism commands and changes in the visibility of variables in the optimized programs.

Interpreting Prism Interaction With an Optimized Program

When the control flow is inside a routine that has been compiled with both -g and an optimization option (a debuggable optimized routine), the next and step commands change their behavior:

You can set breakpoints using the stop at command inside debuggable optimized routines only at the first line of such a routine. If the routine name is foo and the first instruction in foo is ADDR_INSTR then the breakpoint is set as if you had used stop in foo or stopi at ADDR_INSTR.

Note that the following (related) commands are unaffected:

When the control flow returns to a debuggable optimized routine, as a result of one of the following commands:

then Prism assumes that the current position is at the first line of the current routine. Prism makes the same assumption when the source file position (at the command line or in the GUI) is updated as a result of up or down commands ending in a debuggable optimized routine.

Accessing Variables in Optimized Routines

Due to the effects of optimization on variable location in executable programs that have been compiled with optimization, not all variables can be accessed by Prism at all times.

The accessibility of variables can be defined by whether the variables can be used in expressions that require the right value of the variable (such as print X, or call foo(X)) or the left value of the variable (such as assign X=1).

The limits of accessibility can be described by the flow of control in an optimized program. When the flow of control is in a routine compiled with both -g and an optimization flag:

The following commands can use only accessible variables:

The where command reports all active stack frames which have a stack pointer. The where command does not report routines that have no frame pointer and routines that have been inlined.

Examining the Contents of Memory and Registers

You can issue commands in the command window to display the contents of memory addresses and registers.

Displaying Memory

To display the contents of an address, specify the address on the command line, followed by a slash (/). For example,

0x10000/

If you specify the address as a period, Prism displays the contents of the memory address following the one printed most recently.

Specify a symbolic address by preceding the name with an &. For example,

&x/

prints the contents of memory for variable x. The Prism output, for example, might be

0x000237f8:  0x3f800000

The address you specify can be an expression made up of other addresses and the operators +, -, and indirection (unary *). For example,

0x1000+100/

prints the contents of the location 100 addresses above address 0x1000.

After the slash you can specify how memory is to be displayed. Formats that are supported are listed in Table 4-1.

Table 4-1 Memory Address Formats

Format 

Description 

d

Print a short word in decimal 

D

Print a long word in decimal 

o

Print a short word in octal 

O

Print a long word in octal 

x

Print a short word in hexadecimal 

X

Print a long word in hexadecimal 

b

Print a byte in octal 

c

Print a byte as a character 

s

Print a string of characters terminated by a null byte 

f

Print a single-precision real number 

F

Print a double-precision real number 

i

Print the machine instruction 

The initial format is X. If you omit the format in your command, you get either X (if you haven't previously specified a format) or the format you specified previously.

You can print the contents of multiple addresses by specifying a number after the slash (and before the format). For example,

0x1000/8X

displays the contents of eight memory locations starting at address 0x1000. Contents are displayed as hexadecimal long words.

Displaying the Contents of Registers

You can examine the contents of registers in the same way that you examine the contents of memory. Specify a register by preceding its name with a dollar sign. For example,

$f0/

prints the contents of the X register.

Specify a number after the slash to print the contents of multiple registers. For example,

$f0/3

prints the contents of registers f0, f1, and f2. The order in which the registers are displayed is that shown in Table 4-1.

You can also specify a format, as described above. The format specifier controls the display of the output; it doesn't affect how much of the register contents is displayed. Thus,

$f0/3X

displays three registers; the output is displayed as hexadecimal longwords.

The registers in the UltraSPARC processor are listed in Table 4-2.

Table 4-2 UltraSPARC Registers

Name 

Register 

$g0-$g7

Global registers (64 bits) 

$o0-$o7

Output registers (64 bits) 

$l0-$l7

Local registers 

$i0-$i7

Input registers 

$psr

Processor state register 

$pc

Program counter 

$npc

Next program counter 

$y

Y register 

$wim

Window invalid mask 

$tbr

Trap base register 

$f0-$f31

Floating-point registers 

$fsr

Floating status register (64 bits) 

$f0f1-$f62f63

Floating-point registers 

$xg0-$xg7

Upper 32 bits of $g0-$g7 (SPARC V8 plus only, or higher)

$xo0-$xo7

Upper 32 bits of $o0-$o7 (SPARC V8 plus only, or higher)

$xfsr

Upper 32 bits of $fsr (SPARC V8 plus only, or higher)

$fprs

Floating-point registers state (SPARC V8 plus only, or higher) 

$tstate

Trap state register (SPARC V8 plus only, or higher) 

$fp

Frame pointer (synonym for $i6)

$sp

Stack pointer (synonym for $o6)