| 1 | /* Machine-specific calling sequence for `mcount' profiling function. alpha |
| 2 | Copyright (C) 1995-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 | /* Assembly stub to invoke _mcount(). Compiler generated code calls |
| 20 | this stub after executing a function's prologue and without saving any |
| 21 | registers. It is therefore necessary to preserve a0..a5 as they may |
| 22 | contain function arguments. To work correctly with frame- less |
| 23 | functions, it is also necessary to preserve ra. Finally, division |
| 24 | routines are invoked with a special calling convention and the |
| 25 | compiler treats those calls as if they were instructions. In |
| 26 | particular, it doesn't save any of the temporary registers (caller |
| 27 | saved registers). It is therefore necessary to preserve all |
| 28 | caller-saved registers as well. |
| 29 | |
| 30 | Upon entering _mcount, register $at holds the return address and ra |
| 31 | holds the return address of the function's caller (selfpc and frompc, |
| 32 | respectively in gmon.c language...). */ |
| 33 | |
| 34 | #include <sysdep.h> |
| 35 | |
| 36 | .set noat |
| 37 | .set noreorder |
| 38 | |
| 39 | LEAF(_mcount, 0xb0) |
| 40 | subq sp, 0xb0, sp |
| 41 | .prologue 0 |
| 42 | stq a0, 0x00(sp) |
| 43 | mov ra, a0 # a0 = caller-pc |
| 44 | stq a1, 0x08(sp) |
| 45 | mov $at, a1 # a1 = self-pc |
| 46 | stq $at, 0x10(sp) |
| 47 | |
| 48 | stq a2, 0x18(sp) |
| 49 | stq a3, 0x20(sp) |
| 50 | stq a4, 0x28(sp) |
| 51 | stq a5, 0x30(sp) |
| 52 | stq ra, 0x38(sp) |
| 53 | stq gp, 0x40(sp) |
| 54 | |
| 55 | br gp, 1f |
| 56 | 1: ldgp gp, 0(gp) |
| 57 | |
| 58 | stq t0, 0x48(sp) |
| 59 | stq t1, 0x50(sp) |
| 60 | stq t2, 0x58(sp) |
| 61 | stq t3, 0x60(sp) |
| 62 | stq t4, 0x68(sp) |
| 63 | stq t5, 0x70(sp) |
| 64 | stq t6, 0x78(sp) |
| 65 | |
| 66 | stq t7, 0x80(sp) |
| 67 | stq t8, 0x88(sp) |
| 68 | stq t9, 0x90(sp) |
| 69 | stq t10, 0x98(sp) |
| 70 | stq t11, 0xa0(sp) |
| 71 | stq v0, 0xa8(sp) |
| 72 | |
| 73 | jsr ra, __mcount |
| 74 | |
| 75 | ldq a0, 0x00(sp) |
| 76 | ldq a1, 0x08(sp) |
| 77 | ldq $at, 0x10(sp) # restore self-pc |
| 78 | ldq a2, 0x18(sp) |
| 79 | ldq a3, 0x20(sp) |
| 80 | ldq a4, 0x28(sp) |
| 81 | ldq a5, 0x30(sp) |
| 82 | ldq ra, 0x38(sp) |
| 83 | ldq gp, 0x40(sp) |
| 84 | mov $at, pv # make pv point to return address |
| 85 | ldq t0, 0x48(sp) # this is important under OSF/1 to |
| 86 | ldq t1, 0x50(sp) # ensure that the code that we return |
| 87 | ldq t2, 0x58(sp) # can correctly compute its gp |
| 88 | ldq t3, 0x60(sp) |
| 89 | ldq t4, 0x68(sp) |
| 90 | ldq t5, 0x70(sp) |
| 91 | ldq t6, 0x78(sp) |
| 92 | ldq t7, 0x80(sp) |
| 93 | ldq t8, 0x88(sp) |
| 94 | ldq t9, 0x90(sp) |
| 95 | ldq t10, 0x98(sp) |
| 96 | ldq t11, 0xa0(sp) |
| 97 | ldq v0, 0xa8(sp) |
| 98 | |
| 99 | addq sp, 0xb0, sp |
| 100 | ret zero,($at),1 |
| 101 | |
| 102 | END(_mcount) |
| 103 | |
| 104 | weak_alias (_mcount, mcount) |
| 105 | |