arm-linux: Add libitm support.
[official-gcc.git] / libitm / config / arm / sjlj.S
blob2c9fb02c5019d401bc5a05e7e2aa7e1efd386f98
1 /* Copyright (C) 2011 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/>.  */
25 #include "hwcap.h"
26 #include "asmcfi.h"
28         .syntax unified
30 #if defined(__thumb2__)
31 # define PC_OFS 4
32         .thumb
33         .thumb_func
34 #else
35 # define PC_OFS 8
36 #endif
38 #if defined (__thumb2__) && defined(__ARM_ARCH_6T2__)
39 # define HAVE_MOVT
40         .arch   armv6t2
41 #elif defined (__ARM_ARCH_7A__)
42 # define HAVE_MOVT
43         .arch   armv7-a
44 #elif defined (__ARM_ARCH_7R__)
45 # define HAVE_MOVT
46         .arch   armv7-r
47 #elif defined (__ARM_ARCH_7M__)
48 # define HAVE_MOVT
49         .arch   armv7-m
50 #endif
52 #if defined(HAVE_MOVT) && defined(PIC)
53 .macro ldaddr reg, addr
54         movw    \reg, #:lower16:(\addr - (98f + PC_OFS))
55         movt    \reg, #:upper16:(\addr - (98f + PC_OFS))
56 98:     add     \reg, \reg, pc
57 .endm
58 #elif defined(HAVE_MOVT)
59 .macro ldaddr reg, addr
60         movw    \reg, #:lower16:\addr
61         movt    \reg, #:upper16:\addr
62 .endm
63 #elif defined(PIC)
64 .macro ldaddr reg, addr
65         ldr     \reg, 99f
66 98:     add     \reg, \reg, pc
67 .subsection 1
68         .align  2
69 99:     .word   \addr - (98b + PC_OFS)
70 .subsection 0
71 .endm
72 #else
73 .macro ldaddr reg, addr
74         ldr     \reg, =\addr
75 .endm
76 #endif
78         .text
79         .align  2
80         .global _ITM_beginTransaction
81         .type   _ITM_beginTransaction, %function
83 _ITM_beginTransaction:
84         .fnstart
85         cfi_startproc
86         mov     ip, sp
87         push    { r4-r11, ip, lr }
88         .save   { lr }
89         .pad    #(9*4)
90         cfi_adjust_cfa_offset(40)
91         cfi_rel_offset(lr, 36)
92         sub     sp, sp, #(14*8)
93         .pad    #(14*8)
94         cfi_adjust_cfa_offset(14*8)
96         ldaddr  r2, GTM_hwcap
97         ldr     r2, [r2]
99         /* Store the VFP registers.  Don't use VFP instructions directly
100            because this code is used in non-VFP multilibs.  */
101         tst     r2, #HWCAP_ARM_VFP
102         beq     1f
103         stc     p11, cr8, [sp], {16}    /* vstm sp, {d8-d15} */
105         /* Save the call-preserved iWMMXt registers.  */
106         tst     r2, #HWCAP_ARM_IWMMXT
107         beq     1f
108         stcl    p1, cr10, [sp, #64]     /* wstrd wr10, [sp, #64] */
109         stcl    p1, cr11, [sp, #72]
110         stcl    p1, cr12, [sp, #80]
111         stcl    p1, cr13, [sp, #88]
112         stcl    p1, cr14, [sp, #96]
113         stcl    p1, cr15, [sp, #104]
115         /* Invoke GTM_begin_transaction with the struct we just built.  */
116         mov     r1, sp
117         bl      GTM_begin_transaction
119         /* Return; we don't need to restore any of the call-saved regs.  */
120         add     sp, sp, #(14*8 + 9*4)
121         cfi_adjust_cfa_offset(-(14*8 + 9*4))
122         pop     { pc }
123         .fnend
124         cfi_endproc
125         .size   _ITM_beginTransaction, . - _ITM_beginTransaction
127         .align  2
128         .global GTM_longjmp
129         .hidden GTM_longjmp
130         .type   GTM_longjmp, %function
132 GTM_longjmp:
133         cfi_startproc
134         ldaddr  r2, GTM_hwcap
135         ldr     r2, [r2]
137         tst     r2, #HWCAP_ARM_VFP
138         beq     1f
139         ldc     p11, cr8, [r1], {16}    /* vldmia r1, {d8-d15} */
141         tst     r2, #HWCAP_ARM_IWMMXT
142         beq     1f
143         ldcl    p1, cr10, [r1, #64]     /* wldrd wr10, [r1, #64] */
144         ldcl    p1, cr11, [r1, #72]
145         ldcl    p1, cr12, [r1, #80]
146         ldcl    p1, cr13, [r1, #88]
147         ldcl    p1, cr14, [r1, #96]
148         ldcl    p1, cr15, [r1, #104]
150         add     r1, r1, #(14*8)         /* Skip both VFP and iWMMXt blocks */
151 #ifdef __thumb2__
152         ldm     r1, { r4-r11, ip, lr }
153         cfi_def_cfa(ip, 0)
154         mov     sp, ip
155         bx      lr
156 #else
157         ldm     r1, { r4-r11, sp, pc }
158 #endif
159         cfi_endproc
160         .size   GTM_longjmp, . - GTM_longjmp
162 #ifdef __linux__
163 .section .note.GNU-stack, "", %progbits
164 #endif