Home | History | Annotate | Download | only in tests
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2004-2005 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 	.text
     27 
     28 #define CALL_NEXT_PTR(gp_save_reg, arg0, arg1)				\
     29 	ld8 r2 = [arg0], 8;;	/* read the next function pointer */	\
     30 	ld8 r3 = [r2], 8;;	/* read the function's entry-point */	\
     31 	ld8 r2 = [r2];;		/* read the function's gp */		\
     32 	mov b6 = r3;							\
     33 	mov gp_save_reg = gp;						\
     34 	mov out0 = arg0;						\
     35 	mov out1 = arg1;						\
     36 	mov gp = r2;							\
     37 	br.call.sptk.many rp = b6;;					\
     38 	mov gp = gp_save_reg
     39 
     40 #define CALL_NEXT(gp_save_reg)	CALL_NEXT_PTR(gp_save_reg, in0, in1)
     41 
     42 #define LOAD_VAL(reg)				\
     43 	ld8 reg = [in1], 8;;			\
     44 	tbit.nz p15, p0 = reg, 0;;		\
     45 (p15)	ld8.s reg = [r0]
     46 
     47 
     48 	.global flushrs
     49 	.proc flushrs
     50 flushrs:
     51 	flushrs;;
     52 	br.ret.sptk.many rp
     53 	.endp flushrs
     54 
     55 	/* Save r4-r7 into stacked registers, load them up with the
     56 	   values passed via the pointer in in1 and then call the
     57 	   function passed via the pointer in in0.  */
     58 
     59 	.global save_static_to_stacked
     60 	.proc save_static_to_stacked
     61 save_static_to_stacked:
     62 	.prologue
     63 	.regstk 2, 7, 2, 0
     64 	.save ar.pfs, loc0
     65 	alloc loc0 = ar.pfs, 2, 7, 2, 0
     66 	.save rp, loc1
     67 	mov loc1 = rp
     68 	.spillreg r4, loc2
     69 	mov loc2 = r4
     70 	.spillreg r5, loc3
     71 	mov loc3 = r5
     72 	.spillreg r6, loc4
     73 	mov loc4 = r6
     74 	.spillreg r7, loc5
     75 	mov loc5 = r7
     76 	.body
     77 	LOAD_VAL(r4)
     78 	LOAD_VAL(r5)
     79 	LOAD_VAL(r6)
     80 	LOAD_VAL(r7)
     81 	CALL_NEXT(loc6)
     82 
     83 	mov r4 = loc2
     84 	mov r5 = loc3
     85 	mov r6 = loc4
     86 	mov r7 = loc5
     87 
     88 	mov ar.pfs = loc0
     89 	mov rp = loc1
     90 	br.ret.sptk.many rp
     91 	.endp save_static_to_stacked
     92 
     93 	/* Save f2 to the memory stack, save r4 to f2, then load
     94 	   r4 with the value passed via in1 and call the function
     95 	   passed via in0.  */
     96 
     97 	.global save_static_to_fr
     98 	.proc save_static_to_fr
     99 save_static_to_fr:
    100 	.prologue
    101 	.regstk 2, 3, 2, 0
    102 	.save ar.pfs, loc0
    103 	alloc loc0 = ar.pfs, 2, 3, 2, 0
    104 	.save rp, loc1
    105 	mov loc1 = rp
    106 	.fframe 16
    107 	.spillpsp f2, 0
    108 	stf.spill [sp] = f2, -16
    109 	.spillreg r4, f2
    110 	setf.sig f2 = r4
    111 
    112 	.body
    113 
    114 	ld8 r4 = [in1], 8;;
    115 	tbit.nz p6, p0 = r4, 0;;
    116 (p6)	ld8.s r4 = [r0]
    117 
    118 	CALL_NEXT(loc2)
    119 
    120 	getf.sig r4 = f2		// restore r4
    121 	.restore sp
    122 	add sp = 16, sp;;
    123 	ldf.fill f2 = [sp]		// restore r2
    124 
    125 	mov ar.pfs = loc0
    126 	mov rp = loc1
    127 	br.ret.sptk.many rp
    128 	.endp save_static_to_fr
    129 
    130 	/* If r4 is not a NaT, save b3 to a stacked register and
    131 	   then save r4 in b3.  The non-NaTness of r4 is saved in
    132 	   p1.  */
    133 
    134 	.global save_static_to_br
    135 	.proc save_static_to_br
    136 save_static_to_br:
    137 	.prologue
    138 	.regstk 2, 6, 2, 0
    139 	.save ar.pfs, loc0
    140 	alloc loc0 = ar.pfs, 2, 6, 2, 0
    141 	.save rp, loc1
    142 	mov loc1 = rp
    143 
    144 	.save pr, loc2
    145 	mov loc2 = pr			// save predicates
    146 
    147 	.spillreg b3, loc3
    148 	mov loc3 = b3
    149 
    150 	tnat.z p1, p2 = r4;;
    151 	.spillreg.p p1, r4, b3
    152 (p1)	mov b3 = r4
    153 	.spillreg.p p2, r4, loc4
    154 (p2)	mov loc4 = r4
    155 
    156 	.body
    157 
    158 	LOAD_VAL(r4)
    159 	CALL_NEXT(loc5)
    160 
    161 	.pred.rel.mutex p1, p2
    162 (p1)	mov r4 = b3			// restore r4
    163 (p2)	mov r4 = loc4
    164 
    165 	mov ar.pfs = loc0
    166 	mov rp = loc1
    167 	mov pr = loc2, -1
    168 	mov b3 = loc3			// restore b3
    169 	br.ret.sptk.many rp
    170 	.endp save_static_to_br
    171 
    172 	/* Spill r4 into memory and then save r5 in r4.  */
    173 
    174 	.global save_static_to_mem
    175 	.proc save_static_to_mem
    176 save_static_to_mem:
    177 	.prologue
    178 	.regstk 2, 4, 2, 0
    179 	.save ar.pfs, loc0
    180 	alloc loc0 = ar.pfs, 2, 4, 2, 0
    181 	.save rp, loc1
    182 	mov loc1 = rp
    183 	.save ar.unat, loc2
    184 	mov loc2 = ar.unat
    185 
    186 	.fframe 16
    187 	.spillpsp r4, 0
    188 	st8.spill [sp] = r4, -16
    189 
    190 	.spillreg r5, r4
    191 	mov r4 = r5
    192 
    193 	.body
    194 
    195 	LOAD_VAL(r5)
    196 	CALL_NEXT(loc3)
    197 
    198 	mov r5 = r4			// restore r5
    199 	.restore sp
    200 	add sp = 16, sp;;
    201 	ld8.fill r4 = [sp]		// restore r4
    202 
    203 	mov ar.pfs = loc0
    204 	mov rp = loc1
    205 	mov ar.unat = loc2		// restore ar.unat
    206 	br.ret.sptk.many rp
    207 	.endp save_static_to_mem
    208 
    209 	/* Spill r6 into memory and save primary ar.unat in a register.  */
    210 
    211 	.global save_static_to_mem2
    212 	.proc save_static_to_mem2
    213 save_static_to_mem2:
    214 	.prologue
    215 	.regstk 2, 5, 2, 0
    216 	.save ar.pfs, loc0
    217 	alloc loc0 = ar.pfs, 2, 5, 2, 0
    218 	.save rp, loc1
    219 	mov loc1 = rp
    220 	.save ar.unat, loc2
    221 	mov loc2 = ar.unat
    222 
    223 	.fframe 16
    224 	.spillpsp r6, 0
    225 	st8.spill [sp] = r6, -16;;
    226 	.save @priunat, loc3
    227 	mov loc3 = ar.unat
    228 	mov ar.unat = 0			// trash ar.unat
    229 
    230 	.body
    231 
    232 	LOAD_VAL(r6)
    233 	CALL_NEXT(loc4)
    234 
    235 	mov ar.unat = loc3		// restore primary UNaT
    236 	.restore sp
    237 	add sp = 16, sp;;
    238 	ld8.fill r6 = [sp]		// restore r6
    239 
    240 	mov ar.pfs = loc0
    241 	mov rp = loc1
    242 	mov ar.unat = loc2		// restore ar.unat
    243 	br.ret.sptk.many rp
    244 	.endp save_static_to_mem2
    245 
    246 	/* Spill r6 into memory and save primary ar.unat in memory.  */
    247 
    248 	.global save_static_to_mem3
    249 	.proc save_static_to_mem3
    250 save_static_to_mem3:
    251 	.prologue
    252 	.regstk 2, 5, 2, 0
    253 	.save ar.pfs, loc0
    254 	alloc loc0 = ar.pfs, 2, 5, 2, 0
    255 	.save rp, loc1
    256 	mov loc1 = rp
    257 	.save ar.unat, loc2
    258 	mov loc2 = ar.unat
    259 
    260 	add r2 = 8, sp
    261 	.fframe 16
    262 	.spillpsp r6, 0
    263 	st8.spill [sp] = r6, -16;;
    264 	mov r3 = ar.unat;;
    265 	.savepsp @priunat, -8
    266 	st8 [r2] = r3
    267 	mov ar.unat = 0			// trash ar.unat
    268 
    269 	.body
    270 
    271 	LOAD_VAL(r6)
    272 	CALL_NEXT(loc4)
    273 
    274 	add r2 = 24, sp;;
    275 	ld8 r3 = [r2];;
    276 	mov ar.unat = r3		// restore primary UNaT
    277 	.restore sp
    278 	add sp = 16, sp;;
    279 	ld8.fill r6 = [sp]		// restore r6
    280 
    281 	mov ar.pfs = loc0
    282 	mov rp = loc1
    283 	mov ar.unat = loc2		// restore ar.unat
    284 	br.ret.sptk.many rp
    285 	.endp save_static_to_mem3
    286 
    287 	/* Spill r6 into memory and save primary ar.unat in register,
    288 	   then in memory.  */
    289 
    290 	.global save_static_to_mem4
    291 	.proc save_static_to_mem4
    292 save_static_to_mem4:
    293 	.prologue
    294 	.regstk 2, 5, 2, 0
    295 	.save ar.pfs, loc0
    296 	alloc loc0 = ar.pfs, 2, 5, 2, 0
    297 	.save rp, loc1
    298 	mov loc1 = rp
    299 	.save ar.unat, loc2
    300 	mov loc2 = ar.unat
    301 
    302 	add r2 = 8, sp
    303 	.fframe 16
    304 	.spillpsp r6, 0
    305 	st8.spill [sp] = r6, -16;;
    306 	.save @priunat, r3
    307 	mov r3 = ar.unat;;
    308 	mov ar.unat = 0			// trash ar.unat
    309 	.savepsp @priunat, -8
    310 	st8 [r2] = r3
    311 	mov r3 = r0			// trash register pri UNaT location
    312 	.body
    313 
    314 	LOAD_VAL(r6)
    315 	CALL_NEXT(loc4)
    316 
    317 	add r2 = 24, sp;;
    318 	ld8 r3 = [r2];;
    319 	mov ar.unat = r3		// restore primary UNaT
    320 	.restore sp
    321 	add sp = 16, sp;;
    322 	ld8.fill r6 = [sp]		// restore r6
    323 
    324 	mov ar.pfs = loc0
    325 	mov rp = loc1
    326 	mov ar.unat = loc2		// restore ar.unat
    327 	br.ret.sptk.many rp
    328 	.endp save_static_to_mem4
    329 
    330 	/* Spill r6 into memory and save primary ar.unat in register,
    331 	   then in memory.  */
    332 
    333 	.global save_static_to_mem5
    334 	.proc save_static_to_mem5
    335 save_static_to_mem5:
    336 	.prologue
    337 	.regstk 2, 5, 2, 0
    338 	.save ar.pfs, loc0
    339 	alloc loc0 = ar.pfs, 2, 5, 2, 0
    340 	.save rp, loc1
    341 	mov loc1 = rp
    342 	.save ar.unat, loc2
    343 	mov loc2 = ar.unat
    344 
    345 	add r2 = 8, sp
    346 	.fframe 16
    347 	.spillpsp r6, 0
    348 	st8.spill [sp] = r6, -16;;
    349 	mov r3 = ar.unat;;
    350 	mov ar.unat = 0			// trash ar.unat
    351 	.savepsp @priunat, -8
    352 	st8 [r2] = r3
    353 	.save @priunat, loc3
    354 	mov loc3 = r3
    355 	st8 [r2] = r0			// trash memory pri UNaT location
    356 	.body
    357 
    358 	LOAD_VAL(r6)
    359 	CALL_NEXT(loc4)
    360 
    361 	add r2 = 24, sp;;
    362 	ld8 r3 = [r2];;
    363 	mov ar.unat = loc3		// restore primary UNaT
    364 	.restore sp
    365 	add sp = 16, sp;;
    366 	ld8.fill r6 = [sp]		// restore r6
    367 
    368 	mov ar.pfs = loc0
    369 	mov rp = loc1
    370 	mov ar.unat = loc2		// restore ar.unat
    371 	br.ret.sptk.many rp
    372 	.endp save_static_to_mem5
    373 
    374 	/* Save r4-r7 to various scratch registers, then trigger
    375 	   a segfault.  */
    376 
    377 	.global save_static_to_scratch
    378 	.proc save_static_to_scratch
    379 save_static_to_scratch:
    380 	.prologue
    381 
    382 	.spillreg r4, r16
    383 	mov r16 = r4			// save r4 in r16
    384 	tnat.nz p6, p7 = r5;;
    385 	.spillreg.p p6, r5, f31
    386 (p6)	setf.sig f31 = r5		// save r5 in f31 if it's a NaT
    387 	.spillreg.p p7, r5, b6
    388 (p7)	mov b6 = r5			//         in  b6 if it not
    389 	.spillreg r6, f32
    390 	setf.sig f32 = r6		// save r6 in f32 (fph partition)
    391 	.spillsp r7, 0
    392 	st8.spill [sp] = r7		// save r7 in the scratch stack space
    393 	.spillreg f4, f6
    394 	mov f6 = f4;;
    395 	.body
    396 
    397 	ld8 r2 = [in1]
    398 	;;
    399 	mov ar.ec = r2
    400 
    401 	LOAD_VAL(r4)
    402 	LOAD_VAL(r5)
    403 	LOAD_VAL(r6)
    404 	LOAD_VAL(r7)
    405 	setf.sig f4 = r4
    406 
    407 	/* Now force a SIGSEGV.  Make sure the ld8 is at the beginning of a
    408 	   bundle, so the signal-handler can skip over it simply by
    409 	   incrementing the IP.  */
    410 	{
    411 		.mmi
    412 		ld8 r2 = [r0]
    413 		nop.m 0
    414 		nop.i 0 ;;
    415 	}
    416 
    417 	mov f4 = f6
    418 	mov r4 = r16
    419 	.pred.rel.mutex p6, p7
    420 (p6)	getf.sig r5 = f31
    421 (p7)	mov r5 = b6
    422 	getf.sig r6 = f32
    423 	ld8.fill r7 = [sp]
    424 
    425 	br.ret.sptk.many rp
    426 	.endp save_static_to_scratch
    427 
    428 	/* Rotate registers a bit in a vain attempt to sow some confusion.
    429 	   Care must be taken not to write any rotating general register
    430 	   after rotation, because we keep the preserved state
    431 	   there... */
    432 
    433 	.global rotate_regs
    434 	.proc rotate_regs
    435 rotate_regs:
    436 	.prologue
    437 	.regstk 2, 14, 2, 16
    438 	.save ar.pfs, loc0
    439 	alloc loc0 = ar.pfs, 2, 14, 2, 16
    440 	.save rp, loc1
    441 	mov loc1 = rp
    442 	.save pr, loc2
    443 	mov loc2 = pr
    444 	.save ar.lc, loc3
    445 	mov loc3 = ar.lc
    446 	.spillreg r4, loc4
    447 	mov loc4 = r4
    448 
    449 	ld8 r2 = [in1], 8;;
    450 	mov pr = r2, -1
    451 
    452 	ld8 r2 = [in1], 8;;
    453 	mov r8 = in0
    454 	mov r9 = in1
    455 	and r2 = 127, r2;;
    456 	mov ar.ec = 0
    457 	mov ar.lc = r2;;
    458 
    459 	// use p6 to preserve p63 as it gets rotated into p16:
    460 (p16)	cmp.eq.unc p6,p0 = r0,r0;;
    461 1:
    462 (p6)	cmp.eq.unc p16,p0 = r0,r0
    463 (p63)	cmp.eq.unc p6,p0 = r0,r0
    464 	br.ctop.dptk.few 1b;;
    465 
    466 (p6)	cmp.eq.unc p63,p0 = r0,r0
    467 
    468 	CALL_NEXT_PTR(r4, r8, r9)
    469 
    470 	clrrrb
    471 
    472 	mov ar.pfs = loc0
    473 	mov rp = loc1
    474 	mov pr = loc2, -1
    475 	mov ar.lc = loc3
    476 	mov r4 = loc4
    477 	br.ret.sptk.many rp
    478 
    479 	.endp rotate_regs
    480 
    481 	.global save_pr
    482 	.proc save_pr
    483 save_pr:
    484 	.prologue
    485 	.regstk 2, 4, 2, 0
    486 	.save ar.pfs, loc0
    487 	alloc loc0 = ar.pfs, 2, 4, 2, 0
    488 	.save rp, loc1
    489 	mov loc1 = rp
    490 	.save pr, loc2
    491 	mov loc2 = pr
    492 
    493 	ld8 r2 = [in1], 8;;
    494 	mov pr = r2, -1
    495 
    496 	CALL_NEXT(loc3)
    497 
    498 	mov ar.pfs = loc0
    499 	mov rp = loc1
    500 	mov pr = loc2, -1
    501 	br.ret.sptk.many rp
    502 
    503 	.endp save_pr
    504 
    505 #ifdef __linux__
    506         /* We do not need executable stack.  */
    507         .section        .note.GNU-stack,"",@progbits
    508 #endif
    509