Re: [PATCH] fix fdump-lang-raw ICE
[official-gcc.git] / libitm / config / x86 / sjlj.S
blob21ca9d76772ae9716e550a292d8b7ab4190b9c8b
1 /* Copyright (C) 2008-2017 Free Software Foundation, Inc.
2    Contributed by Richard Henderson <rth@redhat.com>.
4    This file is part of the GNU Transactional Memory Library (libitm).
6    Libitm is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
11    Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
12    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14    more details.
16    Under Section 7 of GPL version 3, you are granted additional
17    permissions described in the GCC Runtime Library Exception, version
18    3.1, as published by the Free Software Foundation.
20    You should have received a copy of the GNU General Public License and
21    a copy of the GCC Runtime Library Exception along with this program;
22    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23    <http://www.gnu.org/licenses/>.  */
26 #include "asmcfi.h"
27 #include "config.h"
29 #define CONCAT1(a, b) CONCAT2(a, b)
30 #define CONCAT2(a, b) a ## b
32 #ifdef __USER_LABEL_PREFIX__
33 #  define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
34 #else
35 #  define SYM(x) x
36 #endif
38 #ifdef __ELF__
39 #  define TYPE(x) .type SYM(x), @function
40 #  define SIZE(x) .size SYM(x), . - SYM(x)
41 #  ifdef HAVE_ATTRIBUTE_VISIBILITY
42 #    define HIDDEN(x) .hidden SYM(x)
43 #  else
44 #    define HIDDEN(x)
45 #  endif
46 #else
47 #  define TYPE(x)
48 #  define SIZE(x)
49 #  ifdef __MACH__
50 #    define HIDDEN(x) .private_extern SYM(x)
51 #  else
52 #    define HIDDEN(x)
53 #  endif
54 #endif
56 /* These are duplicates of the canonical definitions in libitm.h.  Note that
57    the code relies on pr_uninstrumentedCode == a_runUninstrumentedCode.  */
58 #define pr_uninstrumentedCode   0x02
59 #define pr_hasNoAbort           0x08
60 #define pr_HTMRetryableAbort    0x800000
61 #define pr_HTMRetriedAfterAbort 0x1000000
62 #define a_runInstrumentedCode   0x01
63 #define a_runUninstrumentedCode 0x02
64 #define a_tryHTMFastPath        0x20
66 #define _XABORT_EXPLICIT        (1 << 0)
67 #define _XABORT_RETRY           (1 << 1)
69         .text
71         .align 4
72         .globl  SYM(_ITM_beginTransaction)
74 SYM(_ITM_beginTransaction):
75         cfi_startproc
76 #ifdef __x86_64__
77 #ifdef HAVE_AS_RTM
78         /* Custom HTM fast path.  We start the HW transaction here and let
79            gtm_thread::begin_transaction (aka GTM_begin_transaction) decide
80            how to proceed on aborts: We either retry the fast path, or fall
81            back to another execution method.  RTM restores all registers after
82            a HW transaction abort, so we can do the SW setjmp after aborts,
83            and we have to because we might choose a SW fall back.  However,
84            we have to explicitly save/restore the first argument (edi).
85            The htm_fastpath field is the second int in gtm_rwlock.  */
86         cmpl    $0, (SYM(gtm_serial_lock)+4)(%rip)
87         jz      .Lno_htm
88         testl   $pr_hasNoAbort, %edi
89         jz      .Lno_htm
90 .Lhtm_fastpath:
91         xbegin  .Ltxn_abort
92         /* Monitor the serial lock (specifically, the 32b writer/summary field
93            at its start), and only continue if there is no serial-mode
94            transaction.  Note that we might be just a nested transaction and
95            our outermost transaction might be in serial mode; we check for
96            this case in the retry policy implementation.  */
97         cmpl    $0, SYM(gtm_serial_lock)(%rip)
98         jnz     1f
99         /* Now also check that HW transactions are still allowed to run (see
100            gtm_thread::begin_transaction for why this is necessary).  */
101         cmpl    $0, (SYM(gtm_serial_lock)+4)(%rip)
102         jz      1f
103         /* Everything is good.  Run the transaction, preferably using the
104            uninstrumented code path.  Note that the following works because
105            pr_uninstrumentedCode == a_runUninstrumentedCode.  */
106         andl    $pr_uninstrumentedCode, %edi
107         mov     $a_runInstrumentedCode, %eax
108         cmovnz  %edi, %eax
109         ret
110         /* There is a serial-mode transaction or HW transactions are not
111            allowed anymore, so abort (see htm_abort() regarding the abort
112            code).  */
113 1:      xabort  $0xff
114 .Ltxn_abort:
115         /* If it might make sense to retry the HTM fast path, let the C++
116            code decide.  */
117         testl   $(_XABORT_RETRY|_XABORT_EXPLICIT), %eax
118         jz      .Lno_htm
119         orl     $pr_HTMRetryableAbort, %edi
120         /* Let the C++ code handle the retry policy.  */
121 .Lno_htm:
122 #endif
123         leaq    8(%rsp), %rax
124         subq    $72, %rsp
125         cfi_adjust_cfa_offset(72)
126         /* Store edi for future HTM fast path retries.  We use a stack slot
127            lower than the jmpbuf so that the jmpbuf's rip field will overlap
128            with the proper return address on the stack.  */
129         movl    %edi, 8(%rsp)
130         /* Save the jmpbuf for any non-HTM-fastpath execution method.
131            Because rsp-based addressing is 1 byte larger and we've got rax
132            handy, use it.  */
133         movq    %rax, -64(%rax)
134         movq    %rbx, -56(%rax)
135         movq    %rbp, -48(%rax)
136         movq    %r12, -40(%rax)
137         movq    %r13, -32(%rax)
138         movq    %r14, -24(%rax)
139         movq    %r15, -16(%rax)
140         leaq    -64(%rax), %rsi
141         call    SYM(GTM_begin_transaction)
142         movl    8(%rsp), %edi
143         addq    $72, %rsp
144         cfi_adjust_cfa_offset(-72)
145 #ifdef HAVE_AS_RTM
146         /* If a_tryHTMFastPath was returned, then we need to retry the
147            fast path.  We also restore edi and set pr_HTMRetriedAfterAbort
148            to state that we have retried the fast path already (it's harmless
149            if this bit is set even if we don't retry the fast path because it
150            is checked iff pr_HTMRetryableAbort is set).  We clear
151            pr_HTMRetryableAbort because it applies to a previous HW
152            transaction attempt.  */
153         cmpl    $a_tryHTMFastPath, %eax
154         jnz     2f
155         andl    $(0xffffffff-pr_HTMRetryableAbort), %edi
156         orl     $pr_HTMRetriedAfterAbort, %edi
157         jmp     .Lhtm_fastpath
159 #endif
160 #else
161         leal    4(%esp), %ecx
162         movl    4(%esp), %eax
163         subl    $28, %esp
164         cfi_def_cfa_offset(32)
165         movl    %ecx, 8(%esp)
166         movl    %ebx, 12(%esp)
167         movl    %esi, 16(%esp)
168         movl    %edi, 20(%esp)
169         movl    %ebp, 24(%esp)
170         leal    8(%esp), %edx
171 #if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__
172         call    SYM(GTM_begin_transaction)
173 #elif defined __ELF__
174         call    1f
175 1:      popl    %ebx
176         addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
177         call    SYM(GTM_begin_transaction)@PLT
178         movl    12(%esp), %ebx
179 #else
180 # error "Unsupported PIC sequence"
181 #endif
182         addl    $28, %esp
183         cfi_def_cfa_offset(4)
184 #endif
185         ret
186         cfi_endproc
188         TYPE(_ITM_beginTransaction)
189         SIZE(_ITM_beginTransaction)
191         .align 4
192         .globl  SYM(GTM_longjmp)
194 SYM(GTM_longjmp):
195         cfi_startproc
196 #ifdef __x86_64__
197         movq    (%rsi), %rcx
198         movq    8(%rsi), %rbx
199         movq    16(%rsi), %rbp
200         movq    24(%rsi), %r12
201         movq    32(%rsi), %r13
202         movq    40(%rsi), %r14
203         movq    48(%rsi), %r15
204         movl    %edi, %eax
205         cfi_def_cfa(%rsi, 0)
206         cfi_offset(%rip, 56)
207         cfi_register(%rsp, %rcx)
208         movq    %rcx, %rsp
209         jmp     *56(%rsi)
210 #else
211         movl    (%edx), %ecx
212         movl    4(%edx), %ebx
213         movl    8(%edx), %esi
214         movl    12(%edx), %edi
215         movl    16(%edx), %ebp
216         cfi_def_cfa(%edx, 0)
217         cfi_offset(%eip, 20)
218         cfi_register(%esp, %ecx)
219         movl    %ecx, %esp
220         jmp     *20(%edx)
221 #endif
222         cfi_endproc
224         TYPE(GTM_longjmp)
225         HIDDEN(GTM_longjmp)
226         SIZE(GTM_longjmp)
228 #ifdef __linux__
229 .section .note.GNU-stack, "", @progbits
230 #endif