Initial import
[external/libunwind.git] / tests / ia64-test-nat-asm.S
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2004-2005 Hewlett-Packard Co
3         Contributed by David Mosberger-Tang <davidm@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