| #!/usr/bin/perl |
| # |
| # This file is part of Cygwin. |
| # |
| # This software is a copyrighted work licensed under the terms of the |
| # Cygwin license. Please consult the file "CYGWIN_LICENSE" for |
| # details. |
| # |
| use strict; |
| use integer; |
| use Getopt::Long; |
| |
| sub cleanup(@); |
| |
| my $cpu; |
| my $output_def; |
| my $tls_offsets; |
| GetOptions('cpu=s'=>\$cpu, 'output-def=s'=>\$output_def, 'tlsoffsets=s'=>\$tls_offsets); |
| |
| $main::first = 0; |
| if (!defined($cpu) || !defined($output_def) || !defined($tls_offsets)) { |
| die "$0: missing required option\n"; |
| } |
| |
| require $tls_offsets; |
| |
| my $is64bit = $cpu eq 'x86_64'; |
| my $sym_prefix = $is64bit ? '' : '_'; |
| |
| my @top = (); |
| while (<>) { |
| push(@top, cleanup $_); |
| last if /^\s*exports$/oi; |
| } |
| my @in = cleanup <>; |
| |
| my %sigfe = (); |
| my @data = (); |
| my @nosigfuncs = (); |
| my @text = (); |
| for (@in) { |
| chomp; |
| s/\s+DATA$//o and do { |
| push @data, $_; |
| next; |
| }; |
| if (/=/o) { |
| if (s/\s+NOSIGFE\s*$//) { |
| # nothing |
| } elsif (s/\s+SIGFE(_MAYBE)?$//) { |
| my $func = (split(' '))[2]; |
| my $maybe = (defined($1) ? lc $1 : '') . '_'; |
| $sigfe{$func} = '_sigfe' . $maybe . $func; |
| } |
| } else { |
| my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGFE(?:_MAYBE)?))?$%o; |
| if (defined($sigfe) && $sigfe =~ /^NO/o) { |
| $_ = $func; |
| } else { |
| $sigfe ||= 'sigfe'; |
| $_ = '_' . lc($sigfe) . '_' . $func; |
| $sigfe{$func} = $_; |
| $_ = $func . ' = ' . $_; |
| } |
| } |
| s/(\S)\s+(\S)/$1 $2/go; |
| s/(\S)\s+$/$1/o; |
| s/^\s+(\S)/$1/o; |
| push @text, $_; |
| } |
| |
| for (@text) { |
| my ($alias, $func) = /^(\S+)\s+=\s+(\S+)\s*$/o; |
| $_ = $alias . ' = ' . $sigfe{$func} |
| if defined($func) && $sigfe{$func}; |
| } |
| |
| open OUT, '>', $output_def or die "$0: couldn't open \"$output_def\" - $!\n"; |
| push @top, (map {$_ . " DATA\n"} @data), (map {$_ . "\n"} @text); |
| print OUT @top; |
| close OUT; |
| |
| open SIGFE, '>', 'sigfe.s' or die "$0: couldn't open 'sigfe.s' file for writing - $!\n"; |
| |
| for my $k (sort keys %sigfe) { |
| print SIGFE fefunc($k, $sigfe{$k}); |
| } |
| close SIGFE; |
| |
| sub fefunc { |
| my $func = $sym_prefix . shift; |
| my $fe = $sym_prefix . shift; |
| my $sigfe_func; |
| if ($is64bit) { |
| $sigfe_func = ($fe =~ /^(.*)_${func}$/)[0]; |
| } else { |
| $sigfe_func = ($fe =~ /^(.*)${func}$/)[0]; |
| } |
| my $extra; |
| my $res; |
| if ($is64bit) { |
| $res = <<EOF; |
| .extern $func |
| .global $fe |
| .seh_proc $fe |
| $fe: |
| leaq $func(%rip),%r10 |
| pushq %r10 |
| .seh_pushreg %r10 |
| .seh_endprologue |
| jmp $sigfe_func |
| .seh_endproc |
| |
| EOF |
| } else { |
| $res = <<EOF; |
| .extern $func |
| .global $fe |
| $fe: |
| pushl \$$func |
| jmp $sigfe_func |
| |
| EOF |
| } |
| if (!$main::first++) { |
| if ($is64bit) { |
| $res = <<EOF . longjmp () . $res; |
| .text |
| |
| .seh_proc _sigfe_maybe |
| _sigfe_maybe: # stack is aligned on entry! |
| .seh_endprologue |
| movq %gs:8,%r10 # location of bottom of stack |
| leaq $tls::initialized(%r10),%r11 # where we will be looking |
| cmpq %r11,%rsp # stack loc > than tls |
| jge 0f # yep. we don't have a tls. |
| movl $tls::initialized(%r10),%r11d |
| cmpl \$0xc763173f,%r11d # initialized? |
| je 1f |
| 0: ret |
| .seh_endproc |
| |
| .seh_proc _sigfe |
| _sigfe: # stack is aligned on entry! |
| .seh_endprologue |
| movq %gs:8,%r10 # location of bottom of stack |
| 1: movl \$1,%r11d # potential lock value |
| xchgl %r11d,$tls::stacklock(%r10) # see if we can grab it |
| movl %r11d,$tls::spinning(%r10) # flag if we are waiting for lock |
| testl %r11d,%r11d # it will be zero |
| jz 2f # if so |
| pause |
| jmp 1b # loop |
| 2: movq \$8,%rax # have the lock, now increment the |
| xaddq %rax,$tls::stackptr(%r10) # stack pointer and get pointer |
| leaq _sigbe(%rip),%r11 # new place to return to |
| xchgq %r11,8(%rsp) # exchange with real return value |
| movq %r11,(%rax) # store real return value on alt stack |
| incl $tls::incyg(%r10) |
| decl $tls::stacklock(%r10) # remove lock |
| popq %rax # pop real function address from stack |
| jmp *%rax # and jmp to it |
| .seh_endproc |
| |
| .global _sigbe |
| .seh_proc _sigbe |
| _sigbe: # return here after cygwin syscall |
| # stack is aligned on entry! |
| .seh_endprologue |
| movq %gs:8,%r10 # address of bottom of tls |
| 1: movl \$1,%r11d # potential lock value |
| xchgl %r11d,$tls::stacklock(%r10) # see if we can grab it |
| movl %r11d,$tls::spinning(%r10) # flag if we are waiting for lock |
| testl %r11d,%r11d # it will be zero |
| jz 2f # if so |
| pause |
| jmp 1b # and loop |
| 2: movq \$-8,%r11 # now decrement aux stack |
| xaddq %r11,$tls::stackptr(%r10) # and get pointer |
| movq -8(%r11),%r11 # get return address from signal stack |
| decl $tls::incyg(%r10) |
| decl $tls::stacklock(%r10) # release lock |
| jmp *%r11 # "return" to caller |
| .seh_endproc |
| |
| .global sigdelayed |
| .seh_proc sigdelayed |
| sigdelayed: |
| pushq %r10 # used for return address injection |
| .seh_pushreg %r10 |
| pushq %rbp |
| .seh_pushreg %rbp |
| movq %rsp,%rbp |
| pushf |
| .seh_pushreg %rax # fake, there's no .seh_pushreg for the flags |
| # stack is aligned or unaligned on entry! |
| # make sure it is aligned from here on |
| # We could be called from an interrupted thread which doesn't know |
| # about his fate, so save and restore everything and the kitchen sink. |
| andq \$0xfffffffffffffff0,%rsp |
| .seh_setframe %rbp,0 |
| pushq %r15 |
| .seh_pushreg %r15 |
| pushq %r14 |
| .seh_pushreg %r14 |
| pushq %r13 |
| .seh_pushreg %r13 |
| pushq %r12 |
| .seh_pushreg %r12 |
| pushq %r11 |
| .seh_pushreg %r11 |
| pushq %r9 |
| .seh_pushreg %r9 |
| pushq %r8 |
| .seh_pushreg %r8 |
| pushq %rsi |
| .seh_pushreg %rsi |
| pushq %rdi |
| .seh_pushreg %rdi |
| pushq %rdx |
| .seh_pushreg %rdx |
| pushq %rcx |
| .seh_pushreg %rcx |
| pushq %rbx |
| .seh_pushreg %rbx |
| pushq %rax |
| .seh_pushreg %rax |
| subq \$0x128,%rsp |
| .seh_stackalloc 0x128 |
| stmxcsr 0x124(%rsp) |
| fnstcw 0x120(%rsp) |
| movdqa %xmm15,0x110(%rsp) |
| movdqa %xmm14,0x100(%rsp) |
| movdqa %xmm13,0xf0(%rsp) |
| movdqa %xmm12,0xe0(%rsp) |
| movdqa %xmm11,0xd0(%rsp) |
| movdqa %xmm10,0xc0(%rsp) |
| movdqa %xmm9,0xb0(%rsp) |
| movdqa %xmm8,0xa0(%rsp) |
| movdqa %xmm7,0x90(%rsp) |
| movdqa %xmm6,0x80(%rsp) |
| movdqa %xmm5,0x70(%rsp) |
| movdqa %xmm4,0x60(%rsp) |
| movdqa %xmm3,0x50(%rsp) |
| movdqa %xmm2,0x40(%rsp) |
| movdqa %xmm1,0x30(%rsp) |
| movdqa %xmm0,0x20(%rsp) |
| .seh_endprologue |
| |
| movq %gs:8,%r12 # get tls |
| movl $tls::saved_errno(%r12),%r15d # temporarily save saved_errno |
| movq \$$tls::start_offset,%rcx # point to beginning of tls block |
| addq %r12,%rcx # and store as first arg to method |
| call _ZN7_cygtls19call_signal_handlerEv # call handler |
| |
| 1: movl \$1,%r11d # potential lock value |
| xchgl %r11d,$tls::stacklock(%r12) # see if we can grab it |
| movl %r11d,$tls::spinning(%r12) # flag if we are waiting for lock |
| testl %r11d,%r11d # it will be zero |
| jz 2f # if so |
| pause |
| jmp 1b # and loop |
| 2: testl %r15d,%r15d # was saved_errno < 0 |
| jl 3f # yup. ignore it |
| movq $tls::errno_addr(%r12),%r11 |
| movl %r15d,(%r11) |
| 3: movq \$-8,%r11 # now decrement aux stack |
| xaddq %r11,$tls::stackptr(%r12) # and get pointer |
| xorq %r10,%r10 |
| xchgq %r10,-8(%r11) # get return address from signal stack |
| xorl %r11d,%r11d |
| movl %r11d,$tls::incyg(%r12) |
| movl %r11d,$tls::stacklock(%r12) # unlock |
| movdqa 0x20(%rsp),%xmm0 |
| movdqa 0x30(%rsp),%xmm1 |
| movdqa 0x40(%rsp),%xmm2 |
| movdqa 0x50(%rsp),%xmm3 |
| movdqa 0x60(%rsp),%xmm4 |
| movdqa 0x70(%rsp),%xmm5 |
| movdqa 0x80(%rsp),%xmm6 |
| movdqa 0x90(%rsp),%xmm7 |
| movdqa 0xa0(%rsp),%xmm8 |
| movdqa 0xb0(%rsp),%xmm9 |
| movdqa 0xc0(%rsp),%xmm10 |
| movdqa 0xd0(%rsp),%xmm11 |
| movdqa 0xe0(%rsp),%xmm12 |
| movdqa 0xf0(%rsp),%xmm13 |
| movdqa 0x100(%rsp),%xmm14 |
| movdqa 0x110(%rsp),%xmm15 |
| fninit |
| fldcw 0x120(%rsp) |
| ldmxcsr 0x124(%rsp) |
| addq \$0x128,%rsp |
| popq %rax |
| popq %rbx |
| popq %rcx |
| popq %rdx |
| popq %rdi |
| popq %rsi |
| popq %r8 |
| popq %r9 |
| popq %r11 |
| popq %r12 |
| popq %r13 |
| popq %r14 |
| popq %r15 |
| movq %rbp,%rsp |
| subq \$8, %rsp |
| popf |
| popq %rbp |
| xchgq %r10,(%rsp) |
| ret |
| .seh_endproc |
| _sigdelayed_end: |
| .global _sigdelayed_end |
| |
| # _cygtls::pop |
| .global _ZN7_cygtls3popEv |
| .seh_proc _ZN7_cygtls3popEv |
| _ZN7_cygtls3popEv: |
| .seh_endprologue |
| movq \$-8,%r11 |
| xaddq %r11,$tls::pstackptr(%rcx) |
| movq -8(%r11),%rax |
| ret |
| .seh_endproc |
| |
| # _cygtls::lock |
| .global _ZN7_cygtls4lockEv |
| .seh_proc _ZN7_cygtls4lockEv |
| _ZN7_cygtls4lockEv: |
| pushq %r12 |
| .seh_pushreg %r12 |
| .seh_endprologue |
| movq %rcx,%r12 |
| 1: movl \$1,%r11d |
| xchgl %r11d,$tls::pstacklock(%r12) |
| testl %r11d,%r11d |
| jz 2f |
| pause |
| jmp 1b |
| 2: popq %r12 |
| ret |
| .seh_endproc |
| |
| # _cygtls::unlock |
| .global _ZN7_cygtls6unlockEv |
| .seh_proc _ZN7_cygtls6unlockEv |
| _ZN7_cygtls6unlockEv: |
| .seh_endprologue |
| decl $tls::pstacklock(%rcx) |
| ret |
| .seh_endproc |
| |
| # _cygtls::locked |
| .global _ZN7_cygtls6lockedEv |
| .seh_proc _ZN7_cygtls6lockedEv |
| _ZN7_cygtls6lockedEv: |
| .seh_endprologue |
| movl $tls::pstacklock(%rcx),%eax |
| ret |
| .seh_endproc |
| |
| .seh_proc stabilize_sig_stack |
| stabilize_sig_stack: |
| pushq %r12 |
| .seh_pushreg %r12 |
| subq \$0x20,%rsp |
| .seh_stackalloc 32 |
| .seh_endprologue |
| movq %gs:8,%r12 |
| 1: movl \$1,%r10d |
| xchgl %r10d,$tls::stacklock(%r12) |
| movl %r10d,$tls::spinning(%r12) # flag if we are waiting for lock |
| testl %r10d,%r10d |
| jz 2f |
| pause |
| jmp 1b |
| 2: incl $tls::incyg(%r12) |
| cmpl \$0,$tls::sig(%r12) |
| jz 3f |
| decl $tls::stacklock(%r12) # unlock |
| movq \$$tls::start_offset,%rcx # point to beginning |
| addq %r12,%rcx # of tls block |
| call _ZN7_cygtls19call_signal_handlerEv |
| jmp 1b |
| 3: decl $tls::incyg(%r12) |
| addq \$0x20,%rsp |
| movq %r12,%r11 # return tls addr in r11 |
| popq %r12 |
| ret |
| .seh_endproc |
| EOF |
| } else { |
| $res = <<EOF . longjmp () . $res; |
| .text |
| |
| __sigfe_maybe: |
| pushl %ebx |
| pushl %edx |
| movl %fs:4,%ebx # location of bottom of stack |
| addl \$$tls::initialized,%ebx # where we will be looking |
| cmpl %ebx,%esp # stack loc > than tls |
| jge 0f # yep. we don't have a tls. |
| subl \$$tls::initialized,%ebx # where we will be looking |
| movl $tls::initialized(%ebx),%eax |
| cmpl \$0xc763173f,%eax # initialized? |
| je 1f |
| 0: popl %edx |
| popl %ebx |
| ret |
| |
| __sigfe: |
| pushl %ebx |
| pushl %edx |
| movl %fs:4,%ebx # location of bottom of stack |
| 1: movl \$1,%eax # potential lock value |
| xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it |
| movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock |
| testl %eax,%eax # it will be zero |
| jz 2f # if so |
| call _yield # should be a short-time thing, so |
| jmp 1b # sleep and loop |
| 2: movl \$4,%eax # have the lock, now increment the |
| xadd %eax,$tls::stackptr(%ebx) # stack pointer and get pointer |
| leal __sigbe,%edx # new place to return to |
| xchgl %edx,12(%esp) # exchange with real return value |
| movl %edx,(%eax) # store real return value on alt stack |
| incl $tls::incyg(%ebx) |
| decl $tls::stacklock(%ebx) # remove lock |
| popl %edx # restore saved value |
| popl %ebx |
| ret |
| |
| .global __sigbe |
| __sigbe: # return here after cygwin syscall |
| pushl %eax # don't clobber |
| pushl %ebx # tls pointer |
| 1: movl %fs:4,%ebx # address of bottom of tls |
| movl \$1,%eax # potential lock value |
| xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it |
| movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock |
| testl %eax,%eax # it will be zero |
| jz 2f # if so |
| call _yield # sleep |
| jmp 1b # and loop |
| 2: movl \$-4,%eax # now decrement aux stack |
| xadd %eax,$tls::stackptr(%ebx) # and get pointer |
| movl -4(%eax),%eax # get return address from signal stack |
| xchgl %eax,4(%esp) # swap return address with saved eax |
| decl $tls::incyg(%ebx) |
| decl $tls::stacklock(%ebx) # release lock |
| popl %ebx |
| ret |
| |
| .global _sigdelayed |
| _sigdelayed: |
| pushl %ebp |
| movl %esp,%ebp |
| # We could be called from an interrupted thread which doesn't know |
| # about his fate, so save and restore everything and the kitchen sink. |
| pushf |
| pushl %esi |
| pushl %edi |
| pushl %edx |
| pushl %ecx |
| pushl %ebx |
| pushl %eax |
| subl \$0x84,%esp |
| fnstcw 0x80(%esp) |
| movdqu %xmm7,0x70(%esp) |
| movdqu %xmm6,0x60(%esp) |
| movdqu %xmm5,0x50(%esp) |
| movdqu %xmm4,0x40(%esp) |
| movdqu %xmm3,0x30(%esp) |
| movdqu %xmm2,0x20(%esp) |
| movdqu %xmm1,0x10(%esp) |
| movdqu %xmm0,(%esp) |
| movl %fs:4,%ebx # get tls |
| pushl $tls::saved_errno(%ebx) # saved errno |
| |
| movl \$$tls::start_offset,%eax # point to beginning |
| addl %ebx,%eax # of tls block |
| call __ZN7_cygtls19call_signal_handlerEv\@4 # call handler |
| |
| movl %fs:4,%ebx # reget tls |
| 1: movl \$1,%eax # potential lock value |
| xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it |
| movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock |
| testl %eax,%eax # it will be zero |
| jz 2f # if so |
| call _yield # sleep |
| jmp 1b # and loop |
| 2: popl %edx # saved errno |
| testl %edx,%edx # Is it < 0 |
| jl 3f # yup. ignore it |
| movl $tls::errno_addr(%ebx),%eax |
| movl %edx,(%eax) |
| 3: movl \$-4,%eax # now decrement aux stack |
| xadd %eax,$tls::stackptr(%ebx) # and get pointer |
| xorl %ebp,%ebp |
| xchgl %ebp,-4(%eax) # get return address from signal stack |
| xchgl %ebp,0xa0(%esp) # store real return address |
| leave: xorl %eax,%eax |
| movl %eax,$tls::incyg(%ebx) |
| movl %eax,$tls::stacklock(%ebx) # unlock |
| |
| movdqu (%esp),%xmm0 |
| movdqu 0x10(%esp),%xmm1 |
| movdqu 0x20(%esp),%xmm2 |
| movdqu 0x30(%esp),%xmm3 |
| movdqu 0x40(%esp),%xmm4 |
| movdqu 0x50(%esp),%xmm5 |
| movdqu 0x60(%esp),%xmm6 |
| movdqu 0x70(%esp),%xmm7 |
| fninit |
| fldcw 0x80(%esp) |
| addl \$0x84,%esp |
| popl %eax |
| popl %ebx |
| popl %ecx |
| popl %edx |
| popl %edi |
| popl %esi |
| popf |
| ret |
| |
| .global __ZN7_cygtls3popEv\@4 |
| __ZN7_cygtls3popEv\@4: |
| 1: pushl %ebx |
| movl %eax,%ebx # this |
| movl \$-4,%eax |
| xadd %eax,$tls::pstackptr(%ebx) |
| movl -4(%eax),%eax |
| popl %ebx |
| ret |
| |
| # _cygtls::lock |
| .global __ZN7_cygtls4lockEv\@4 |
| __ZN7_cygtls4lockEv\@4: |
| pushl %ebx |
| movl %eax,%ebx |
| 1: movl \$1,%eax |
| xchgl %eax,$tls::pstacklock(%ebx) |
| testl %eax,%eax |
| jz 2f |
| call _yield |
| jmp 1b |
| 2: popl %ebx |
| ret |
| |
| # _cygtls::unlock |
| .global __ZN7_cygtls6unlockEv\@4 |
| __ZN7_cygtls6unlockEv\@4: |
| decl $tls::pstacklock(%eax) |
| ret |
| |
| .global __ZN7_cygtls6lockedEv |
| __ZN7_cygtls6lockedEv: |
| movl $tls::pstacklock(%eax),%eax |
| ret |
| |
| .extern __ZN7_cygtls19call_signal_handlerEv\@4 |
| stabilize_sig_stack: |
| movl %fs:4,%ebx |
| 1: movl \$1,%eax |
| xchgl %eax,$tls::stacklock(%ebx) |
| movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock |
| testl %eax,%eax |
| jz 2f |
| call _yield |
| jmp 1b |
| 2: incl $tls::incyg(%ebx) |
| cmpl \$0,$tls::sig(%ebx) |
| jz 3f |
| decl $tls::stacklock(%ebx) # unlock |
| movl \$$tls::start_offset,%eax # point to beginning |
| addl %ebx,%eax # of tls block |
| call __ZN7_cygtls19call_signal_handlerEv\@4 |
| jmp 1b |
| 3: decl $tls::incyg(%ebx) |
| ret |
| EOF |
| } |
| } |
| return $res; |
| } |
| |
| sub longjmp { |
| if ($is64bit) { |
| return <<EOF; |
| |
| .globl sigsetjmp |
| .seh_proc sigsetjmp |
| sigsetjmp: |
| .seh_endprologue |
| movl %edx,0x100(%rcx) # store savemask |
| testl %edx,%edx # savemask != 0? |
| je setjmp # no, skip fetching sigmask |
| pushq %rcx |
| subq \$0x20,%rsp |
| leaq 0x108(%rcx),%r8 # &sigjmp_buf.sigmask |
| xorq %rdx,%rdx # NULL |
| xorl %ecx,%ecx # SIG_SETMASK |
| call pthread_sigmask |
| addq \$0x20,%rsp |
| popq %rcx |
| jmp setjmp |
| .seh_endproc |
| |
| .globl setjmp |
| .seh_proc setjmp |
| setjmp: |
| .seh_endprologue |
| # We use the Windows jmp_buf layout with two small twists. |
| # - we store the tls stackptr in Frame, MSVCRT stores a second copy |
| # of %rbp in Frame (twice? why?) |
| # - we just store %rsp as is, MSVCRT stores %rsp of the caller in Rsp |
| movq %rbx,0x8(%rcx) |
| movq %rsp,0x10(%rcx) |
| movq %rbp,0x18(%rcx) |
| movq %rsi,0x20(%rcx) |
| movq %rdi,0x28(%rcx) |
| movq %r12,0x30(%rcx) |
| movq %r13,0x38(%rcx) |
| movq %r14,0x40(%rcx) |
| movq %r15,0x48(%rcx) |
| movq (%rsp),%r10 |
| movq %r10,0x50(%rcx) |
| stmxcsr 0x58(%rcx) |
| fnstcw 0x5c(%rcx) |
| # jmp_buf is potentially unaligned! |
| movdqu %xmm6,0x60(%rcx) |
| movdqu %xmm7,0x70(%rcx) |
| movdqu %xmm8,0x80(%rcx) |
| movdqu %xmm9,0x90(%rcx) |
| movdqu %xmm10,0xa0(%rcx) |
| movdqu %xmm11,0xb0(%rcx) |
| movdqu %xmm12,0xc0(%rcx) |
| movdqu %xmm13,0xd0(%rcx) |
| movdqu %xmm14,0xe0(%rcx) |
| movdqu %xmm15,0xf0(%rcx) |
| pushq %rcx |
| .seh_pushreg %rcx |
| call stabilize_sig_stack # returns tls in r11 |
| popq %rcx |
| movq $tls::stackptr(%r11),%r10 |
| movq %r10,(%rcx) |
| decl $tls::stacklock(%r11) |
| xorl %eax,%eax |
| ret |
| .seh_endproc |
| |
| .globl siglongjmp |
| .seh_proc siglongjmp |
| siglongjmp: |
| pushq %rcx |
| .seh_pushreg %rcx |
| .seh_endprologue |
| movl %edx, %r12d |
| movl 0x100(%rcx),%r8d # savemask |
| testl %r8d,%r8d # savemask != 0? |
| je 1f # no, jmp to longjmp |
| xorq %r8,%r8 # NULL |
| leaq 0x108(%rcx),%rdx # &sigjmp_buf.sigmask |
| xorl %ecx,%ecx # SIG_SETMASK |
| subq \$0x20,%rsp |
| call pthread_sigmask |
| addq \$0x20,%rsp |
| jmp 1f |
| .seh_endproc |
| |
| .globl longjmp |
| .seh_proc longjmp |
| longjmp: |
| pushq %rcx |
| .seh_pushreg %rcx |
| .seh_endprologue |
| movl %edx,%r12d # save return value |
| 1: |
| call stabilize_sig_stack # returns tls in r11 |
| popq %rcx |
| movl %r12d,%eax # restore return value |
| movq (%rcx),%r10 # get old signal stack |
| movq %r10,$tls::stackptr(%r11) # restore |
| decl $tls::stacklock(%r11) # relinquish lock |
| xorl %r10d,%r10d |
| movl %r10d,$tls::incyg(%r11) # we're not in cygwin anymore |
| movq 0x8(%rcx),%rbx |
| movq 0x10(%rcx),%rsp |
| movq 0x18(%rcx),%rbp |
| movq 0x20(%rcx),%rsi |
| movq 0x28(%rcx),%rdi |
| movq 0x30(%rcx),%r12 |
| movq 0x38(%rcx),%r13 |
| movq 0x40(%rcx),%r14 |
| movq 0x48(%rcx),%r15 |
| movq 0x50(%rcx),%r10 |
| movq %r10,(%rsp) |
| ldmxcsr 0x58(%rcx) |
| fnclex |
| fldcw 0x5c(%rcx) |
| # jmp_buf is potentially unaligned! |
| movdqu 0x60(%rcx),%xmm6 |
| movdqu 0x70(%rcx),%xmm7 |
| movdqu 0x80(%rcx),%xmm8 |
| movdqu 0x90(%rcx),%xmm9 |
| movdqu 0xa0(%rcx),%xmm10 |
| movdqu 0xb0(%rcx),%xmm11 |
| movdqu 0xc0(%rcx),%xmm12 |
| movdqu 0xd0(%rcx),%xmm13 |
| movdqu 0xe0(%rcx),%xmm14 |
| movdqu 0xf0(%rcx),%xmm15 |
| testl %eax,%eax |
| jne 0f |
| incl %eax |
| 0: ret |
| .seh_endproc |
| EOF |
| } else { |
| return <<EOF; |
| |
| .globl _sigsetjmp |
| _sigsetjmp: |
| pushl %ebp |
| movl %esp,%ebp |
| pushl %edi |
| movl 8(%ebp),%edi # &sigjmp_buf |
| movl 12(%ebp),%eax # savemask |
| movl %eax,208(%edi) # store savemask |
| testl %eax,%eax # savemask != 0? |
| je 1f # no, skip fetching sigmask |
| subl \$12,%esp |
| leal 212(%edi),%eax # &sigjmp_buf.sigmask |
| movl %eax,8(%esp) # -> 3rd param "oldset" |
| xorl %eax,%eax |
| movl %eax,4(%esp) # NULL -> 2nd param "set" |
| movl %eax,(%esp) # SIG_SETMASK -> 1st param "how" |
| call _pthread_sigmask |
| addl \$12,%esp |
| jmp 1f |
| |
| .globl _setjmp |
| _setjmp: |
| pushl %ebp |
| movl %esp,%ebp |
| pushl %edi |
| movl 8(%ebp),%edi |
| 1: |
| movl %eax,0(%edi) |
| movl %ebx,4(%edi) |
| movl %ecx,8(%edi) |
| movl %edx,12(%edi) |
| movl %esi,16(%edi) |
| movl -4(%ebp),%eax |
| movl %eax,20(%edi) |
| movl 0(%ebp),%eax |
| movl %eax,24(%edi) |
| movl %esp,%eax |
| addl \$12,%eax |
| movl %eax,28(%edi) |
| movl 4(%ebp),%eax |
| movl %eax,32(%edi) |
| movw %es,%ax |
| movw %ax,36(%edi) |
| movw %fs,%ax |
| movw %ax,38(%edi) |
| movw %gs,%ax |
| movw %ax,40(%edi) |
| movw %ss,%ax |
| movw %ax,42(%edi) |
| movl %fs:0,%eax |
| movl %eax,44(%edi) |
| fnstcw 48(%edi) |
| pushl %ebx |
| call stabilize_sig_stack |
| movl $tls::stackptr(%ebx),%eax # save stack pointer contents |
| decl $tls::stacklock(%ebx) |
| popl %ebx |
| movl %eax,52(%edi) |
| popl %edi |
| movl \$0,%eax |
| leave |
| ret |
| |
| .globl ___sjfault |
| ___sjfault: |
| pushl %ebp |
| movl %esp,%ebp |
| pushl %edi |
| movl 8(%ebp),%edi |
| movl %eax,0(%edi) |
| movl %ebx,4(%edi) |
| movl %ecx,8(%edi) |
| movl %edx,12(%edi) |
| movl %esi,16(%edi) |
| movl -4(%ebp),%eax |
| movl %eax,20(%edi) |
| movl 0(%ebp),%eax |
| movl %eax,24(%edi) |
| movl %esp,%eax |
| addl \$12,%eax |
| movl %eax,28(%edi) |
| movl 4(%ebp),%eax |
| movl %eax,32(%edi) |
| movw %es,%ax |
| movw %ax,36(%edi) |
| movw %fs,%ax |
| movw %ax,38(%edi) |
| movw %gs,%ax |
| movw %ax,40(%edi) |
| movw %ss,%ax |
| movw %ax,42(%edi) |
| movl %fs:0,%eax |
| movl %eax,44(%edi) |
| popl %edi |
| movl \$0,%eax |
| leave |
| ret |
| |
| .global ___ljfault |
| ___ljfault: |
| pushl %ebp |
| movl %esp,%ebp |
| movl 8(%ebp),%edi |
| |
| movl 12(%ebp),%eax |
| testl %eax,%eax |
| jne 0f |
| incl %eax |
| |
| 0: movl %eax,0(%edi) |
| movl 24(%edi),%ebp |
| pushfl |
| popl %ebx |
| movl 44(%edi),%eax |
| movl %eax,%fs:0 |
| movw 42(%edi),%ax |
| movw %ax,%ss |
| movl 28(%edi),%esp |
| pushl 32(%edi) |
| pushl %ebx |
| movw 36(%edi),%ax |
| movw %ax,%es |
| movw 40(%edi),%ax |
| movw %ax,%gs |
| movl 0(%edi),%eax |
| movl 4(%edi),%ebx |
| movl 8(%edi),%ecx |
| movl 16(%edi),%esi |
| movl 12(%edi),%edx |
| movl 20(%edi),%edi |
| popfl |
| ret |
| |
| .globl _siglongjmp |
| _siglongjmp: |
| pushl %ebp |
| movl %esp,%ebp |
| movl 8(%ebp),%edi # &sigjmp_buf |
| movl 208(%edi),%eax # load savemask |
| testl %eax,%eax # savemask != 0? |
| je 1f # no, skip restoring sigmask |
| subl \$12,%esp |
| leal 212(%edi),%eax # &sigjmp_buf.sigmask |
| movl %eax,4(%esp) # -> 2nd param "set" |
| xorl %eax,%eax |
| movl %eax,8(%esp) # NULL -> 3rd param "oldset" |
| movl %eax,(%esp) # SIG_SETMASK -> 1st param "how" |
| call _pthread_sigmask |
| addl \$12,%esp |
| jmp 1f |
| |
| .globl _longjmp |
| _longjmp: |
| pushl %ebp |
| movl %esp,%ebp |
| movl 8(%ebp),%edi # &jmp_buf |
| 1: |
| call stabilize_sig_stack |
| movl 52(%edi),%eax # get old signal stack |
| movl %eax,$tls::stackptr(%ebx) # restore |
| decl $tls::stacklock(%ebx) # relinquish lock |
| xorl %eax,%eax |
| movl %eax,$tls::incyg(%ebx) # we're not in cygwin anymore |
| |
| movl 12(%ebp),%eax |
| testl %eax,%eax |
| jne 3f |
| incl %eax |
| |
| 3: movl %eax,0(%edi) |
| movl 24(%edi),%ebp |
| pushfl |
| popl %ebx |
| fninit |
| fldcw 48(%edi) |
| movl 44(%edi),%eax |
| movl %eax,%fs:0 |
| movw 42(%edi),%ax |
| movw %ax,%ss |
| movl 28(%edi),%esp |
| pushl 32(%edi) |
| pushl %ebx |
| movw 36(%edi),%ax |
| movw %ax,%es |
| movw 40(%edi),%ax |
| movw %ax,%gs |
| movl 0(%edi),%eax |
| movl 4(%edi),%ebx |
| movl 8(%edi),%ecx |
| movl 16(%edi),%esi |
| movl 12(%edi),%edx |
| movl 20(%edi),%edi |
| popfl |
| ret |
| EOF |
| } |
| } |
| |
| sub cleanup(@) { |
| grep {s/\r//og; s/#.*//og; s/\s+\n//sog; !/^$/o && $_} @_; |
| } |