| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2011-2016 Free Software Foundation, Inc. | 
|  | 2 | This file is part of the GNU C Library. | 
|  | 3 | Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. | 
|  | 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 | <http://www.gnu.org/licenses/>.  */ | 
|  | 18 |  | 
|  | 19 | #include <sysdep.h> | 
|  | 20 | #include <arch/abi.h> | 
|  | 21 |  | 
|  | 22 | /* This function is called via the PLT header, which is called | 
|  | 23 | from an individual PLT entry. | 
|  | 24 |  | 
|  | 25 | At this point we have several values passed in: | 
|  | 26 |  | 
|  | 27 | lr:  return address to original user code | 
|  | 28 | r28: the tpnt value to pass to _dl_runtime_resolver | 
|  | 29 | r29: the PLT index of the invoked jump table entry. | 
|  | 30 |  | 
|  | 31 | We set up a frame entry that looks like this (in int_reg_t units): | 
|  | 32 |  | 
|  | 33 | +57: r25 return values from function... | 
|  | 34 | +56: r24 | 
|  | 35 | [...] | 
|  | 36 | +33: r1 | 
|  | 37 | +32: r0 | 
|  | 38 | +31: PLT index | 
|  | 39 | +30: tpnt | 
|  | 40 | +29: stackframe | 
|  | 41 | +28: caller lr | 
|  | 42 | +27: r25 arguments to function... | 
|  | 43 | +26: r24 | 
|  | 44 | [...] | 
|  | 45 | +3:  r1 | 
|  | 46 | +2:  r0 | 
|  | 47 | +1:  standard ABI slot (sp) | 
|  | 48 | +0:  standard ABI slot (callee lr) | 
|  | 49 |  | 
|  | 50 | The entries from "stackframe" up are only used in _dl_profile_resolve. | 
|  | 51 | We save and restore r0 through r25, rather than the strictly | 
|  | 52 | architected r0 through r9, to support unusual calling conventions; | 
|  | 53 | for example, __tls_get_addr takes r0 and returns r0, but promises | 
|  | 54 | not to clobber r1 through r24 to support its usual fast path.  */ | 
|  | 55 |  | 
|  | 56 | #define FRAME_SP		(1 * REGSIZE) | 
|  | 57 | #define FRAME_REGS		(2 * REGSIZE) | 
|  | 58 | #define FRAME_LR		(28 * REGSIZE)  /* Must follow FRAME_REGS */ | 
|  | 59 | #define FRAME_STACKFRAME	(29 * REGSIZE) | 
|  | 60 | #define FRAME_TPNT		(30 * REGSIZE) | 
|  | 61 | #define FRAME_INDEX		(31 * REGSIZE) | 
|  | 62 | #define FRAME_RETVAL		(32 * REGSIZE) | 
|  | 63 |  | 
|  | 64 | #define FRAME_SIZE_SMALL	(30 * REGSIZE) | 
|  | 65 | #define FRAME_SIZE_LARGE	(58 * REGSIZE) | 
|  | 66 |  | 
|  | 67 | #define FOR_EACH_REG(f) \ | 
|  | 68 | f(r0);  f(r1);  f(r2);  f(r3);  \ | 
|  | 69 | f(r4);  f(r5);  f(r6);  f(r7);  \ | 
|  | 70 | f(r8);  f(r9);  f(r10); f(r11); \ | 
|  | 71 | f(r12); f(r13); f(r14); f(r15); \ | 
|  | 72 | f(r16); f(r17); f(r18); f(r19); \ | 
|  | 73 | f(r20); f(r21); f(r22); f(r23); \ | 
|  | 74 | f(r24); f(r25) | 
|  | 75 |  | 
|  | 76 | #define SAVE(REG) { ST r27, REG; ADDI_PTR r27, r27, REGSIZE } | 
|  | 77 | #define RESTORE(REG) { LD REG, r27; ADDI_PTR r27, r27, REGSIZE } | 
|  | 78 |  | 
|  | 79 | .macro dl_resolve, name, profile, framesize | 
|  | 80 | .text | 
|  | 81 | .global \name | 
|  | 82 | .hidden \name | 
|  | 83 | /* Note that cpp expands ENTRY(\name) incorrectly. */ | 
|  | 84 | .type \name,@function | 
|  | 85 | .align 8 | 
|  | 86 | \name: | 
|  | 87 | cfi_startproc | 
|  | 88 | { | 
|  | 89 | ST sp, lr | 
|  | 90 | move r26, sp | 
|  | 91 | } | 
|  | 92 | { | 
|  | 93 | ADDLI_PTR sp, sp, -\framesize | 
|  | 94 | ADDLI_PTR r27, sp, FRAME_SP - \framesize | 
|  | 95 | } | 
|  | 96 | cfi_def_cfa_offset (\framesize) | 
|  | 97 | { | 
|  | 98 | ST r27, r26 | 
|  | 99 | ADDI_PTR r27, r27, FRAME_REGS - FRAME_SP | 
|  | 100 | } | 
|  | 101 | FOR_EACH_REG(SAVE) | 
|  | 102 | { | 
|  | 103 | ST r27, lr | 
|  | 104 | ADDLI_PTR r27, sp, FRAME_TPNT | 
|  | 105 | } | 
|  | 106 | cfi_offset (lr, FRAME_LR - \framesize) | 
|  | 107 | .if \profile | 
|  | 108 | { | 
|  | 109 | move r0, r28  /* tpnt value */ | 
|  | 110 | ST r27, r28 | 
|  | 111 | ADDI_PTR r27, r27, FRAME_INDEX - FRAME_TPNT | 
|  | 112 | } | 
|  | 113 | { | 
|  | 114 | move r1, r29  /* PLT index */ | 
|  | 115 | ST r27, r29 | 
|  | 116 | } | 
|  | 117 | { | 
|  | 118 | move r2, lr  /* retaddr */ | 
|  | 119 | ADDI_PTR r3, sp, FRAME_REGS  /* La_tile_regs pointer */ | 
|  | 120 | } | 
|  | 121 | { | 
|  | 122 | ADDLI_PTR r4, sp, FRAME_STACKFRAME  /* framesize pointer */ | 
|  | 123 | jal _dl_profile_fixup | 
|  | 124 | } | 
|  | 125 | ADDLI_PTR r28, sp, FRAME_STACKFRAME | 
|  | 126 | LD_PTR r28, r28 | 
|  | 127 | BGTZ r28, 1f | 
|  | 128 | .else | 
|  | 129 | { | 
|  | 130 | move r0, r28  /* tpnt value 1 */ | 
|  | 131 | move r1, r29  /* PLT index 2 */ | 
|  | 132 | } | 
|  | 133 | jal _dl_fixup | 
|  | 134 | .endif | 
|  | 135 | { | 
|  | 136 | /* Copy aside the return value so we can restore r0 below. */ | 
|  | 137 | move r29, r0 | 
|  | 138 | /* Set up r27 to let us start restoring registers. */ | 
|  | 139 | ADDLI_PTR r27, sp, FRAME_REGS | 
|  | 140 | } | 
|  | 141 | FOR_EACH_REG(RESTORE) | 
|  | 142 | .if \profile | 
|  | 143 | ADDLI_PTR r28, sp, FRAME_STACKFRAME | 
|  | 144 | LD r28, r28 | 
|  | 145 | BGTZ r28, 1f | 
|  | 146 | .endif | 
|  | 147 | { | 
|  | 148 | /* Restore original user return address. */ | 
|  | 149 | LD lr, r27 | 
|  | 150 | /* Pop off our stack frame. */ | 
|  | 151 | ADDLI_PTR sp, sp, \framesize | 
|  | 152 | } | 
|  | 153 | cfi_def_cfa_offset (0) | 
|  | 154 | jr r29  /* Transfer control to freshly loaded code. */ | 
|  | 155 | jrp lr  /* Keep backtracer happy. */ | 
|  | 156 |  | 
|  | 157 | .if \profile | 
|  | 158 | 1:	jalr r29   /* Call resolved function. */ | 
|  | 159 | { | 
|  | 160 | ADDLI_PTR r28, sp, FRAME_TPNT | 
|  | 161 | ADDLI_PTR r27, sp, FRAME_RETVAL | 
|  | 162 | } | 
|  | 163 | FOR_EACH_REG(SAVE) | 
|  | 164 | { | 
|  | 165 | LD r0, r28 | 
|  | 166 | ADDI_PTR r28, r28, FRAME_INDEX - FRAME_TPNT | 
|  | 167 | } | 
|  | 168 | { | 
|  | 169 | LD r1, r28 | 
|  | 170 | ADDLI_PTR r2, sp, FRAME_REGS | 
|  | 171 | } | 
|  | 172 | { | 
|  | 173 | ADDLI_PTR r3, sp, FRAME_RETVAL | 
|  | 174 | jal _dl_call_pltexit | 
|  | 175 | } | 
|  | 176 | { | 
|  | 177 | ADDLI_PTR lr, sp, FRAME_LR | 
|  | 178 | ADDLI_PTR r27, sp, FRAME_RETVAL | 
|  | 179 | } | 
|  | 180 | FOR_EACH_REG(RESTORE) | 
|  | 181 | { | 
|  | 182 | LD lr, lr | 
|  | 183 | ADDLI_PTR sp, sp, \framesize | 
|  | 184 | } | 
|  | 185 | jrp lr | 
|  | 186 | .endif | 
|  | 187 | END (\name) | 
|  | 188 | .endm | 
|  | 189 |  | 
|  | 190 | dl_resolve _dl_runtime_resolve, 0, FRAME_SIZE_SMALL | 
|  | 191 | #ifndef PROF | 
|  | 192 | dl_resolve _dl_runtime_profile, 1, FRAME_SIZE_LARGE | 
|  | 193 | #endif |