summaryrefslogtreecommitdiff
path: root/src/third_party/unwind/dist/tests/ia64-test-nat-asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/unwind/dist/tests/ia64-test-nat-asm.S')
-rw-r--r--src/third_party/unwind/dist/tests/ia64-test-nat-asm.S508
1 files changed, 508 insertions, 0 deletions
diff --git a/src/third_party/unwind/dist/tests/ia64-test-nat-asm.S b/src/third_party/unwind/dist/tests/ia64-test-nat-asm.S
new file mode 100644
index 00000000000..eea5ac27836
--- /dev/null
+++ b/src/third_party/unwind/dist/tests/ia64-test-nat-asm.S
@@ -0,0 +1,508 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2004-2005 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .text
+
+#define CALL_NEXT_PTR(gp_save_reg, arg0, arg1) \
+ ld8 r2 = [arg0], 8;; /* read the next function pointer */ \
+ ld8 r3 = [r2], 8;; /* read the function's entry-point */ \
+ ld8 r2 = [r2];; /* read the function's gp */ \
+ mov b6 = r3; \
+ mov gp_save_reg = gp; \
+ mov out0 = arg0; \
+ mov out1 = arg1; \
+ mov gp = r2; \
+ br.call.sptk.many rp = b6;; \
+ mov gp = gp_save_reg
+
+#define CALL_NEXT(gp_save_reg) CALL_NEXT_PTR(gp_save_reg, in0, in1)
+
+#define LOAD_VAL(reg) \
+ ld8 reg = [in1], 8;; \
+ tbit.nz p15, p0 = reg, 0;; \
+(p15) ld8.s reg = [r0]
+
+
+ .global flushrs
+ .proc flushrs
+flushrs:
+ flushrs;;
+ br.ret.sptk.many rp
+ .endp flushrs
+
+ /* Save r4-r7 into stacked registers, load them up with the
+ values passed via the pointer in in1 and then call the
+ function passed via the pointer in in0. */
+
+ .global save_static_to_stacked
+ .proc save_static_to_stacked
+save_static_to_stacked:
+ .prologue
+ .regstk 2, 7, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 7, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .spillreg r4, loc2
+ mov loc2 = r4
+ .spillreg r5, loc3
+ mov loc3 = r5
+ .spillreg r6, loc4
+ mov loc4 = r6
+ .spillreg r7, loc5
+ mov loc5 = r7
+ .body
+ LOAD_VAL(r4)
+ LOAD_VAL(r5)
+ LOAD_VAL(r6)
+ LOAD_VAL(r7)
+ CALL_NEXT(loc6)
+
+ mov r4 = loc2
+ mov r5 = loc3
+ mov r6 = loc4
+ mov r7 = loc5
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ br.ret.sptk.many rp
+ .endp save_static_to_stacked
+
+ /* Save f2 to the memory stack, save r4 to f2, then load
+ r4 with the value passed via in1 and call the function
+ passed via in0. */
+
+ .global save_static_to_fr
+ .proc save_static_to_fr
+save_static_to_fr:
+ .prologue
+ .regstk 2, 3, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 3, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .fframe 16
+ .spillpsp f2, 0
+ stf.spill [sp] = f2, -16
+ .spillreg r4, f2
+ setf.sig f2 = r4
+
+ .body
+
+ ld8 r4 = [in1], 8;;
+ tbit.nz p6, p0 = r4, 0;;
+(p6) ld8.s r4 = [r0]
+
+ CALL_NEXT(loc2)
+
+ getf.sig r4 = f2 // restore r4
+ .restore sp
+ add sp = 16, sp;;
+ ldf.fill f2 = [sp] // restore r2
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ br.ret.sptk.many rp
+ .endp save_static_to_fr
+
+ /* If r4 is not a NaT, save b3 to a stacked register and
+ then save r4 in b3. The non-NaTness of r4 is saved in
+ p1. */
+
+ .global save_static_to_br
+ .proc save_static_to_br
+save_static_to_br:
+ .prologue
+ .regstk 2, 6, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 6, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+
+ .save pr, loc2
+ mov loc2 = pr // save predicates
+
+ .spillreg b3, loc3
+ mov loc3 = b3
+
+ tnat.z p1, p2 = r4;;
+ .spillreg.p p1, r4, b3
+(p1) mov b3 = r4
+ .spillreg.p p2, r4, loc4
+(p2) mov loc4 = r4
+
+ .body
+
+ LOAD_VAL(r4)
+ CALL_NEXT(loc5)
+
+ .pred.rel.mutex p1, p2
+(p1) mov r4 = b3 // restore r4
+(p2) mov r4 = loc4
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ mov b3 = loc3 // restore b3
+ br.ret.sptk.many rp
+ .endp save_static_to_br
+
+ /* Spill r4 into memory and then save r5 in r4. */
+
+ .global save_static_to_mem
+ .proc save_static_to_mem
+save_static_to_mem:
+ .prologue
+ .regstk 2, 4, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 4, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ .fframe 16
+ .spillpsp r4, 0
+ st8.spill [sp] = r4, -16
+
+ .spillreg r5, r4
+ mov r4 = r5
+
+ .body
+
+ LOAD_VAL(r5)
+ CALL_NEXT(loc3)
+
+ mov r5 = r4 // restore r5
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r4 = [sp] // restore r4
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem
+
+ /* Spill r6 into memory and save primary ar.unat in a register. */
+
+ .global save_static_to_mem2
+ .proc save_static_to_mem2
+save_static_to_mem2:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ .save @priunat, loc3
+ mov loc3 = ar.unat
+ mov ar.unat = 0 // trash ar.unat
+
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ mov ar.unat = loc3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem2
+
+ /* Spill r6 into memory and save primary ar.unat in memory. */
+
+ .global save_static_to_mem3
+ .proc save_static_to_mem3
+save_static_to_mem3:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ mov r3 = ar.unat;;
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ mov ar.unat = 0 // trash ar.unat
+
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = r3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem3
+
+ /* Spill r6 into memory and save primary ar.unat in register,
+ then in memory. */
+
+ .global save_static_to_mem4
+ .proc save_static_to_mem4
+save_static_to_mem4:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ .save @priunat, r3
+ mov r3 = ar.unat;;
+ mov ar.unat = 0 // trash ar.unat
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ mov r3 = r0 // trash register pri UNaT location
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = r3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem4
+
+ /* Spill r6 into memory and save primary ar.unat in register,
+ then in memory. */
+
+ .global save_static_to_mem5
+ .proc save_static_to_mem5
+save_static_to_mem5:
+ .prologue
+ .regstk 2, 5, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 5, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save ar.unat, loc2
+ mov loc2 = ar.unat
+
+ add r2 = 8, sp
+ .fframe 16
+ .spillpsp r6, 0
+ st8.spill [sp] = r6, -16;;
+ mov r3 = ar.unat;;
+ mov ar.unat = 0 // trash ar.unat
+ .savepsp @priunat, -8
+ st8 [r2] = r3
+ .save @priunat, loc3
+ mov loc3 = r3
+ st8 [r2] = r0 // trash memory pri UNaT location
+ .body
+
+ LOAD_VAL(r6)
+ CALL_NEXT(loc4)
+
+ add r2 = 24, sp;;
+ ld8 r3 = [r2];;
+ mov ar.unat = loc3 // restore primary UNaT
+ .restore sp
+ add sp = 16, sp;;
+ ld8.fill r6 = [sp] // restore r6
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov ar.unat = loc2 // restore ar.unat
+ br.ret.sptk.many rp
+ .endp save_static_to_mem5
+
+ /* Save r4-r7 to various scratch registers, then trigger
+ a segfault. */
+
+ .global save_static_to_scratch
+ .proc save_static_to_scratch
+save_static_to_scratch:
+ .prologue
+
+ .spillreg r4, r16
+ mov r16 = r4 // save r4 in r16
+ tnat.nz p6, p7 = r5;;
+ .spillreg.p p6, r5, f31
+(p6) setf.sig f31 = r5 // save r5 in f31 if it's a NaT
+ .spillreg.p p7, r5, b6
+(p7) mov b6 = r5 // in b6 if it not
+ .spillreg r6, f32
+ setf.sig f32 = r6 // save r6 in f32 (fph partition)
+ .spillsp r7, 0
+ st8.spill [sp] = r7 // save r7 in the scratch stack space
+ .spillreg f4, f6
+ mov f6 = f4;;
+ .body
+
+ ld8 r2 = [in1]
+ ;;
+ mov ar.ec = r2
+
+ LOAD_VAL(r4)
+ LOAD_VAL(r5)
+ LOAD_VAL(r6)
+ LOAD_VAL(r7)
+ setf.sig f4 = r4
+
+ /* Now force a SIGSEGV. Make sure the ld8 is at the beginning of a
+ bundle, so the signal-handler can skip over it simply by
+ incrementing the IP. */
+ {
+ .mmi
+ ld8 r2 = [r0]
+ nop.m 0
+ nop.i 0 ;;
+ }
+
+ mov f4 = f6
+ mov r4 = r16
+ .pred.rel.mutex p6, p7
+(p6) getf.sig r5 = f31
+(p7) mov r5 = b6
+ getf.sig r6 = f32
+ ld8.fill r7 = [sp]
+
+ br.ret.sptk.many rp
+ .endp save_static_to_scratch
+
+ /* Rotate registers a bit in a vain attempt to sow some confusion.
+ Care must be taken not to write any rotating general register
+ after rotation, because we keep the preserved state
+ there... */
+
+ .global rotate_regs
+ .proc rotate_regs
+rotate_regs:
+ .prologue
+ .regstk 2, 14, 2, 16
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 14, 2, 16
+ .save rp, loc1
+ mov loc1 = rp
+ .save pr, loc2
+ mov loc2 = pr
+ .save ar.lc, loc3
+ mov loc3 = ar.lc
+ .spillreg r4, loc4
+ mov loc4 = r4
+
+ ld8 r2 = [in1], 8;;
+ mov pr = r2, -1
+
+ ld8 r2 = [in1], 8;;
+ mov r8 = in0
+ mov r9 = in1
+ and r2 = 127, r2;;
+ mov ar.ec = 0
+ mov ar.lc = r2;;
+
+ // use p6 to preserve p63 as it gets rotated into p16:
+(p16) cmp.eq.unc p6,p0 = r0,r0;;
+1:
+(p6) cmp.eq.unc p16,p0 = r0,r0
+(p63) cmp.eq.unc p6,p0 = r0,r0
+ br.ctop.dptk.few 1b;;
+
+(p6) cmp.eq.unc p63,p0 = r0,r0
+
+ CALL_NEXT_PTR(r4, r8, r9)
+
+ clrrrb
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ mov ar.lc = loc3
+ mov r4 = loc4
+ br.ret.sptk.many rp
+
+ .endp rotate_regs
+
+ .global save_pr
+ .proc save_pr
+save_pr:
+ .prologue
+ .regstk 2, 4, 2, 0
+ .save ar.pfs, loc0
+ alloc loc0 = ar.pfs, 2, 4, 2, 0
+ .save rp, loc1
+ mov loc1 = rp
+ .save pr, loc2
+ mov loc2 = pr
+
+ ld8 r2 = [in1], 8;;
+ mov pr = r2, -1
+
+ CALL_NEXT(loc3)
+
+ mov ar.pfs = loc0
+ mov rp = loc1
+ mov pr = loc2, -1
+ br.ret.sptk.many rp
+
+ .endp save_pr
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif