3 # This file is part of Cygwin.
5 # This software is a copyrighted work licensed under the terms of the
6 # Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 GetOptions
('cpu=s'=>\
$cpu, 'output-def=s'=>\
$output_def);
20 if (!defined($cpu) || !defined($output_def)) {
21 die "$0: missing required option\n";
24 my $is_x86_64 = $cpu eq 'x86_64';
25 # FIXME? Do other (non-32 bit) arches on Windows still use symbol prefixes?
30 push(@top, cleanup
$_);
31 last if /^\s*exports$/oi;
41 s/\s+DATA$//o and do {
46 if (s/\s+NOSIGFE\s*$//) {
48 } elsif (s/\s+SIGFE(_MAYBE)?$//) {
49 my $func = (split(' '))[2];
50 my $maybe = (defined($1) ?
lc $1 : '') . '_';
51 $sigfe{$func} = '_sigfe' . $maybe . $func;
54 my ($func, $sigfe) = m
%^\s
*(\S
+)(?
:\s
+((?
:NO
)?SIGFE
(?
:_MAYBE
)?
))?
$%o;
55 if (defined($sigfe) && $sigfe =~ /^NO/o) {
59 $_ = '_' . lc($sigfe) . '_' . $func;
61 $_ = $func . ' = ' . $_;
64 s/(\S)\s+(\S)/$1 $2/go;
71 my ($alias, $func) = /^(\S+)\s+=\s+(\S+)\s*$/o;
72 $_ = $alias . ' = ' . $sigfe{$func}
73 if defined($func) && $sigfe{$func};
76 open OUT
, '>', $output_def or die "$0: couldn't open \"$output_def\" - $!\n";
77 push @top, (map {$_ . " DATA\n"} @data), (map {$_ . "\n"} @text);
81 open SIGFE
, '>', 'sigfe.s' or die "$0: couldn't open 'sigfe.s' file for writing - $!\n";
83 for my $k (sort keys %sigfe) {
84 print SIGFE fefunc
($k, $sigfe{$k});
89 my $func = $sym_prefix . shift;
90 my $fe = $sym_prefix . shift;
93 $sigfe_func = ($fe =~ /^(.*)_${func}$/)[0];
103 leaq $func(%rip),%r10
112 if (!$main::first
++) {
114 $res = <<EOF . longjmp () . $res;
115 .include "tlsoffsets"
118 .seh_proc _sigfe_maybe
119 _sigfe_maybe: # stack is aligned on entry!
121 movq %gs:8,%r10 # location of bottom of stack
122 leaq _cygtls.initialized(%r10),%r11 # where we will be looking
123 cmpq %r11,%rsp # stack loc > than tls
124 jge 0f # yep. we don't have a tls.
125 movl _cygtls.initialized(%r10),%r11d
126 cmpl \$0xc763173f,%r11d # initialized?
132 _sigfe: # stack is aligned on entry!
134 movq %gs:8,%r10 # location of bottom of stack
135 1: movl \$1,%r11d # potential lock value
136 xchgl %r11d,_cygtls.stacklock(%r10) # see if we can grab it
137 movl %r11d,_cygtls.spinning(%r10) # flag if we are waiting for lock
138 testl %r11d,%r11d # it will be zero
142 2: movq \$8,%rax # have the lock, now increment the
143 xaddq %rax,_cygtls.stackptr(%r10) # stack pointer and get pointer
144 leaq _sigbe(%rip),%r11 # new place to return to
145 xchgq %r11,8(%rsp) # exchange with real return value
146 movq %r11,(%rax) # store real return value on alt stack
147 incl _cygtls.incyg(%r10)
148 decl _cygtls.stacklock(%r10) # remove lock
149 popq %rax # pop real function address from stack
150 jmp *%rax # and jmp to it
155 _sigbe: # return here after cygwin syscall
156 # stack is aligned on entry!
158 movq %gs:8,%r10 # address of bottom of tls
159 1: movl \$1,%r11d # potential lock value
160 xchgl %r11d,_cygtls.stacklock(%r10) # see if we can grab it
161 movl %r11d,_cygtls.spinning(%r10) # flag if we are waiting for lock
162 testl %r11d,%r11d # it will be zero
166 2: movq \$-8,%r11 # now decrement aux stack
167 xaddq %r11,_cygtls.stackptr(%r10) # and get pointer
168 movq -8(%r11),%r11 # get return address from signal stack
169 decl _cygtls.incyg(%r10)
170 decl _cygtls.stacklock(%r10) # release lock
171 jmp *%r11 # "return" to caller
177 pushq %r10 # used for return address injection
183 .seh_pushreg %rax # fake, there's no .seh_pushreg for the flags
184 # stack is aligned or unaligned on entry!
185 # make sure it is aligned from here on
186 # We could be called from an interrupted thread which doesn't know
187 # about his fate, so save and restore everything and the kitchen sink.
188 andq \$0xfffffffffffffff0,%rsp
217 .seh_stackalloc 0x128
220 movdqa %xmm15,0x110(%rsp)
221 movdqa %xmm14,0x100(%rsp)
222 movdqa %xmm13,0xf0(%rsp)
223 movdqa %xmm12,0xe0(%rsp)
224 movdqa %xmm11,0xd0(%rsp)
225 movdqa %xmm10,0xc0(%rsp)
226 movdqa %xmm9,0xb0(%rsp)
227 movdqa %xmm8,0xa0(%rsp)
228 movdqa %xmm7,0x90(%rsp)
229 movdqa %xmm6,0x80(%rsp)
230 movdqa %xmm5,0x70(%rsp)
231 movdqa %xmm4,0x60(%rsp)
232 movdqa %xmm3,0x50(%rsp)
233 movdqa %xmm2,0x40(%rsp)
234 movdqa %xmm1,0x30(%rsp)
235 movdqa %xmm0,0x20(%rsp)
238 movq %gs:8,%r12 # get tls
239 movl _cygtls.saved_errno(%r12),%r15d # temporarily save saved_errno
240 movq \$_cygtls.start_offset,%rcx # point to beginning of tls block
241 addq %r12,%rcx # and store as first arg to method
242 call _ZN7_cygtls19call_signal_handlerEv # call handler
244 1: movl \$1,%r11d # potential lock value
245 xchgl %r11d,_cygtls.stacklock(%r12) # see if we can grab it
246 movl %r11d,_cygtls.spinning(%r12) # flag if we are waiting for lock
247 testl %r11d,%r11d # it will be zero
251 2: testl %r15d,%r15d # was saved_errno < 0
252 jl 3f # yup. ignore it
253 movq _cygtls.errno_addr(%r12),%r11
255 3: movq \$-8,%r11 # now decrement aux stack
256 xaddq %r11,_cygtls.stackptr(%r12) # and get pointer
258 xchgq %r10,-8(%r11) # get return address from signal stack
260 movl %r11d,_cygtls.incyg(%r12)
261 movl %r11d,_cygtls.stacklock(%r12) # unlock
262 movdqa 0x20(%rsp),%xmm0
263 movdqa 0x30(%rsp),%xmm1
264 movdqa 0x40(%rsp),%xmm2
265 movdqa 0x50(%rsp),%xmm3
266 movdqa 0x60(%rsp),%xmm4
267 movdqa 0x70(%rsp),%xmm5
268 movdqa 0x80(%rsp),%xmm6
269 movdqa 0x90(%rsp),%xmm7
270 movdqa 0xa0(%rsp),%xmm8
271 movdqa 0xb0(%rsp),%xmm9
272 movdqa 0xc0(%rsp),%xmm10
273 movdqa 0xd0(%rsp),%xmm11
274 movdqa 0xe0(%rsp),%xmm12
275 movdqa 0xf0(%rsp),%xmm13
276 movdqa 0x100(%rsp),%xmm14
277 movdqa 0x110(%rsp),%xmm15
303 .global _sigdelayed_end
306 .global _ZN7_cygtls3popEv
307 .seh_proc _ZN7_cygtls3popEv
311 xaddq %r11,_cygtls.stackptr_p(%rcx)
317 .global _ZN7_cygtls4lockEv
318 .seh_proc _ZN7_cygtls4lockEv
325 xchgl %r11d,_cygtls.stacklock_p(%r12)
335 .global _ZN7_cygtls6unlockEv
336 .seh_proc _ZN7_cygtls6unlockEv
337 _ZN7_cygtls6unlockEv:
339 decl _cygtls.stacklock_p(%rcx)
344 .global _ZN7_cygtls6lockedEv
345 .seh_proc _ZN7_cygtls6lockedEv
346 _ZN7_cygtls6lockedEv:
348 movl _cygtls.stacklock_p(%rcx),%eax
352 .seh_proc stabilize_sig_stack
361 xchgl %r10d,_cygtls.stacklock(%r12)
362 movl %r10d,_cygtls.spinning(%r12) # flag if we are waiting for lock
367 2: incl _cygtls.incyg(%r12)
368 cmpl \$0,_cygtls.sig(%r12)
370 decl _cygtls.stacklock(%r12) # unlock
371 movq \$_cygtls.start_offset,%rcx # point to beginning
372 addq %r12,%rcx # of tls block
373 call _ZN7_cygtls19call_signal_handlerEv
375 3: decl _cygtls.incyg(%r12)
377 movq %r12,%r11 # return tls addr in r11
395 movl %edx,0x100(%rcx) # store savemask
396 testl %edx,%edx # savemask != 0?
397 je setjmp # no, skip fetching sigmask
400 leaq 0x108(%rcx),%r8 # &sigjmp_buf.sigmask
401 xorq %rdx,%rdx # NULL
402 xorl %ecx,%ecx # SIG_SETMASK
413 # We use the Windows jmp_buf layout with two small twists.
414 # - we store the tls stackptr in Frame, MSVCRT stores a second copy
415 # of %rbp in Frame (twice? why?)
416 # - we just store %rsp as is, MSVCRT stores %rsp of the caller in Rsp
430 # jmp_buf is potentially unaligned!
431 movdqu %xmm6,0x60(%rcx)
432 movdqu %xmm7,0x70(%rcx)
433 movdqu %xmm8,0x80(%rcx)
434 movdqu %xmm9,0x90(%rcx)
435 movdqu %xmm10,0xa0(%rcx)
436 movdqu %xmm11,0xb0(%rcx)
437 movdqu %xmm12,0xc0(%rcx)
438 movdqu %xmm13,0xd0(%rcx)
439 movdqu %xmm14,0xe0(%rcx)
440 movdqu %xmm15,0xf0(%rcx)
443 call stabilize_sig_stack # returns tls in r11
445 movq _cygtls.stackptr(%r11),%r10
447 decl _cygtls.stacklock(%r11)
459 movl 0x100(%rcx),%r8d # savemask
460 testl %r8d,%r8d # savemask != 0?
461 je 1f # no, jmp to longjmp
463 leaq 0x108(%rcx),%rdx # &sigjmp_buf.sigmask
464 xorl %ecx,%ecx # SIG_SETMASK
477 movl %edx,%r12d # save return value
479 call stabilize_sig_stack # returns tls in r11
481 movl %r12d,%eax # restore return value
482 movq (%rcx),%r10 # get old signal stack
483 movq %r10,_cygtls.stackptr(%r11) # restore
484 decl _cygtls.stacklock(%r11) # relinquish lock
486 movl %r10d,_cygtls.incyg(%r11) # we're not in cygwin anymore
501 # jmp_buf is potentially unaligned!
502 movdqu 0x60(%rcx),%xmm6
503 movdqu 0x70(%rcx),%xmm7
504 movdqu 0x80(%rcx),%xmm8
505 movdqu 0x90(%rcx),%xmm9
506 movdqu 0xa0(%rcx),%xmm10
507 movdqu 0xb0(%rcx),%xmm11
508 movdqu 0xc0(%rcx),%xmm12
509 movdqu 0xd0(%rcx),%xmm13
510 movdqu 0xe0(%rcx),%xmm14
511 movdqu 0xf0(%rcx),%xmm15
522 grep {s/\r//og; s/#.*//og; s/\s+\n//sog; !/^$/o && $_} @_;