Changeset 0bb0b8d in rtems-docs


Ignore:
Timestamp:
Nov 9, 2018, 10:28:10 PM (6 months ago)
Author:
Joel Sherrill <joel@…>
Branches:
master
Children:
ae05a27
Parents:
f067ba3
git-author:
Joel Sherrill <joel@…> (11/09/18 22:28:10)
git-committer:
Joel Sherrill <joel@…> (11/19/18 19:11:52)
Message:

cpu-supplement/sparc_v8_stacks_regwin.rst: Basic formatting with TBDs

Leaving notes for follow up as a GCI 2018 task.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpu-supplement/sparc_v8_stacks_regwin.rst

    rf067ba3 r0bb0b8d  
    11.. comment SPDX-License-Identifier: CC-BY-SA-4.0
    22
    3 .. COMMENT: Permission granted by the original author (Peter Magnusson) to
    4 .. COMMENT: convert this page to Rest and include in the RTEMS Documentation.
    5 .. COMMENT: This content is no longer online and only accessible at
    6 .. COMMENT: https://web.archive.org/web/20120205014832/https://www.sics.se/~psm/sparcstack.html
    7 
    8 Understanding stacks and registers in the Sparc architecture(s)
     3.. comment Permission granted by the original author (Peter Magnusson) to
     4.. comment convert this page to Rest and include in the RTEMS Documentation.
     5.. comment This content is no longer online and only accessible at
     6.. comment https://web.archive.org/web/20120205014832/https://www.sics.se/~psm/sparcstack.html
     7
     8.. comment XXX Format Tables
     9.. comment XXX Format Figures (could be code, ascii art, etc.)
     10.. comment XXX double check against web page
     11.. comment XXX Fix Figure references in text
     12.. comment XXX instruction names probably should be marked as code font
     13
     14Understanding stacks and registers in the SPARC architecture(s)
    915===============================================================
    10 The Sparc architecture from Sun Microsystems has some "interesting" characteristics. After having to deal with both compiler, interpreter, OS emulator, and OS porting issues for the Sparc, I decided to gather notes and documentation in one place. If there are any issues you don't find addressed by this page, or if you know of any similar Net resources, let me know. This document is limited to the V8 version of the architecture.
     16The SPARC architecture from Sun Microsystems has some "interesting"
     17characteristics. After having to deal with both compiler, interpreter, OS
     18emulator, and OS porting issues for the SPARC, I decided to gather notes
     19and documentation in one place. If there are any issues you don't find
     20addressed by this page, or if you know of any similar Net resources, let
     21me know. This document is limited to the V8 version of the architecture.
    1122
    1223General Structure
    13 Sparc has 32 general purpose integer registers visible to the program at any given time. Of these, 8 registers are global registers and 24 registers are in a register window. A window consists of three groups of 8 registers, the out, local, and in registers. See table 1. A Sparc implementation can have from 2 to 32 windows, thus varying the number of registers from 40 to 520. Most implentations have 7 or 8 windows. The variable number of registers is the principal reason for the Sparc being "scalable".
    14 
    15 At any given time, only one window is visible, as determined by the current window pointer (CWP) which is part of the processor status register (PSR). This is a five bit value that can be decremented or incremented by the SAVE and RESTORE instructions, respectively. These instructions are generally executed on procedure call and return (respectively). The idea is that the in registers contain incoming parameters, the local register constitute scratch registers, the out registers contain outgoing parameters, and the global registers contain values that vary little between executions. The register windows overlap partially, thus the out registers become renamed by SAVE to become the in registers of the called procedure. Thus, the memory traffic is reduced when going up and down the procedure call. Since this is a frequent operation, performance is improved.
    16 
    17 (That was the idea, anyway. The drawback is that upon interactions with the system the registers need to be flushed to the stack, necessitating a long sequence of writes to memory of data that is often mostly garbage. Register windows was a bad idea that was caused by simulation studies that considered only programs in isolation, as opposed to multitasking workloads, and by considering compilers with poor optimization. It also caused considerable problems in implementing high-end Sparc processors such as the SuperSparc, although more recent implementations have dealt effectively with the obstacles. Register windows is now part of the compatibility legacy and not easily removed from the architecture.)
    18 
    19 Register Group  Mnemonic        Register Address
    20 global  %g0-%g7         r[0]-r[7]
    21 out     %o0-%o7         r[8]-r[15]
    22 local   %l0-%l7         r[16]-r[23]
    23 in      %i0-%i7         r[24]-r[31]
     24-----------------
     25SPARC has 32 general purpose integer registers visible to the program
     26at any given time. Of these, 8 registers are global registers and 24
     27registers are in a register window. A window consists of three groups
     28of 8 registers, the out, local, and in registers. See table 1. A SPARC
     29implementation can have from 2 to 32 windows, thus varying the number
     30of registers from 40 to 520. Most implentations have 7 or 8 windows. The
     31variable number of registers is the principal reason for the SPARC being
     32"scalable".
     33
     34At any given time, only one window is visible, as determined by the
     35current window pointer (CWP) which is part of the processor status
     36register (PSR). This is a five bit value that can be decremented or
     37incremented by the SAVE and RESTORE instructions, respectively. These
     38instructions are generally executed on procedure call and return
     39(respectively). The idea is that the in registers contain incoming
     40parameters, the local register constitute scratch registers, the out
     41registers contain outgoing parameters, and the global registers contain
     42values that vary little between executions. The register windows overlap
     43partially, thus the out registers become renamed by SAVE to become the in
     44registers of the called procedure. Thus, the memory traffic is reduced
     45when going up and down the procedure call. Since this is a frequent
     46operation, performance is improved.
     47
     48(That was the idea, anyway. The drawback is that upon interactions
     49with the system the registers need to be flushed to the stack,
     50necessitating a long sequence of writes to memory of data that is
     51often mostly garbage. Register windows was a bad idea that was caused
     52by simulation studies that considered only programs in isolation, as
     53opposed to multitasking workloads, and by considering compilers with
     54poor optimization. It also caused considerable problems in implementing
     55high-end SPARC processors such as the SuperSPARC, although more recent
     56implementations have dealt effectively with the obstacles. Register
     57windows is now part of the compatibility legacy and not easily removed
     58from the architecture.)
     59
     60.. comment XXX FIX FORMATTING
     61
     62+------------+------------+---------------+
     63|  Register  |  Mnemonic  |    Register   |
     64|  Group     |            |    Address    |
     65+============+============+===============+
     66+   global   +  %g0-%g7   + r[0] - r[7]   +
     67+------------+------------+---------------+
     68+    out     +  %o0-%o7   + r[8] - r[15]  +
     69+------------+------------+---------------+
     70+   local    +  %l0-%l7   + r[16] - r[23] +
     71+------------+------------+---------------+
     72+    in      +  %i0-%i7   + r[24] - r[31] +
     73+------------+------------+---------------+
    2474
    2575Table 1 - Visible Registers
    2676
    27 The overlap of the registers is illustrated in figure 1. The figure shows an implementation with 8 windows, numbered 0 to 7 (labeled w0 to w7 in the figure).. Each window corresponds to 24 registers, 16 of which are shared with "neighboring" windows. The windows are arranged in a wrap-around manner, thus window number 0 borders window number 7. The common cause of changing the current window, as pointed to by CWP, is the RESTORE and SAVE instuctions, shown in the middle. Less common is the supervisor RETT instruction (return from trap) and the trap event (interrupt, exception, or TRAP instruction).
     77The overlap of the registers is illustrated in figure 1. The figure
     78shows an implementation with 8 windows, numbered 0 to 7 (labeled w0 to
     79w7 in the figure).. Each window corresponds to 24 registers, 16 of which
     80are shared with "neighboring" windows. The windows are arranged in a
     81wrap-around manner, thus window number 0 borders window number 7. The
     82common cause of changing the current window, as pointed to by CWP, is
     83the RESTORE and SAVE instuctions, shown in the middle. Less common is
     84the supervisor RETT instruction (return from trap) and the trap event
     85(interrupt, exception, or TRAP instruction).
     86
     87.. comment XXX insert graphic from website (redraw if needed)
    2888
    2989Figure 1 - Windowed Registers
    3090
    31 The "WIM" register is also indicated in the top left of figure 1. The window invalid mask is a bit map of valid windows. It is generally used as a pointer, i.e. exactly one bit is set in the WIM register indicating which window is invalid (in the figure it's window 7). Register windows are generally used to support procedure calls, so they can be viewed as a cache of the stack contents. The WIM "pointer" indicates how many procedure calls in a row can be taken without writing out data to memory. In the figure, the capacity of the register windows is fully utilized. An additional call will thus exceed capacity, triggering a window overflow trap. At the other end, a window underflow trap occurs when the register window "cache" if empty and more data needs to be fetched from memory.
     91The "WIM" register is also indicated in the top left of Figure 1. The
     92window invalid mask is a bit map of valid windows. It is generally used
     93as a pointer, i.e. exactly one bit is set in the WIM register indicating
     94which window is invalid (in the figure it's window 7). Register windows
     95are generally used to support procedure calls, so they can be viewed
     96as a cache of the stack contents. The WIM "pointer" indicates how
     97many procedure calls in a row can be taken without writing out data to
     98memory. In the figure, the capacity of the register windows is fully
     99utilized. An additional call will thus exceed capacity, triggering a
     100window overflow trap. At the other end, a window underflow trap occurs
     101when the register window "cache" if empty and more data needs to be
     102fetched from memory.
    32103
    33104Register Semantics
    34 The Sparc Architecture includes recommended software semantics. These are described in the architecture manual, the Sparc ABI (application binary interface) standard, and, unfortunately, in various other locations as well (including header files and compiler documentation).
     105------------------
     106
     107The SPARC Architecture includes recommended software semantics. These are
     108described in the architecture manual, the SPARC ABI (application binary
     109interface) standard, and, unfortunately, in various other locations as
     110well (including header files and compiler documentation).
    35111
    36112Figure 2 shows a summary of register contents at any given time.
     113
     114.. comment XXX FIX FORMATTING
     115
     116.. code-block:: c
    37117
    38118                 %g0  (r00)       always zero
     
    78158[3] assumed by caller to be preserved across a procedure call
    79159
    80 Figure 2 - Sparc register semantics
     160Figure 2 - SPARC register semantics
    81161
    82162Particular compilers are likely to vary slightly.
    83163
    84 Note that globals %g2-%g4 are reserved for the "application", which includes libraries and compiler. Thus, for example, libraries may overwrite these registers unless they've been compiled with suitable flags. Also, the "reserved" registers are presumed to be allocated (in the future) bottom-up, i.e. %g7 is currently the "safest" to use.
     164Note that globals %g2-%g4 are reserved for the "application", which
     165includes libraries and compiler. Thus, for example, libraries may
     166overwrite these registers unless they've been compiled with suitable
     167flags. Also, the "reserved" registers are presumed to be allocated
     168(in the future) bottom-up, i.e. %g7 is currently the "safest" to use.
    85169
    86170Optimizing linkers and interpreters are exmples that use global registers.
    87171
    88172Register Windows and the Stack
    89 The sparc register windows are, naturally, intimately related to the stack. In particular, the stack pointer (%sp or %o6) must always point to a free block of 64 bytes. This area is used by the operating system (Solaris, SunOS, and Linux at least) to save the current local and in registers upon a system interupt, exception, or trap instruction. (Note that this can occur at any time.)
    90 
    91 Other aspects of register relations with memory are programming convention. The typical, and recommended, layout of the stack is shown in figure 3. The figure shows a stack frame.
     173------------------------------
     174
     175The SPARC register windows are, naturally, intimately related to the
     176stack. In particular, the stack pointer (%sp or %o6) must always point
     177to a free block of 64 bytes. This area is used by the operating system
     178(Solaris, SunOS, and Linux at least) to save the current local and in
     179registers upon a system interupt, exception, or trap instruction. (Note
     180that this can occur at any time.)
     181
     182Other aspects of register relations with memory are programming
     183convention. The typical, and recommended, layout of the stack is shown
     184in figure 3. The figure shows a stack frame.
     185
     186.. comment XXX FIX FORMATTING
     187
     188.. code-block:: c
    92189
    93190                    low addresses
     
    129226Figure 3 - Stack frame contents
    130227
    131 Note that the top boxes of figure 3 are addressed via the stack pointer (%sp), as positive offsets (including zero), and the bottom boxes are accessed over the frame pointer using negative offsets (excluding zero), and that the frame pointer is the old stack pointer. This scheme allows the separation of information known at compile time (number and size of local parameters, etc) from run-time information (size of blocks allocated by alloca()).
     228Note that the top boxes of figure 3 are addressed via the stack pointer
     229(%sp), as positive offsets (including zero), and the bottom boxes are
     230accessed over the frame pointer using negative offsets (excluding zero),
     231and that the frame pointer is the old stack pointer. This scheme allows
     232the separation of information known at compile time (number and size
     233of local parameters, etc) from run-time information (size of blocks
     234allocated by alloca()).
    132235
    133236"addressable scalar automatics" is a fancy name for local variables.
    134237
    135 The clever nature of the stack and frame pointers are that they are always 16 registers apart in the register windows. Thus, a SAVE instruction will make the current stack pointer into the frame pointer and, since the SAVE instruction also doubles as an ADD, create a new stack pointer. Figure 4 illustrates what the top of a stack might look like during execution. (The listing is from the "pwin" command in the SimICS simulator.)
     238The clever nature of the stack and frame pointers are that they are always
     23916 registers apart in the register windows. Thus, a SAVE instruction will
     240make the current stack pointer into the frame pointer and, since the SAVE
     241instruction also doubles as an ADD, create a new stack pointer. Figure 4
     242illustrates what the top of a stack might look like during execution. (The
     243listing is from the "pwin" command in the SimICS simulator.)
     244
     245.. comment XXX FIX FORMATTING
     246
     247.. code-block:: c
    136248
    137249                  REGISTER WINDOWS
     
    215327Figure 4 - Sample stack contents
    216328
    217 Note how the stack contents are not necessarily synchronized with the registers. Various events can cause the register windows to be "flushed" to memory, including most system calls. A programmer can force this update by using ST_FLUSH_WINDOWS trap, which also reduces the number of valid windows to the minimum of 1.
    218 
    219 Writing a library for multithreaded execution is an example that requires explicit flushing, as is longjmp().
     329Note how the stack contents are not necessarily synchronized with the
     330registers. Various events can cause the register windows to be "flushed"
     331to memory, including most system calls. A programmer can force this
     332update by using ST_FLUSH_WINDOWS trap, which also reduces the number of
     333valid windows to the minimum of 1.
     334
     335Writing a library for multithreaded execution is an example that requires
     336explicit flushing, as is longjmp().
    220337
    221338Procedure epilogue and prologue
    222 The stack frame described in the previous section leads to the standard entry/exit mechanisms listed in figure 5.
     339-------------------------------
     340
     341The stack frame described in the previous section leads to the standard
     342entry/exit mechanisms listed in figure 5.
     343
     344.. comment XXX FIX FORMATTING
     345
     346.. code-block:: c
    223347
    224348  function:
     
    233357Figure 5 - Epilogue/prologue in procedures
    234358
    235 The SAVE instruction decrements the CWP, as discussed earlier, and also performs an addition. The constant "C" that is used in the figure to indicate the amount of space to make on the stack, and thus corresponds to the frame contents in Figure 3. The minimum is therefore the 16 words for the LOCAL and IN registers, i.e. (hex) 0x40 bytes.
    236 
    237 A confusing element of the SAVE instruction is that the source operands (the first two parameters) are read from the old register window, and the destination operand (the rightmost parameter) is written to the new window. Thus, allthough "%sp" is indicated as both source and destination, the result is actually written into the stack pointer of the new window (the source stack pointer becomes renamed and is now the frame pointer).
    238 
    239 The return instructions are also a bit particular. ret is a synthetic instruction, corresponding to jmpl (jump linked). This instruction jumps to the address resulting from adding 8 to the %i7 register. The source instruction address (the address of the ret instruction itself) is written to the %g0 register, i.e. it is discarded.
    240 
    241 The restore instruction is similarly a synthetic instruction, and is just a short form for a restore that choses not to perform an addition.
     359The SAVE instruction decrements the CWP, as discussed earlier, and also
     360performs an addition. The constant "C" that is used in the figure to
     361indicate the amount of space to make on the stack, and thus corresponds
     362to the frame contents in Figure 3. The minimum is therefore the 16 words
     363for the LOCAL and IN registers, i.e. (hex) 0x40 bytes.
     364
     365A confusing element of the SAVE instruction is that the source operands
     366(the first two parameters) are read from the old register window, and
     367the destination operand (the rightmost parameter) is written to the new
     368window. Thus, allthough "%sp" is indicated as both source and destination,
     369the result is actually written into the stack pointer of the new window
     370(the source stack pointer becomes renamed and is now the frame pointer).
     371
     372The return instructions are also a bit particular. ret is a synthetic
     373instruction, corresponding to jmpl (jump linked). This instruction
     374jumps to the address resulting from adding 8 to the %i7 register. The
     375source instruction address (the address of the ret instruction itself)
     376is written to the %g0 register, i.e. it is discarded.
     377
     378The restore instruction is similarly a synthetic instruction, and is
     379just a short form for a restore that choses not to perform an addition.
    242380
    243381The calling instruction, in turn, typically looks as follows:
     382
     383.. comment XXX FIX FORMATTING
     384
     385.. code-block:: c
    244386
    245387    call <function>    ; jmpl <address>, %o7
    246388    mov 0, %o0
    247389
    248 Again, the call instruction is synthetic, and is actually the same instruction that performs the return. This time, however, it is interested in saving the return address, into register %o7. Note that the delay slot is often filled with an instruction related to the parameters, in this example it sets the first parameter to zero.
     390Again, the call instruction is synthetic, and is actually the same
     391instruction that performs the return. This time, however, it is interested
     392in saving the return address, into register %o7. Note that the delay
     393slot is often filled with an instruction related to the parameters,
     394in this example it sets the first parameter to zero.
    249395
    250396Note also that the return value is also generally passed in %o0.
    251397
    252 Leaf procedures are different. A leaf procedure is an optimization that reduces unnecessary work by taking advantage of the knowledge that no call instructions exist in many procedures. Thus, the save/restore couple can be eliminated. The downside is that such a procedure may only use the out registers (since the in and local registers actually belong to the caller). See Figure 6.
     398Leaf procedures are different. A leaf procedure is an optimization that
     399reduces unnecessary work by taking advantage of the knowledge that no
     400call instructions exist in many procedures. Thus, the save/restore couple
     401can be eliminated. The downside is that such a procedure may only use
     402the out registers (since the in and local registers actually belong to
     403the caller). See Figure 6.
     404
     405.. comment XXX FIX FORMATTING
     406
     407.. code-block:: c
    253408
    254409  function:
     
    263418Figure 6 - Epilogue/prologue in leaf procedures
    264419
    265 Note in the figure that there is only one instruction overhead, namely the retl instruction. retl is also synthetic (return from leaf subroutine), is again a variant of the jmpl instruction, this time with %o7+8 as target.
    266 
    267 Yet another variation of epilogue is caused by tail call elimination, an optimization supported by some compilers (including Sun's C compiler but not GCC). If the compiler detects that a called function will return to the calling function, it can replace its place on the stack with the called function. Figure 7 contains an example.
     420Note in the figure that there is only one instruction overhead, namely the
     421retl instruction. retl is also synthetic (return from leaf subroutine), is
     422again a variant of the jmpl instruction, this time with %o7+8 as target.
     423
     424Yet another variation of epilogue is caused by tail call elimination,
     425an optimization supported by some compilers (including Sun's C compiler
     426but not GCC). If the compiler detects that a called function will return
     427to the calling function, it can replace its place on the stack with the
     428called function. Figure 7 contains an example.
     429
     430.. comment XXX FIX FORMATTING
     431
     432.. code-block:: c
    268433
    269434      int
     
    286451Figure 7 - Example of tail call elimination
    287452
    288 Note that the call instruction overwrites register %o7 with the program counter. Therefore the above code saves the old value of %o7, and restores it in the delay slot of the call instruction. If the function call is register indirect, this twiddling with %o7 can be avoided, but of course that form of call is slower on modern processors.
    289 
    290 The benefit of tail call elimination is to remove an indirection upon return. It is also needed to reduce register window usage, since otherwise the foo() function in Figure 7 would need to allocate a stack frame to save the program counter.
    291 
    292 A special form of tail call elimination is tail recursion elimination, which detects functions calling themselves, and replaces it with a simple branch. Figure 8 contains an example.
     453Note that the call instruction overwrites register %o7 with the program
     454counter. Therefore the above code saves the old value of %o7, and restores
     455it in the delay slot of the call instruction. If the function call is
     456register indirect, this twiddling with %o7 can be avoided, but of course
     457that form of call is slower on modern processors.
     458
     459The benefit of tail call elimination is to remove an indirection upon
     460return. It is also needed to reduce register window usage, since otherwise
     461the foo() function in Figure 7 would need to allocate a stack frame to
     462save the program counter.
     463
     464A special form of tail call elimination is tail recursion elimination,
     465which detects functions calling themselves, and replaces it with a simple
     466branch. Figure 8 contains an example.
     467
     468.. comment XXX FIX FORMATTING
     469
     470.. code-block:: c
    293471
    294472        int
     
    312490Figure 8 - Example of tail recursion elimination
    313491
    314 Needless to say, these optimizations produce code that is difficult to debug.
     492Needless to say, these optimizations produce code that is difficult
     493to debug.
    315494
    316495Procedures, stacks, and debuggers
    317 When debugging an application, your debugger will be parsing the binary and consulting the symbol table to determine procedure entry points. It will also travel the stack frames "upward" to determine the current call chain.
    318 
    319 When compiling for debugging, compilers will generate additional code as well as avoid some optimizations in order to allow reconstructing situations during execution. For example, GCC/GDB makes sure original parameter values are kept intact somewhere for future parsing of the procedure call stack. The live in registers other than %i0 are not touched. %i0 itself is copied into a free local register, and its location is noted in the symbol file. (You can find out where variables reside by using the "info address" command in GDB.)
    320 
    321 Given that much of the semantics relating to stack handling and procedure call entry/exit code is only recommended, debuggers will sometimes be fooled. For example, the decision as to wether or not the current procedure is a leaf one or not can be incorrect. In this case a spurious procedure will be inserted between the current procedure and it's "real" parent. Another example is when the application maintains its own implicit call hierarchy, such as jumping to function pointers. In this case the debugger can easily become totally confused.
     496---------------------------------
     497
     498When debugging an application, your debugger will be parsing the binary
     499and consulting the symbol table to determine procedure entry points. It
     500will also travel the stack frames "upward" to determine the current
     501call chain.
     502
     503When compiling for debugging, compilers will generate additional code
     504as well as avoid some optimizations in order to allow reconstructing
     505situations during execution. For example, GCC/GDB makes sure original
     506parameter values are kept intact somewhere for future parsing of
     507the procedure call stack. The live in registers other than %i0 are
     508not touched. %i0 itself is copied into a free local register, and its
     509location is noted in the symbol file. (You can find out where variables
     510reside by using the "info address" command in GDB.)
     511
     512Given that much of the semantics relating to stack handling and procedure
     513call entry/exit code is only recommended, debuggers will sometimes
     514be fooled. For example, the decision as to wether or not the current
     515procedure is a leaf one or not can be incorrect. In this case a spurious
     516procedure will be inserted between the current procedure and it's "real"
     517parent. Another example is when the application maintains its own implicit
     518call hierarchy, such as jumping to function pointers. In this case the
     519debugger can easily become totally confused.
    322520
    323521The window overflow and underflow traps
    324 When the SAVE instruction decrements the current window pointer (CWP) so that it coincides with the invalid window in the window invalid mask (WIM), a window overflow trap occurs. Conversely, when the RESTORE or RETT instructions increment the CWP to coincide with the invalid window, a window underflow trap occurs.
    325 
    326 Either trap is handled by the operating system. Generally, data is written out to memory and/or read from memory, and the WIM register suitably altered.
    327 
    328 The code in Figure 9 and Figure 10 below are bare-bones handlers for the two traps. The text is directly from the source code, and sort of works. (As far as I know, these are minimalistic handlers for Sparc V8). Note that there is no way to directly access window registers other than the current one, hence the code does additional save/restore instructions. It's pretty tricky to understand the code, but figure 1 should be of help.
     522---------------------------------------
     523
     524When the SAVE instruction decrements the current window pointer (CWP)
     525so that it coincides with the invalid window in the window invalid mask
     526(WIM), a window overflow trap occurs. Conversely, when the RESTORE or
     527RETT instructions increment the CWP to coincide with the invalid window,
     528a window underflow trap occurs.
     529
     530Either trap is handled by the operating system. Generally, data is
     531written out to memory and/or read from memory, and the WIM register
     532suitably altered.
     533
     534The code in Figure 9 and Figure 10 below are bare-bones handlers for
     535the two traps. The text is directly from the source code, and sort of
     536works. (As far as I know, these are minimalistic handlers for SPARC
     537V8). Note that there is no way to directly access window registers
     538other than the current one, hence the code does additional save/restore
     539instructions. It's pretty tricky to understand the code, but figure 1
     540should be of help.
     541
     542.. comment XXX FIX FORMATTING
     543
     544.. code-block:: c
    329545
    330546        /* a SAVE instruction caused a trap */
    331 window_overflow:
     547  window_overflow:
    332548        /* rotate WIM on bit right, we have 8 windows */
    333549        mov %wim,%l3
     
    367583Figure 9 - window_underflow trap handler
    368584
     585
     586.. code-block:: c
     587
     588
    369589        /* a RESTORE instruction caused a trap */
    370 window_underflow:
     590  window_underflow:
    371591
    372592        /* rotate WIM on bit LEFT, we have 8 windows */
Note: See TracChangeset for help on using the changeset viewer.