1 /* libunwind - a platform-independent unwind library 2 Copyright (C) 2001-2003 Hewlett-Packard Co 3 Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com> 4 5 This file is part of libunwind. 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 "Software"), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be 16 included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 25 26 #include "ucontext_i.h" 27 28 #ifdef UNW_LOCAL_ONLY 29 # include "Lcursor_i.h" 30 # define ia64_install_cursor _ULia64_install_cursor 31 #else 32 # include "Gcursor_i.h" 33 # define ia64_install_cursor _Uia64_install_cursor 34 #endif 35 36 #define SYS_sigreturn 1181 37 38 #ifndef UNW_REMOTE_ONLY 39 40 /* ia64_install_cursor (const cursor *c, long pri_unat, long *extra, 41 long bspstore, long dirty_size, long *dirty_partition, 42 long dirty_rnat) 43 44 Restores the machine-state represented by C and thereby resumes execution 45 in that frame. If the frame or one of its descendants was interrupted 46 by a signal, all registers are restored (including the signal mask). 47 Otherwise, only the preserved registers, the global-pointer (r1), and 48 the exception-arguments (r15-r18) are restored. */ 49 50 #define pRet p6 51 #define pSig p7 52 53 .align 32 54 .hidden ia64_install_cursor 55 .global ia64_install_cursor 56 .proc ia64_install_cursor 57 ia64_install_cursor: 58 alloc r3 = ar.pfs, 7, 0, 0, 0 59 invala 60 add r2 = FR_LOC_OFF, in0 61 ;; 62 63 ld8 r16 = [r2], LOC_SIZE // r16 = loc[IA64_REG_FR16] 64 mov.m r10 = ar.rsc // (ar.rsc: ~ 12 cycle latency) 65 add r3 = FR_LOC_OFF + 16, in0 66 ;; 67 68 ld8 r17 = [r2], 2*LOC_SIZE // r17 = loc[IA64_REG_FR17] 69 ld8 r18 = [r3], 2*LOC_SIZE // r18 = loc[IA64_REG_FR18] 70 and r16 = -4, r16 71 ;; 72 73 ld8 r19 = [r2], 2*LOC_SIZE // r19 = loc[IA64_REG_FR19] 74 ld8 r20 = [r3], 2*LOC_SIZE // r20 = loc[IA64_REG_FR20] 75 and r17 = -4, r17 76 ;; 77 78 ldf.fill f16 = [r16] // f16 restored (don't touch no more) 79 ldf.fill f17 = [r17] // f17 restored (don't touch no more) 80 and r18 = -4, r18 81 82 ld8 r21 = [r2], 2*LOC_SIZE // r21 = loc[IA64_REG_FR21] 83 ld8 r22 = [r3], 2*LOC_SIZE // r22 = loc[IA64_REG_FR22] 84 and r19 = -4, r19 85 ;; 86 87 ldf.fill f18 = [r18] // f18 restored (don't touch no more) 88 ldf.fill f19 = [r19] // f19 restored (don't touch no more) 89 and r20 = -4, r20 90 91 ld8 r23 = [r2], 2*LOC_SIZE // r23 = loc[IA64_REG_FR23] 92 ld8 r24 = [r3], 2*LOC_SIZE // r24 = loc[IA64_REG_FR24] 93 and r21 = -4, r21 94 ;; 95 96 ldf.fill f20 = [r20] // f20 restored (don't touch no more) 97 ldf.fill f21 = [r21] // f21 restored (don't touch no more) 98 and r22 = -4, r22 99 100 ld8 r25 = [r2], 2*LOC_SIZE // r25 = loc[IA64_REG_FR25] 101 ld8 r26 = [r3], 2*LOC_SIZE // r26 = loc[IA64_REG_FR26] 102 and r23 = -4, r23 103 ;; 104 105 ldf.fill f22 = [r22] // f22 restored (don't touch no more) 106 ldf.fill f23 = [r23] // f23 restored (don't touch no more) 107 and r24 = -4, r24 108 109 ld8 r27 = [r2], 2*LOC_SIZE // r27 = loc[IA64_REG_FR27] 110 ld8 r28 = [r3], 2*LOC_SIZE // r28 = loc[IA64_REG_FR28] 111 and r25 = -4, r25 112 ;; 113 114 ldf.fill f24 = [r24] // f24 restored (don't touch no more) 115 ldf.fill f25 = [r25] // f25 restored (don't touch no more) 116 and r26 = -4, r26 117 118 ld8 r29 = [r2], 2*LOC_SIZE // r29 = loc[IA64_REG_FR29] 119 ld8 r30 = [r3], 2*LOC_SIZE // r30 = loc[IA64_REG_FR30] 120 and r27 = -4, r27 121 ;; 122 123 ldf.fill f26 = [r26] // f26 restored (don't touch no more) 124 ldf.fill f27 = [r27] // f27 restored (don't touch no more) 125 and r28 = -4, r28 126 127 ld8 r31 = [r2] // r31 = loc[IA64_REG_FR31] 128 mov.m ar.unat = in1 129 and r29 = -4, r29 130 ;; 131 132 ldf.fill f28 = [r28] // f28 restored (don't touch no more) 133 ldf.fill f29 = [r29] // f29 restored (don't touch no more) 134 and r30 = -4, r30 135 136 ld8 r1 = [in2], 8 // gp restored (don't touch no more) 137 add r8 = SIGCONTEXT_ADDR_OFF, in0 138 and r31 = -4, r31 139 ;; 140 141 ld8 r8 = [r8] // r8 = sigcontext_addr 142 and r11 = 0x1c, r10 // clear all but rsc.be and rsc.pl 143 add r2 = PFS_LOC_OFF, in0 144 145 ldf.fill f30 = [r30] // f30 restored (don't touch no more) 146 ldf.fill f31 = [r31] // f31 restored (don't touch no more) 147 add r3 = 8, in2 148 ;; 149 150 ld8.fill r4 = [in2], 16 // r4 restored (don't touch no more) 151 ld8.fill r5 = [r3], 16 // r5 restored (don't touch no more) 152 cmp.eq pRet, pSig = r0, r8 // sigcontext_addr == NULL? 153 ;; 154 ld8.fill r6 = [in2], 16 // r6 restored (don't touch no more) 155 ld8.fill r7 = [r3] // r7 restored (don't touch no more) 156 add r3 = IP_OFF, in0 157 ;; 158 159 ld8 r14 = [r2], (B1_LOC_OFF - PFS_LOC_OFF) // r14 = pfs_loc 160 ld8 r15 = [r3] // r15 = ip 161 add r3 = (B2_LOC_OFF - IP_OFF), r3 162 ;; 163 164 ld8 r16 = [r2], (B3_LOC_OFF - B1_LOC_OFF) // r16 = b1_loc 165 ld8 r17= [r3], (B4_LOC_OFF - B2_LOC_OFF) // r17 = b2_loc 166 and r14 = -4, r14 167 ;; 168 169 ld8 r18 = [r2], (B5_LOC_OFF - B3_LOC_OFF) // r18 = b3_loc 170 ld8 r19 = [r3], (F2_LOC_OFF - B4_LOC_OFF) // r19 = b4_loc 171 and r16 = -4, r16 172 ;; 173 174 ld8 r20 = [r2], (F3_LOC_OFF - B5_LOC_OFF) // r20 = b5_loc 175 ld8 r21 = [r3], (F4_LOC_OFF - F2_LOC_OFF) // r21 = f2_loc 176 and r17 = -4, r17 177 ;; 178 179 ld8 r16 = [r16] // r16 = *b1_loc 180 ld8 r17 = [r17] // r17 = *b2_loc 181 and r18 = -4, r18 182 183 ld8 r22 = [r2], (F5_LOC_OFF - F3_LOC_OFF) // r21 = f3_loc 184 ld8 r23 = [r3], (UNAT_LOC_OFF - F4_LOC_OFF) // r22 = f4_loc 185 and r19 = -4, r19 186 ;; 187 188 ld8 r18 = [r18] // r18 = *b3_loc 189 ld8 r19 = [r19] // r19 = *b4_loc 190 and r20 = -4, r20 191 192 ld8 r24 = [r2], (LC_LOC_OFF - F5_LOC_OFF) // r24 = f5_loc 193 ld8 r25 = [r3], (FPSR_LOC_OFF - UNAT_LOC_OFF) // r25 = unat_loc 194 and r21 = -4, r21 195 ;; 196 197 and r22 = -4, r22 198 and r23 = -4, r23 199 and r24 = -4, r24 200 201 ld8 r20 = [r20] // r20 = *b5_loc 202 ldf.fill f2 = [r21] // f2 restored (don't touch no more) 203 mov b1 = r16 // b1 restored (don't touch no more) 204 ;; 205 206 ldf.fill f3 = [r22] // f3 restored (don't touch no more) 207 ldf.fill f4 = [r23] // f4 restored (don't touch no more) 208 mov b2 = r17 // b2 restored (don't touch no more) 209 210 ld8 r26 = [r2], (RNAT_LOC_OFF - LC_LOC_OFF) // r26 = lc_loc 211 ld8 r27 = [r3] // r27 = fpsr_loc 212 and r25 = -4, r25 213 214 add r3 = (PSP_OFF - FPSR_LOC_OFF), r3 215 nop 0 216 nop 0 217 ;; 218 219 ldf.fill f5 = [r24] // f5 restored (don't touch no more) 220 (pRet) ld8 r25 = [r25] // r25 = *unat_loc 221 mov b3 = r18 // b3 restored (don't touch no more) 222 223 ld8 r28 = [r2], (BSP_OFF - RNAT_LOC_OFF) // r28 = rnat_loc 224 ld8 r29 = [r3], (PR_OFF - PSP_OFF) // r29 = sp 225 mov b4 = r19 // b4 restored (don't touch no more) 226 227 and r26 = -4, r26 228 and r27 = -4, r27 229 mov b5 = r20 // b5 restored (don't touch no more) 230 ;; 231 232 ld8 r26 = [r26] // r26 = *lc_loc 233 ld8 r27 = [r27] // r27 = *fpsr_loc 234 and r28 = -4, r28 235 236 mov r30 = in3 // make backup-copy of new bsp 237 ld8 r31 = [r3] // r31 = pr 238 mov rp = r15 239 ;; 240 241 ld8 r28 = [r28] // r28 = rnat 242 mov.m ar.rsc = r11 // put RSE into enforced lazy mode 243 mov.i ar.lc = r26 // lc restored (don't touch no more) 244 ;; 245 246 loadrs // drop dirty partition 247 mov r9 = in2 // make backup-copy of &extra[r16] 248 cmp.eq p8, p0 = in4, r0 // dirty-size == 0? 249 (p8) br.cond.dpnt.many .skip_load_dirty 250 251 mov r2 = in4 // make backup-copy of dirty_size 252 mov r15 = in5 // make backup-copy of dirty_partition 253 mov r16 = in6 // make backup-copy of dirty_rnat 254 ;; 255 256 alloc r3 = ar.pfs, 0, 0, 0, 0 // drop register frame 257 dep r11 = r2, r11, 16, 16 258 ;; 259 mov.m ar.bspstore = r15 260 ;; 261 mov.m ar.rnat = r16 262 mov.m ar.rsc = r11 // 14 cycles latency to loadrs 263 ;; 264 loadrs // loadup new dirty partition 265 ;; 266 267 .skip_load_dirty: 268 mov.m ar.bspstore = r30 // restore register backing-store 269 add r3 = 8, r9 // r3 = &extra[r16] 270 ;; 271 272 (pRet) mov.m ar.fpsr = r27 // fpsr restored (don't touch no more) 273 mov.m ar.rnat = r28 274 (pSig) br.cond.dpnt.many .next 275 276 /****** Return via br.ret: */ 277 278 ld8 r14 = [r14] // r14 = *pfs_loc 279 ld8 r15 = [r9], 16 // r15 restored (don't touch no more) 280 mov pr = r31, -1 // pr restored (don't touch no more) 281 ;; 282 283 ld8 r16 = [r3], 16 // r16 restored (don't touch no more) 284 ld8 r17 = [r9] // r17 restored (don't touch no more) 285 nop.i 0 286 ;; 287 288 ld8 r18 = [r3] // r18 restored (don't touch no more) 289 mov.m ar.rsc = r10 // restore original ar.rsc 290 mov sp = r29 291 292 mov.m ar.unat = r25 // unat restored (don't touch no more) 293 mov.i ar.pfs = r14 294 br.ret.sptk.many rp 295 ;; 296 297 /****** Return via sigreturn(): */ 298 299 .next: mov.m ar.rsc = r10 // restore original ar.rsc 300 add r2 = (SC_FR + 6*16), r8 301 add r3 = (SC_FR + 7*16), r8 302 ;; 303 304 ldf.fill f6 = [r2], 32 305 ldf.fill f7 = [r3], 32 306 nop 0 307 ;; 308 309 ldf.fill f8 = [r2], 32 310 ldf.fill f9 = [r3], 32 311 nop 0 312 ;; 313 314 ldf.fill f10 = [r2], 32 315 ldf.fill f11 = [r3], 32 316 nop 0 317 ;; 318 319 ldf.fill f12 = [r2], 32 320 ldf.fill f13 = [r3], 32 321 nop 0 322 ;; 323 324 ldf.fill f14 = [r2], 32 325 ldf.fill f15 = [r3], 32 326 mov sp = r29 327 ;; 328 329 #if NEW_SYSCALL 330 add r2 = 8, tp;; 331 ld8 r2 = [r2] 332 mov r15 = SYS_sigreturn 333 mov b7 = r2 334 br.call.sptk.many b6 = b7 335 ;; 336 #else 337 mov r15 = SYS_sigreturn 338 break 0x100000 339 #endif 340 break 0 // bug out if sigreturn() returns 341 342 .endp ia64_install_cursor 343 344 #endif /* !UNW_REMOTE_ONLY */ 345 #ifdef __linux__ 346 /* We do not need executable stack. */ 347 .section .note.GNU-stack,"",@progbits 348 #endif 349