summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/mips/setjmpex.s
blob: 31385e394ebc52a5705729222275d73ac75c3a8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//      TITLE("Set Jump Extended")
//++
//
// Copyright (c) 1993  Microsoft Corporation
//
// Module Name:
//
//    setjmpex.s
//
// Abstract:
//
//    This module implements the MIPS specific routine to provide SAFE
//    handling of setjmp/longjmp with respect to structured exception
//    handling.
//
// Author:
//
//    David N. Cutler (davec) 2-Apr-1993
//
// Environment:
//
//    Any mode.
//
// Revision History:
//
//--

#include "ksmips.h"

//
// Define variable that will cause setjmp/longjmp to be safe with respect
// to structured exception handling.
//

        .globl  _setjmpexused
        .data
_setjmpexused:
        .word   _setjmpex               // set address of safe setjmp routine

        SBTTL("Set Jump Extended")
//++
//
// int
// _setjmpex (
//    IN jmp_buf JumpBuffer
//    )
//
// Routine Description:
//
//    This function transfers control to the actual setjmp routine.
//
// Arguments:
//
//    JumpBuffer (a0) - Supplies the address of a jump buffer to store the
//       jump information.
//
// Return Value:
//
//    A value of zero is returned.
//
//--

        .struct 0
        .space  4 * 4                   // argument save area
SjS0:   .space  4                       // saved integer register s0
SjFl:   .space  4                       // in function flag variable
        .space  4                       // fill
SjRa:   .space  4                       // saved return address
SetjmpFrameLength:

        NESTED_ENTRY(_setjmpex, SetjmpFrameLength, zero)

        subu    sp,sp,SetjmpFrameLength // allocate stack frame
        sw      s0,SjS0(sp)             // save integer register s0
        sw      ra,SjRa(sp)             // save return address
        move    s0,sp                   // set frame pointer

        PROLOGUE_END

        subu    sp,sp,ContextFrameLength + 16 // allocate a context frame

//
// Save the nonvolatile machine state in both the jump buffer and a context
// record that will be used to compute the virtual frame pointer.
//

        sdc1    f20,JbFltF20(a0)        // save floating registers f20 - f31
        sdc1    f22,JbFltF22(a0)        //
        sdc1    f24,JbFltF24(a0)        //
        sdc1    f26,JbFltF26(a0)        //
        sdc1    f28,JbFltF28(a0)        //
        sdc1    f30,JbFltF30(a0)        //
        lw      v0,SjS0(s0)             // get saved integer register s0
        sw      v0,JbIntS0(a0)          // save integer registers s0 - s8
        sw      s1,JbIntS1(a0)          //
        sw      s2,JbIntS2(a0)          //
        sw      s3,JbIntS3(a0)          //
        sw      s4,JbIntS4(a0)          //
        sw      s5,JbIntS5(a0)          //
        sw      s6,JbIntS6(a0)          //
        sw      s7,JbIntS7(a0)          //
        sw      s8,JbIntS8(a0)          //
        sw      ra,JbFir(a0)            // get setjmp return address
        addu    v0,s0,SetjmpFrameLength // compute stack pointer address
        sw      v0,JbIntSp(a0)          // save stack pointer

        sdc1    f20,CxFltF20 + 16(sp)   // save floating registers f20 - f31
        sdc1    f22,CxFltF22 + 16(sp)   //
        sdc1    f24,CxFltF24 + 16(sp)   //
        sdc1    f26,CxFltF26 + 16(sp)   //
        sdc1    f28,CxFltF28 + 16(sp)   //
        sdc1    f30,CxFltF30 + 16(sp)   //
        lw      v0,SjS0(s0)             // get saved integer register s0
        sw      v0,CxIntS0 + 16(sp)     // save integer registers s0 - s8
        sw      s1,CxIntS1 + 16(sp)     //
        sw      s2,CxIntS2 + 16(sp)     //
        sw      s3,CxIntS3 + 16(sp)     //
        sw      s4,CxIntS4 + 16(sp)     //
        sw      s5,CxIntS5 + 16(sp)     //
        sw      s6,CxIntS6 + 16(sp)     //
        sw      s7,CxIntS7 + 16(sp)     //
        sw      s8,CxIntS8 + 16(sp)     // save integer register s8
        sw      gp,CxIntGp + 16(sp)     // save integer register gp
        addu    v0,s0,SetjmpFrameLength // compute stack pointer address
        sw      v0,CxIntSp + 16(sp)     // save stack pointer
        sw      ra,CxIntRa + 16(sp)     // save return address
        sw      ra,CxFir + 16(sp)       // save return address

//
// Perform unwind to determine the virtual frame pointer of the caller.
//

        addu    a0,a0,JbType            // set virtual frame address argument
        sw      a0,4 * 4(sp)            //
        subu    a0,ra,4                 // compute control PC address
        jal     RtlLookupFunctionEntry  // lookup function table address
        lw      a0,SjRa(s0)             // get return address
        subu    a0,a0,4                 // compute control PC address
        move    a1,v0                   // set address of function entry
        addu    a2,sp,16                // compute address of context record
        addu    a3,s0,SjFl              // set address of in function variable
        sw      zero,4 * 5(sp)          // set context pointer array address
        jal     RtlVirtualUnwind        // compute virtual frame pointer value

//
// Set return value, restore registers, deallocate stack frame, and return.
//

        move    v0,zero                 // set return value
        move    sp,s0                   // reset stack pointer
        lw      s0,SjS0(sp)             // restore integer register s0
        lw      ra,SjRa(sp)             // restore return address
        addu    sp,sp,SetjmpFrameLength // deallocate stack frame
        j       ra                      // return

        .end    _setjmpex