summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/alpha/longjmp.s
blob: 412e3e655f652efe038a3dea30a79540feae4bbb (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//      TITLE("Long Jump")
//++
//
// Copyright (c) 1993  Microsoft Corporation
// Copyright (c) 1993  Digital Equipment Corporation
//
// Module Name:
//
//    longjmp.s
//
// Abstract:
//
//    This module implements the Alpha specific routine to perform a long
//    jump operation. Three jump buffer types are supported: unsafe, safe
//    acc-style (virtual frame pointer, PC mapped SEH scope), and safe
//    GEM-style (real frame pointer, SEB-based SEH context).
//
//    N.B. This routine conditionally provides UNSAFE handling of longjmp
//         which is NOT integrated with structured exception handling. The
//         determination is made based on whether an unitialized variable
//         has been set to a nonzero value.
//
// Author:
//
//    David N. Cutler (davec) 2-Apr-1993
//
// Environment:
//
//    Any mode.
//
// Revision History:
//
//    Thomas Van Baak (tvb) 22-Apr-1993
//
//        Adapted for Alpha AXP.
//
//--

#include "ksalpha.h"

//
// Define jump buffer types.
//
//    _JMPBUF_TYPE_ZERO was used for Beta2 which functions the same as
//        _JMPBUF_TYPE_ACC.
//
//    _JMPBUF_TYPE_FAST is for jump buffers containing the set of
//        non-volatile integer and floating registers. This form
//        of setjmp/longjmp is not compatible with SEH.
//
//    _JMPBUF_TYPE_ACC is for setjmp/longjmp compatible with SEH.
//        The Alpha acc compiler uses a virtual frame pointer.
//
//    _JMPBUF_TYPE_GEM is for setjmp/longjmp compatible with SEH.
//        The Alpha GEM C compiler uses a real frame pointer, and
//        SEH scope is maintained with a SEB pointer.
//

#define _JMPBUF_TYPE_ZERO 0
#define _JMPBUF_TYPE_FAST 1
#define _JMPBUF_TYPE_ACC  2
#define _JMPBUF_TYPE_GEM  3

        SBTTL("Long Jump")
//++
//
// int
// longjmp (
//    IN jmp_buf JumpBuffer,
//    IN int ReturnValue
//    )
//
// Routine Description:
//
//    This function performs a long jump to the context specified by the
//    jump buffer.
//
// Arguments:
//
//    JumpBuffer (a0) - Supplies the address of a jump buffer that contains
//       jump information.
//
//    ReturnValue (a1) - Supplies the value that is to be returned to the
//       caller of set jump.
//
// Return Value:
//
//    None.
//
//--

        LEAF_ENTRY(longjmp)

        ldil    t0, 1                   // force nonzero value, if
        cmoveq  a1, t0, a1              //   given return value is zero

        ldl     t1, JbType(a0)          // get setjmp context type flag
        subq    t1, 1, t2               // if eq 1, fast, unsafe longjmp
        bne     t2, 10f                 // otherwise, provide safe longjmp

//
// Type 0x1: Provide unsafe handling of longjmp.
//

        mov     a1, v0                  // set return value

        ldt     f2, JbFltF2(a0)         // restore floating registers f2 - f9
        ldt     f3, JbFltF3(a0)         //
        ldt     f4, JbFltF4(a0)         //
        ldt     f5, JbFltF5(a0)         //
        ldt     f6, JbFltF6(a0)         //
        ldt     f7, JbFltF7(a0)         //
        ldt     f8, JbFltF8(a0)         //
        ldt     f9, JbFltF9(a0)         //

        ldq     s0, JbIntS0(a0)         // restore integer registers s0 - s6/fp
        ldq     s1, JbIntS1(a0)         //
        ldq     s2, JbIntS2(a0)         //
        ldq     s3, JbIntS3(a0)         //
        ldq     s4, JbIntS4(a0)         //
        ldq     s5, JbIntS5(a0)         //
        ldq     fp, JbIntS6(a0)         //

        ldq     a1, JbFir(a0)           // get setjmp return address
        ldq     sp, JbIntSp(a0)         // restore stack pointer
        jmp     zero, (a1)              // jump back to setjmp site

//
// Type 0x0: Provide safe handling of longjmp (idw 404 style).
// Type 0x2: Provide safe handling of longjmp (acc style).
//

10:     bic     t1, 0x2, t2             // if 0 or 2, safe acc longjmp
        bne     t2, longjmpRfp          // if not, safe GEM longjmp

        mov     a1, a3                  // set return value
        mov     zero, a2                // set exception record addres
        ldl     a1, JbPc(a0)            // set target instruction address
        ldl     a0, JbFp(a0)            // set target virtual frame pointer
        br      zero, RtlUnwind         // finish in common code

        .end    longjmp

        SBTTL("Long Jump - GEM")

        .struct 0
LjRa:   .space  8                       // saved return address
        .space  8                       // padding for 16-byte stack alignment
LjEr:   .space  ExceptionRecordLength   // local exception record
LongjmpFrameLength:

//
// Type 0x3: Provide safe handling of longjmp (GEM style).
//

        NESTED_ENTRY(longjmpRfp, LongjmpFrameLength, ra)

        lda     sp, -LongjmpFrameLength(sp) // allocate stack frame
        stq     ra, LjRa(sp)            // save return address

        PROLOGUE_END

//
// Set up the following local exception record:
//
//     ExceptionRecord.ExceptionCode = STATUS_UNWIND;
//     ExceptionRecord.ExceptionFlags = EXCEPTION_UNWINDING;
//     ExceptionRecord.ExceptionRecord = NULL;
//     ExceptionRecord.ExceptionAddress = 0;
//     ExceptionRecord.NumberParameters = 1;
//     ExceptionRecord.ExceptionInformation[0] = Seb;
//

10:     mov     a1, a3                      // set return value
        lda     a2, LjEr(sp)                // set exception record address

        ldil    t0, STATUS_UNWIND           // get status code
        stl     t0, ErExceptionCode(a2)     // store in exception record
        ldil    t1, EXCEPTION_UNWINDING     // get exception flags
        stl     t1, ErExceptionFlags(a2)    // store in exception record
        stl     zero, ErExceptionRecord(a2) // store in exception record
        stl     zero, ErExceptionAddress(a2) // store in exception record
        ldil    t2, 1                       // get number of parameters
        stl     t2, ErNumberParameters(a2)  // store in exception record
        ldl     t3, JbSeb(a0)               // get SEB pointer
        stl     t3, ErExceptionInformation(a2) // store in exception record
        ldl     a1, JbPc(a0)                // set target instruction address
        ldl     a0, JbFp(a0)                // set target real frame pointer

        bsr     ra, RtlUnwindRfp            // finish in common code

        .end    longjmpRfp