Home | History | Annotate | Download | only in ia64
      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