blob: ebcb561c0a51453d79468d9a83e0d82c2cfead3d [file] [log] [blame]
/* Copyright (C) 2011-2021 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU Transactional Memory Library (libitm).
Libitm is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "hwcap.h"
#include "asmcfi.h"
.syntax unified
#if defined(__thumb2__)
# define PC_OFS 4
.thumb
.thumb_func
#else
# define PC_OFS 8
#endif
#if defined (__thumb2__) && defined(__ARM_ARCH_6T2__)
# define HAVE_MOVT
.arch armv6t2
#elif defined (__ARM_ARCH_7A__)
# define HAVE_MOVT
.arch armv7-a
#elif defined (__ARM_ARCH_7R__)
# define HAVE_MOVT
.arch armv7-r
#elif defined (__ARM_ARCH_7M__)
# define HAVE_MOVT
.arch armv7-m
#endif
#if defined(__FDPIC__)
.macro ldaddr reg, addr
ldr \reg, 99f
add \reg, \reg, r9
.subsection 1
.align 2
99: .word \addr(GOTOFF)
.subsection 0
.endm
#elif defined(HAVE_MOVT) && defined(PIC)
.macro ldaddr reg, addr
movw \reg, #:lower16:(\addr - (98f + PC_OFS))
movt \reg, #:upper16:(\addr - (98f + PC_OFS))
98: add \reg, \reg, pc
.endm
#elif defined(HAVE_MOVT)
.macro ldaddr reg, addr
movw \reg, #:lower16:\addr
movt \reg, #:upper16:\addr
.endm
#elif defined(PIC)
.macro ldaddr reg, addr
ldr \reg, 99f
98: add \reg, \reg, pc
.subsection 1
.align 2
99: .word \addr - (98b + PC_OFS)
.subsection 0
.endm
#else
.macro ldaddr reg, addr
ldr \reg, =\addr
.endm
#endif
.text
.align 2
.global _ITM_beginTransaction
.type _ITM_beginTransaction, %function
_ITM_beginTransaction:
.fnstart
cfi_startproc
mov ip, sp
push { r4-r11, ip, lr }
.save { lr }
.pad #(9*4)
cfi_adjust_cfa_offset(40)
cfi_rel_offset(lr, 36)
sub sp, sp, #(14*8)
.pad #(14*8)
cfi_adjust_cfa_offset(14*8)
ldaddr r2, GTM_hwcap
ldr r2, [r2]
/* Store the VFP registers. Don't use VFP instructions directly
because this code is used in non-VFP multilibs. */
tst r2, #HWCAP_ARM_VFP
beq 1f
stc p11, cr8, [sp], {16} /* vstm sp, {d8-d15} */
1:
/* Save the call-preserved iWMMXt registers. */
tst r2, #HWCAP_ARM_IWMMXT
beq 1f
stcl p1, cr10, [sp, #64] /* wstrd wr10, [sp, #64] */
stcl p1, cr11, [sp, #72]
stcl p1, cr12, [sp, #80]
stcl p1, cr13, [sp, #88]
stcl p1, cr14, [sp, #96]
stcl p1, cr15, [sp, #104]
1:
/* Invoke GTM_begin_transaction with the struct we just built. */
mov r1, sp
bl GTM_begin_transaction
/* Return; we don't need to restore any of the call-saved regs. */
add sp, sp, #(14*8 + 9*4)
cfi_adjust_cfa_offset(-(14*8 + 9*4))
pop { pc }
.fnend
cfi_endproc
.size _ITM_beginTransaction, . - _ITM_beginTransaction
.align 2
.global GTM_longjmp
.hidden GTM_longjmp
.type GTM_longjmp, %function
GTM_longjmp:
cfi_startproc
ldaddr r2, GTM_hwcap
ldr r2, [r2]
tst r2, #HWCAP_ARM_VFP
beq 1f
ldc p11, cr8, [r1], {16} /* vldmia r1, {d8-d15} */
1:
tst r2, #HWCAP_ARM_IWMMXT
beq 1f
ldcl p1, cr10, [r1, #64] /* wldrd wr10, [r1, #64] */
ldcl p1, cr11, [r1, #72]
ldcl p1, cr12, [r1, #80]
ldcl p1, cr13, [r1, #88]
ldcl p1, cr14, [r1, #96]
ldcl p1, cr15, [r1, #104]
1:
add r1, r1, #(14*8) /* Skip both VFP and iWMMXt blocks */
#ifdef __thumb2__
ldm r1, { r4-r11, ip, lr }
cfi_def_cfa(ip, 0)
mov sp, ip
bx lr
#else
ldm r1, { r4-r11, sp, pc }
#endif
cfi_endproc
.size GTM_longjmp, . - GTM_longjmp
#ifdef __linux__
.section .note.GNU-stack, "", %progbits
#endif