/* Copyright (C) 2011-2015 Free Software Foundation, Inc. Contributed by Richard Henderson . 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 . */ #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