450 lines
10 KiB
ArmAsm
450 lines
10 KiB
ArmAsm
/* Copyright (C) 2012-2022 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/>. */
|
|
|
|
.text
|
|
|
|
#include "asmcfi.h"
|
|
|
|
#if defined(__powerpc64__) && _CALL_ELF == 2 && defined(__PCREL__)
|
|
.macro FUNC name
|
|
.globl \name
|
|
.type \name, @function
|
|
\name:
|
|
.localentry \name, 1
|
|
.endm
|
|
.macro END name
|
|
.size \name, . - \name
|
|
.endm
|
|
.macro HIDDEN name
|
|
.hidden \name
|
|
.endm
|
|
.macro CALL name
|
|
bl \name @notoc
|
|
.endm
|
|
#elif defined(__powerpc64__) && _CALL_ELF == 2
|
|
.macro FUNC name
|
|
.globl \name
|
|
.type \name, @function
|
|
\name:
|
|
0: addis 2,12,(.TOC.-0b)@ha
|
|
addi 2,2,(.TOC.-0b)@l
|
|
.localentry \name, . - \name
|
|
.endm
|
|
.macro END name
|
|
.size \name, . - \name
|
|
.endm
|
|
.macro HIDDEN name
|
|
.hidden \name
|
|
.endm
|
|
.macro CALL name
|
|
bl \name
|
|
nop
|
|
.endm
|
|
#elif defined(__powerpc64__) && defined(__ELF__)
|
|
.macro FUNC name
|
|
.globl \name, .\name
|
|
.section ".opd","aw"
|
|
.align 3
|
|
\name:
|
|
.quad .\name, .TOC.@tocbase, 0
|
|
.size \name, 24
|
|
.type .\name, @function
|
|
.text
|
|
.\name:
|
|
.endm
|
|
.macro END name
|
|
.size .\name, . - .\name
|
|
.endm
|
|
.macro HIDDEN name
|
|
.hidden \name, .\name
|
|
.endm
|
|
.macro CALL name
|
|
bl \name
|
|
nop
|
|
.endm
|
|
#elif defined(__ELF__)
|
|
.macro FUNC name
|
|
.globl \name
|
|
.type \name, @function
|
|
\name:
|
|
.endm
|
|
.macro END name
|
|
.size \name, . - \name
|
|
.endm
|
|
.macro HIDDEN name
|
|
.hidden \name
|
|
.endm
|
|
.macro CALL name
|
|
bl \name
|
|
.endm
|
|
#elif defined(_CALL_DARWIN)
|
|
.macro FUNC
|
|
.globl _$0
|
|
_$0:
|
|
.endmacro
|
|
.macro END
|
|
.endmacro
|
|
.macro HIDDEN
|
|
.private_extern _$0
|
|
.endmacro
|
|
.macro CALL
|
|
bl _$0
|
|
.endmacro
|
|
# ifdef __ppc64__
|
|
.machine ppc64
|
|
# else
|
|
.machine ppc7400
|
|
# endif
|
|
#else
|
|
#error "unsupported system"
|
|
#endif
|
|
|
|
/* Parameterize the naming of registers. */
|
|
#if defined(__ELF__)
|
|
# define r(N) %r##N
|
|
# define f(N) %f##N
|
|
# define v(N) %v##N
|
|
#elif defined(__MACH__)
|
|
# define r(N) r##N
|
|
# define f(N) f##N
|
|
# define v(N) v##N
|
|
#else
|
|
# define r(N) N
|
|
# define f(N) N
|
|
# define v(N) N
|
|
#endif
|
|
|
|
/* Parameterize the code for 32-bit vs 64-bit. */
|
|
#if defined(__powerpc64__) || defined(__ppc64__)
|
|
#define ldreg ld
|
|
#define streg std
|
|
#define stregu stdu
|
|
#define WS 8
|
|
#else
|
|
#define ldreg lwz
|
|
#define streg stw
|
|
#define stregu stwu
|
|
#define WS 4
|
|
#endif
|
|
|
|
/* Parameterize the code for call frame constants. */
|
|
#if defined(_CALL_AIXDESC)
|
|
# define BASE 6*WS
|
|
# define LR_SAVE 2*WS
|
|
#elif _CALL_ELF == 2
|
|
# define BASE 6*WS
|
|
# define LR_SAVE 2*WS
|
|
#elif defined(_CALL_SYSV)
|
|
# define BASE 2*WS
|
|
# define LR_SAVE 1*WS
|
|
#elif defined(_CALL_DARWIN)
|
|
# define BASE (6*WS + 2*WS)
|
|
# define LR_SAVE 2*WS
|
|
#else
|
|
# error "unsupported system"
|
|
#endif
|
|
|
|
#if defined(__ALTIVEC__) || defined(__VSX__)
|
|
# define OFS_VR 0
|
|
# define OFS_VSCR 12*16
|
|
# define OFS_VR_END OFS_VSCR + 8
|
|
#else
|
|
# define OFS_VR_END 0
|
|
#endif
|
|
#ifndef _SOFT_FLOAT
|
|
# define OFS_FR OFS_VR_END
|
|
# define OFS_FPSCR OFS_FR + 18*8
|
|
# define OFS_FR_END OFS_FPSCR + 8
|
|
#else
|
|
# define OFS_FR_END OFS_VR_END
|
|
#endif
|
|
#define OFS_GR OFS_FR_END
|
|
#define OFS_CFA OFS_GR + 18*WS
|
|
#define OFS_LR OFS_CFA + WS
|
|
#define OFS_TOC OFS_LR + WS
|
|
#define OFS_CR OFS_TOC + WS
|
|
#define OFS_END (((OFS_CR + WS + 15) / 16) * 16)
|
|
|
|
#define FRAME (((BASE + OFS_END + 15) / 16) * 16)
|
|
#define VRSAVE 256
|
|
|
|
.align 4
|
|
FUNC _ITM_beginTransaction
|
|
cfi_startproc
|
|
mflr r(0)
|
|
mfcr r(5)
|
|
addi r(4), r(1), -OFS_END
|
|
mr r(6), r(1)
|
|
streg r(0), LR_SAVE(r(1))
|
|
stregu r(1), -FRAME(r(1))
|
|
cfi_def_cfa_offset(FRAME)
|
|
cfi_offset(65, LR_SAVE)
|
|
streg r(6), OFS_CFA(r(4))
|
|
streg r(0), OFS_LR(r(4))
|
|
#ifdef _CALL_DARWIN
|
|
streg r(13), OFS_TOC(r(4))
|
|
#else
|
|
streg r(2), OFS_TOC(r(4))
|
|
#endif
|
|
streg r(5), OFS_CR(r(4))
|
|
streg r(14), 0*WS+OFS_GR(r(4))
|
|
streg r(15), 1*WS+OFS_GR(r(4))
|
|
streg r(16), 2*WS+OFS_GR(r(4))
|
|
streg r(17), 3*WS+OFS_GR(r(4))
|
|
streg r(18), 4*WS+OFS_GR(r(4))
|
|
streg r(19), 5*WS+OFS_GR(r(4))
|
|
streg r(20), 6*WS+OFS_GR(r(4))
|
|
streg r(21), 7*WS+OFS_GR(r(4))
|
|
streg r(22), 8*WS+OFS_GR(r(4))
|
|
streg r(23), 9*WS+OFS_GR(r(4))
|
|
streg r(24), 10*WS+OFS_GR(r(4))
|
|
streg r(25), 11*WS+OFS_GR(r(4))
|
|
streg r(26), 12*WS+OFS_GR(r(4))
|
|
streg r(27), 13*WS+OFS_GR(r(4))
|
|
streg r(28), 14*WS+OFS_GR(r(4))
|
|
streg r(29), 15*WS+OFS_GR(r(4))
|
|
streg r(30), 16*WS+OFS_GR(r(4))
|
|
streg r(31), 17*WS+OFS_GR(r(4))
|
|
|
|
#ifndef _SOFT_FLOAT
|
|
/* ??? Determine when FPRs not present. */
|
|
/* ??? Test r(3) for pr_hasNoFloatUpdate and skip the fp save.
|
|
This is not yet set by the compiler. */
|
|
mffs f(0)
|
|
stfd f(14), 0+OFS_FR(r(4))
|
|
stfd f(15), 8+OFS_FR(r(4))
|
|
stfd f(16), 16+OFS_FR(r(4))
|
|
stfd f(17), 24+OFS_FR(r(4))
|
|
stfd f(18), 32+OFS_FR(r(4))
|
|
stfd f(19), 40+OFS_FR(r(4))
|
|
stfd f(20), 48+OFS_FR(r(4))
|
|
stfd f(21), 56+OFS_FR(r(4))
|
|
stfd f(22), 64+OFS_FR(r(4))
|
|
stfd f(23), 72+OFS_FR(r(4))
|
|
stfd f(24), 80+OFS_FR(r(4))
|
|
stfd f(25), 88+OFS_FR(r(4))
|
|
stfd f(26), 96+OFS_FR(r(4))
|
|
stfd f(27),104+OFS_FR(r(4))
|
|
stfd f(28),112+OFS_FR(r(4))
|
|
stfd f(29),120+OFS_FR(r(4))
|
|
stfd f(30),128+OFS_FR(r(4))
|
|
stfd f(31),136+OFS_FR(r(4))
|
|
stfd f(0), OFS_FPSCR(r(4))
|
|
#endif
|
|
|
|
#if defined(__ALTIVEC__)
|
|
/* ??? Determine when VRs not present. */
|
|
/* ??? Test r(3) for pr_hasNoVectorUpdate and skip the vr save.
|
|
This is not yet set by the compiler. */
|
|
addi r(5), r(4), OFS_VR
|
|
addi r(6), r(4), OFS_VR+16
|
|
mfspr r(0), VRSAVE
|
|
stvx v(20), 0, r(5)
|
|
addi r(5), r(5), 32
|
|
stvx v(21), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
stvx v(22), 0, r(5)
|
|
addi r(5), r(5), 32
|
|
stvx v(23), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
stvx v(25), 0, r(5)
|
|
addi r(5), r(5), 32
|
|
stvx v(26), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
stvx v(26), 0, r(5)
|
|
addi r(5), r(5), 32
|
|
stvx v(27), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
stvx v(28), 0, r(5)
|
|
addi r(5), r(5), 32
|
|
stvx v(29), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
stvx v(30), 0, r(5)
|
|
stvx v(31), 0, r(6)
|
|
streg r(0), OFS_VSCR(r(4))
|
|
#endif
|
|
|
|
CALL GTM_begin_transaction
|
|
|
|
ldreg r(0), LR_SAVE+FRAME(r(1))
|
|
mtlr r(0)
|
|
addi r(1), r(1), FRAME
|
|
cfi_def_cfa_offset(0)
|
|
cfi_restore(65)
|
|
blr
|
|
cfi_endproc
|
|
END _ITM_beginTransaction
|
|
|
|
.align 4
|
|
HIDDEN GTM_longjmp
|
|
FUNC GTM_longjmp
|
|
cfi_startproc
|
|
#if defined(__ALTIVEC__) || defined(__VSX__)
|
|
/* ??? Determine when VRs not present. */
|
|
/* ??? Test r(5) for pr_hasNoVectorUpdate and skip the vr restore.
|
|
This is not yet set by the compiler. */
|
|
addi r(6), r(4), OFS_VR
|
|
addi r(7), r(4), OFS_VR+16
|
|
ldreg r(0), OFS_VSCR(r(4))
|
|
cfi_undefined(v(20))
|
|
cfi_undefined(v(21))
|
|
cfi_undefined(v(22))
|
|
cfi_undefined(v(23))
|
|
cfi_undefined(v(24))
|
|
cfi_undefined(v(25))
|
|
cfi_undefined(v(26))
|
|
cfi_undefined(v(27))
|
|
cfi_undefined(v(28))
|
|
cfi_undefined(v(29))
|
|
cfi_undefined(v(30))
|
|
cfi_undefined(v(31))
|
|
lvx v(20), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
lvx v(21), 0, r(7)
|
|
addi r(7), r(7), 32
|
|
lvx v(22), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
lvx v(23), 0, r(7)
|
|
addi r(7), r(7), 32
|
|
lvx v(24), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
lvx v(25), 0, r(7)
|
|
addi r(7), r(7), 32
|
|
lvx v(26), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
lvx v(27), 0, r(7)
|
|
addi r(7), r(7), 32
|
|
lvx v(28), 0, r(6)
|
|
addi r(6), r(6), 32
|
|
lvx v(29), 0, r(7)
|
|
addi r(7), r(7), 32
|
|
lvx v(30), 0, r(6)
|
|
lvx v(31), 0, r(7)
|
|
mtspr VRSAVE, r(0)
|
|
#endif
|
|
|
|
#ifndef _SOFT_FLOAT
|
|
/* ??? Determine when FPRs not present. */
|
|
/* ??? Test r(5) for pr_hasNoFloatUpdate and skip the fp load.
|
|
This is not yet set by the compiler. */
|
|
lfd f(0), OFS_FPSCR(r(4))
|
|
cfi_undefined(f(14))
|
|
cfi_undefined(f(15))
|
|
cfi_undefined(f(16))
|
|
cfi_undefined(f(17))
|
|
cfi_undefined(f(18))
|
|
cfi_undefined(f(19))
|
|
cfi_undefined(f(20))
|
|
cfi_undefined(f(21))
|
|
cfi_undefined(f(22))
|
|
cfi_undefined(f(23))
|
|
cfi_undefined(f(24))
|
|
cfi_undefined(f(25))
|
|
cfi_undefined(f(26))
|
|
cfi_undefined(f(27))
|
|
cfi_undefined(f(28))
|
|
cfi_undefined(f(29))
|
|
cfi_undefined(f(30))
|
|
cfi_undefined(f(31))
|
|
lfd f(14), 0+OFS_FR(r(4))
|
|
lfd f(15), 8+OFS_FR(r(4))
|
|
lfd f(16), 16+OFS_FR(r(4))
|
|
lfd f(17), 24+OFS_FR(r(4))
|
|
lfd f(18), 32+OFS_FR(r(4))
|
|
lfd f(19), 40+OFS_FR(r(4))
|
|
lfd f(20), 48+OFS_FR(r(4))
|
|
lfd f(21), 56+OFS_FR(r(4))
|
|
lfd f(22), 64+OFS_FR(r(4))
|
|
lfd f(23), 72+OFS_FR(r(4))
|
|
lfd f(24), 80+OFS_FR(r(4))
|
|
lfd f(25), 88+OFS_FR(r(4))
|
|
lfd f(26), 96+OFS_FR(r(4))
|
|
lfd f(27),104+OFS_FR(r(4))
|
|
lfd f(28),112+OFS_FR(r(4))
|
|
lfd f(29),120+OFS_FR(r(4))
|
|
lfd f(30),128+OFS_FR(r(4))
|
|
lfd f(31),136+OFS_FR(r(4))
|
|
mtfsf 0xff, f(0)
|
|
#endif
|
|
|
|
ldreg r(6), OFS_CFA(r(4))
|
|
ldreg r(0), OFS_LR(r(4))
|
|
#ifdef _CALL_DARWIN
|
|
ldreg r(13), OFS_TOC(r(4))
|
|
#else
|
|
ldreg r(2), OFS_TOC(r(4))
|
|
#endif
|
|
ldreg r(7), OFS_CR(r(4))
|
|
/* At the instant we restore the LR, the only coherent view of
|
|
the world we have is into the new stack frame. Define the
|
|
CFA in terms of the not-yet-restored stack pointer. This will
|
|
last until the end of the function. */
|
|
mtlr r(0)
|
|
cfi_def_cfa(r(6), 0)
|
|
cfi_undefined(r(14))
|
|
cfi_undefined(r(15))
|
|
cfi_undefined(r(16))
|
|
cfi_undefined(r(17))
|
|
cfi_undefined(r(18))
|
|
cfi_undefined(r(19))
|
|
cfi_undefined(r(20))
|
|
cfi_undefined(r(21))
|
|
cfi_undefined(r(22))
|
|
cfi_undefined(r(23))
|
|
cfi_undefined(r(24))
|
|
cfi_undefined(r(25))
|
|
cfi_undefined(r(26))
|
|
cfi_undefined(r(27))
|
|
cfi_undefined(r(28))
|
|
cfi_undefined(r(29))
|
|
cfi_undefined(r(30))
|
|
cfi_undefined(r(31))
|
|
mtcr r(7)
|
|
ldreg r(14), 0*WS+OFS_GR(r(4))
|
|
ldreg r(15), 1*WS+OFS_GR(r(4))
|
|
ldreg r(16), 2*WS+OFS_GR(r(4))
|
|
ldreg r(17), 3*WS+OFS_GR(r(4))
|
|
ldreg r(18), 4*WS+OFS_GR(r(4))
|
|
ldreg r(19), 5*WS+OFS_GR(r(4))
|
|
ldreg r(20), 6*WS+OFS_GR(r(4))
|
|
ldreg r(21), 7*WS+OFS_GR(r(4))
|
|
ldreg r(22), 8*WS+OFS_GR(r(4))
|
|
ldreg r(23), 9*WS+OFS_GR(r(4))
|
|
ldreg r(24), 10*WS+OFS_GR(r(4))
|
|
ldreg r(25), 11*WS+OFS_GR(r(4))
|
|
ldreg r(26), 12*WS+OFS_GR(r(4))
|
|
ldreg r(27), 13*WS+OFS_GR(r(4))
|
|
ldreg r(28), 14*WS+OFS_GR(r(4))
|
|
ldreg r(29), 15*WS+OFS_GR(r(4))
|
|
ldreg r(30), 16*WS+OFS_GR(r(4))
|
|
ldreg r(31), 17*WS+OFS_GR(r(4))
|
|
mr r(1), r(6)
|
|
blr
|
|
cfi_endproc
|
|
END GTM_longjmp
|
|
|
|
#ifdef __linux__
|
|
.section .note.GNU-stack, "", @progbits
|
|
#endif
|