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
|
// TITLE("Long Jump")
//++
//
// Copyright (c) 1993 Microsoft Corporation
//
// Module Name:
//
// longjmp.s
//
// Abstract:
//
// This module implements the MIPS specific routine to perform a long
// jump operation.
//
// 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:
//
//--
#include "ksmips.h"
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.
//
//--
.struct 0
.space 4 * 4 // argument save area
LjEr: .space ExceptionRecordLength // exception record
.space 4 * 3 // fill
LjRa: .space 4 // saved return address
LongjmpFrameLength:
NESTED_ENTRY(longjmp, LongjmpFrameLength, zero)
subu sp,sp,LongjmpFrameLength // allocate stack frame
sw ra,LjRa(sp) // save return address
PROLOGUE_END
bne zero,a1,10f // if ne, return value specified
li a1,1 // set return value to nonzero value
10: lw v0,JbType(a0) // get safe setjmp/longjmp flag
bne zero,v0,20f // if ne, provide safe longjmp
//
// Provide unsafe handling of longjmp.
//
move v0,a1 // set return value
ldc1 f20,JbFltF20(a0) // restore floating registers f20 - f31
ldc1 f22,JbFltF22(a0) //
ldc1 f24,JbFltF24(a0) //
ldc1 f26,JbFltF26(a0) //
ldc1 f28,JbFltF28(a0) //
ldc1 f30,JbFltF30(a0) //
lw s0,JbIntS0(a0) // restore integer registers s0 - s8
lw s1,JbIntS1(a0) //
lw s2,JbIntS2(a0) //
lw s3,JbIntS3(a0) //
lw s4,JbIntS4(a0) //
lw s5,JbIntS5(a0) //
lw s6,JbIntS6(a0) //
lw s7,JbIntS7(a0) //
lw s8,JbIntS8(a0) //
lw a1,JbFir(a0) // get setjmp return address
lw sp,JbIntSp(a0) // restore stack pointer
j a1 // jump back to setjmp site
//
// Provide safe handling of longjmp.
//
// An exception record is constructed that contains a log jump status
// code and the first exception information parameter is a pointer to
// the jump buffer.
//
20: li v0,STATUS_LONGJUMP // get long jump status code
sw v0,LjEr + ErExceptionCode(sp) // set exception code
sw zero,LjEr + ErExceptionFlags(sp) // clear exception flags
sw zero,LjEr + ErExceptionRecord(sp) // clear associate record
sw zero,LjEr + ErExceptionAddress(sp) // clear exception address
li v0,1 // set number of parameters
sw v0,LjEr + ErNumberParameters(sp) //
sw a0,LjEr + ErExceptionInformation(sp) // set jump buffer address
move a3,a1 // set return value
addu a2,sp,LjEr // compute exception record address
lw a1,JbFir(a0) // set target instruction address
lw a0,JbType(a0) // set target virtual frame address
jal RtlUnwind // finish in common code
b 20b
.end longjmp
|