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
|