1 | /* 64 bit S/390-specific implementation of profiling support. |
2 | Copyright (C) 2001-2024 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 | |