1 /* 64 bit S/390-specific implementation of profiling support.
2    Copyright (C) 2001-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <sysdep.h>
20 
21 /* How profiling works on 64 bit S/390:
22    On the start of each function _mcount is called with the address of a
23    data word in %r1 (initialized to 0, used for counting). The compiler
24    with the option -p generates code of the form:
25 
26            STM    6,15,24(15)
27            BRAS   13,.LTN0_0
28    .LT0_0:
29    .LC13:  .long  .LP0
30            .data
31            .align 4
32    .LP0:   .long  0
33            .text
34    # function profiler
35            stg    14,8(15)
36            lg     1,.LC13-.LT0_0(13)
37            brasl  14,_mcount
38            lg     14,8(15)
39 
40    The _mcount implementation now has to call __mcount_internal with the
41    address of .LP0 as first parameter and the return address as second
42    parameter. &.LP0 was loaded to %r1 and the return address is in %r14.
43    _mcount may not modify any register.
44 
45    Alternatively, at the start of each function __fentry__ is called using a
46    single
47 
48    # function profiler
49            brasl  0,__fentry__
50 
51    instruction.  In this case %r0 points to the callee, and %r14 points to the
52    caller.  These values need to be passed to __mcount_internal using the same
53    sequence as for _mcount, so the code below is shared between both functions.
54    The only major difference is that __fentry__ cannot return through %r0, in
55    which the return address is located, because br instruction is a no-op with
56    this register.  Therefore %r1, which is clobbered by the PLT anyway, is
57    used.  */
58 
59 #define xglue(x, y) x ## y
60 #define glue(x, y) xglue(x, y)
61 
62 	.globl C_SYMBOL_NAME(MCOUNT_SYMBOL)
63 	.type C_SYMBOL_NAME(MCOUNT_SYMBOL), @function
64 	cfi_startproc
65 	.align ALIGNARG(4)
66 C_LABEL(MCOUNT_SYMBOL)
67 	cfi_return_column (glue(r, MCOUNT_CALLEE_REG))
68 	/* Save the caller-clobbered registers.  */
69 	aghi  %r15,-224
70 	cfi_adjust_cfa_offset (224)
71 	/* binutils 2.28+: .cfi_val_offset r15, -160 */
72 	.cfi_escape \
73 		/* DW_CFA_val_offset */ 0x14, \
74 		/* r15 */               0x0f, \
75 		/* scaled offset */     0x14
76 	stmg  %r14,%r5,160(%r15)
77 	cfi_offset (r14, -224)
78 	cfi_offset (r0, -224+16)
79 	lg    %r2,MCOUNT_CALLER_OFF(%r15)	# callers address  = 1st param
80 	lgr   %r3,glue(%r, MCOUNT_CALLEE_REG)	# callees address  = 2nd param
81 
82 #ifdef PIC
83 	brasl %r14,__mcount_internal@PLT
84 #else
85 	brasl %r14,__mcount_internal
86 #endif
87 
88 	/* Pop the saved registers.  Please note that `mcount' has no
89 	   return value.  */
90 	lmg   %r14,%r5,160(%r15)
91 	aghi  %r15,224
92 	cfi_adjust_cfa_offset (-224)
93 #if MCOUNT_RETURN_REG != MCOUNT_CALLEE_REG
94 	lgr   glue(%r, MCOUNT_RETURN_REG),glue(%r, MCOUNT_CALLEE_REG)
95 #endif
96 	br    glue(%r, MCOUNT_RETURN_REG)
97 	cfi_endproc
98 	ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(MCOUNT_SYMBOL))
99