| /* Copyright (C) 2011-2018 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(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 |