aboutsummaryrefslogtreecommitdiff
path: root/unix/as.linux64/zsvjmp_c
blob: 2b42a0de1cb25b578b3149db1c43bf580ea646ce (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
/*
# ZSVJMP, ZDOJMP -- Set up a jump (non-local goto) by saving the processor
# registers in the buffer jmpbuf.  A subsequent call to ZDOJMP restores
# the registers, effecting a call in the context of the procedure which
# originally called ZSVJMP, but with the new status code.  These are Fortran
# callable procedusres.
#
#		zsvjmp (jmp_buf, status)	# (returns status)
#		zdojmp (jmp_buf, status)	# (passes status to zsvjmp)
#
# These routines are directly comparable to the UNIX setjmp/longjmp, except
# that they are Fortran callable kernel routines, i.e., trailing underscore,
# call by reference, and no function returns.  ZSVJMP requires an assembler
# jacket routine to avoid modifying the call stack, but relies upon setjmp
# to do the real work.  ZDOJMP is implemented as a portable C routine in OS,
# calling longjmp to do the restore.  In these routines, JMP_BUF consists
# of one longword containing the address of the STATUS variable, followed
# by the "jmp_buf" used by setjmp/longjmp.
*/


#ifdef I386

/*
asm("# Set the address of the MEM common to zero.");
asm(".globl	mem_");
asm("	mem_	=	0");
*/

/*
#if defined(MACOSX)
asm(".globl	_mem_");
asm("	_mem_	=	0");
#endif
*/

#if defined(LINUX)
asm(".text");
asm(".globl	zsvjmp_");
asm("zsvjmp_:");
asm("	movl	4(%esp), %ecx	# &jmpbuf to ECX");
asm("	movl	8(%esp), %eax	# &status to EAX");
asm("	movl	%eax, (%ecx)	# store &status in jmpbuf[0]");
asm("	movl 	$0, (%eax)	# zero the value of status");
asm("	addl	$4, %ecx	# change stack to point to &jmpbuf[1]");
asm("	movl	%ecx, 4(%esp)	# 	...");
asm("	movl	$0, 8(%esp)	# change arg2 to zero");
asm("	jmp	__sigsetjmp	# let sigsetjmp do the rest");
#endif	/* LINUX */

#if (defined(CYGWIN) || defined(MACOSX))
asm(".text");
asm(".globl	_zsvjmp_");
asm("_zsvjmp_:");
asm("	movl	4(%esp), %ecx	# &jmpbuf to ECX");
asm("	movl	8(%esp), %eax	# &status to EAX");
asm("	movl	%eax, (%ecx)	# store &status in jmpbuf[0]");
asm("	movl 	$0, (%eax)	# zero the value of status");
asm("	addl	$4, %ecx	# change stack to point to &jmpbuf[1]");
asm("	movl	%ecx, 4(%esp)	# 	...");
asm("	movl	$0, 8(%esp)	# change arg2 to zero");
asm("	jmp	_setjmp		# let setjmp do the rest");
#endif	/* CYGWIN || MACOSX */

#endif	/* I386 */


#ifdef X86_64

/*
asm("# Set the address of the MEM common to zero.");
asm(".globl	mem_");
asm("	mem_	=	0");
*/

#ifdef SPP_LP64
/* LP64-SPP */
asm(".text");
asm(".globl	zsvjmp_");
asm("zsvjmp_:");
asm("	# %rsi ... &status  %rdi ... &jumpbuf");
asm("	movq	%rsi, (%rdi)	# store &status in jmpbuf[0]");
asm("	movl	$0, (%rsi)	# zero the value of status");
asm("	addq	$8, %rdi	# change point to &jmpbuf[1]");
asm("	movl	$0, %esi	# change arg2 to zero");
asm("	jmp	__sigsetjmp	# let sigsetjmp do the rest");
#else
/* ILP64-SPP */
asm(".text");
asm(".globl	zsvjmp_");
asm("zsvjmp_:");
asm("	# %rsi ... &status  %rdi ... &jumpbuf");
asm("	movq	%rsi, (%rdi)	# store &status in jmpbuf[0]");
asm("	movq	$0, (%rsi)	# zero the value of status");
asm("	addq	$8, %rdi	# change point to &jmpbuf[1]");
asm("	movl	$0, %esi	# change arg2 to zero");
asm("	jmp	__sigsetjmp	# let sigsetjmp do the rest");
#endif

#endif	/* X86_64 */


#ifdef POWERPC

#if defined(LINUX)
/*
asm("	# Set the address of the MEM common to zero.");
asm("	.globl   mem_");
asm("	mem_ = 0");
*/
asm(".text");
asm("	# ZSVJMP -- SPP callable SETJMP.");
asm("	.align	 2");
asm("	.globl	zsvjmp_");
asm("	.type	zsvjmp_,@function");
asm("zsvjmp_:");
asm("	# R3 = buf, R4 = &status");
asm("	li	r11,0		# r11 = 0");
asm("	stw	r11,0(r4)	# set *status to zero");
asm("	stw	r4,0(r3)	# store &status in buf[0]");
asm("	addi	r3,r3,4		# reference buf[1] for sigsetjmp");
asm("	li	r4,0		# zero signal mask for sigsetjmp");
asm("	b	__sigsetjmp");
#endif	/* LINUX */

#if defined(MACOSX)
/*
asm("	# Set the address of the MEM common to zero.");
asm("	.globl   _mem_");
asm("	_mem_ = 0");
*/
asm(".text");
asm("	# ZSVJMP -- SPP callable SETJMP.");
asm("	.align	2");
asm("	.globl	_zsvjmp_");
asm("_zsvjmp_:");
asm("	# R3 = buf, R4 = &status");
asm("	li	r11,0		# r11 = 0");
asm("	stw	r11,0(r4)	# set *status to zero");
asm("	stw	r4,0(r3)	# store &status in buf[0]");
asm("	addi	r3,r3,4		# reference buf[1] for setjmp");
asm("	b	L_setjmp$stub");
asm("L2:");
asm("	lwz	r1,0(r1)");
asm("	lwz	r0,8(r1)");
asm("	mtlr	r0");
asm("	lmw	r30,-8(r1)");
asm("	blr");
asm("");
asm("	# The setjmp code is only available in a dynamic library on 10.1.");
asm(".picsymbol_stub");
asm("L_setjmp$stub:");
asm("        .indirect_symbol _setjmp");
asm("        mflr	r0");
asm("        bcl	20,31,L1$pb");
asm("L1$pb:");
asm("        mflr	r11");
asm("        addis	r11,r11,ha16(L1$lz-L1$pb)");
asm("        mtlr	r0");
asm("        lwz	r12,lo16(L1$lz-L1$pb)(r11)");
asm("        mtctr	r12");
asm("        addi	r11,r11,lo16(L1$lz-L1$pb)");
asm("        bctr");
asm(".lazy_symbol_pointer");
asm("L1$lz:");
asm("        .indirect_symbol _setjmp");
asm("        .long dyld_stub_binding_helper");
#endif	/* MACOSX */

#endif	/* POWERPC */