1 | /* S/390-specific implementation of profiling support. |
2 | Copyright (C) 2000-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 | /* |
22 | * How profiling works on S/390: |
23 | * On the start of each function _mcount is called with the address of a |
24 | * data word in %r1 (initialized to 0, used for counting). The compiler |
25 | * with the option -p generates code of the form: |
26 | * |
27 | * STM 6,15,24(15) |
28 | * BRAS 13,.LTN0_0 |
29 | * .LT0_0: |
30 | * .LC12: .long _mcount |
31 | * .LC13: .long .LP0 |
32 | * .data |
33 | * .align 4 |
34 | * .LP0: .long 0 |
35 | * .text |
36 | * # function profiler |
37 | * st 14,4(15) |
38 | * l 14,.LC12-.LT0_0(13) |
39 | * l 1,.LC13-.LT0_0(13) |
40 | * basr 14,14 |
41 | * l 14,4(15) |
42 | * |
43 | * The _mcount implementation now has to call __mcount_internal with the |
44 | * address of .LP0 as first parameter and the return address as second |
45 | * parameter. &.LP0 was loaded to %r1 and the return address is in %r14. |
46 | * _mcount may not modify any register. |
47 | */ |
48 | |
49 | .globl C_SYMBOL_NAME(_mcount) |
50 | .type C_SYMBOL_NAME(_mcount), @function |
51 | cfi_startproc |
52 | .align ALIGNARG(4) |
53 | C_LABEL(_mcount) |
54 | /* Save the caller-clobbered registers. */ |
55 | ahi %r15,-128 |
56 | cfi_adjust_cfa_offset (128) |
57 | /* binutils 2.28+: .cfi_val_offset r15, -96 */ |
58 | .cfi_escape \ |
59 | /* DW_CFA_val_offset */ 0x14, \ |
60 | /* r15 */ 0x0f, \ |
61 | /* scaled offset */ 0x18 |
62 | stm %r14,%r5,96(%r15) |
63 | cfi_offset (r14, -128) |
64 | l %r2,132(%r15) # callers address = first parameter |
65 | la %r2,0(%r2) # clear bit 0 |
66 | la %r3,0(%r14) # callees address = second parameter |
67 | |
68 | #ifdef PIC |
69 | bras %r14,0f |
70 | .long _GLOBAL_OFFSET_TABLE_-. |
71 | 0: al %r14,0(%r14) |
72 | l %r14,__mcount_internal@GOT(%r14) |
73 | #else |
74 | bras %r14,0f |
75 | .long __mcount_internal |
76 | 0: l %r14,0(%r14) |
77 | #endif |
78 | basr %r14,%r14 |
79 | |
80 | /* |
81 | * Pop the saved registers. Please note that `mcount' has no |
82 | * return value. |
83 | */ |
84 | lm %r14,%r5,96(%r15) |
85 | ahi %r15,128 |
86 | cfi_adjust_cfa_offset (-128) |
87 | br %r14 |
88 | cfi_endproc |
89 | ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(_mcount)) |
90 | |
91 | #undef mcount |
92 | weak_alias (_mcount, mcount) |
93 | |