exception.S revision 268200
1/*-
2 * Copyright (c) 2003,2004 Marcel Moolenaar
3 * Copyright (c) 2000 Doug Rabson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <machine/asm.h>
29__FBSDID("$FreeBSD: stable/10/sys/ia64/ia64/exception.S 268200 2014-07-02 23:47:43Z marcel $");
30
31#include "opt_xtrace.h"
32
33#include <machine/pte.h>
34#include <assym.s>
35
36/*
37 * Nested TLB restart tokens. These are used by the
38 * nested TLB handler for jumping back to the code
39 * where the nested TLB was caused.
40 */
41#define	NTLBRT_SAVE	0x12c12c
42#define	NTLBRT_RESTORE  0x12c12d
43
44/*
45 * ar.k7 = kernel memory stack
46 * ar.k6 = kernel register stack
47 * ar.k5 = EPC gateway page
48 * ar.k4 = PCPU data
49 */
50
51	.section .ivt.data, "aw"
52
53	.align	8
54	.global ia64_kptdir
55	.size	ia64_kptdir, 8
56ia64_kptdir:	data8	0
57
58#ifdef XTRACE
59
60	.align	8
61	.global	ia64_xtrace_mask
62	.size	ia64_xtrace_mask, 8
63ia64_xtrace_mask:	data8	0
64
65	.align	4
66	.global	ia64_xtrace_enabled
67	.size	ia64_xtrace_enabled, 4
68ia64_xtrace_enabled:	data4	0
69
70#define	XTRACE_HOOK(offset)			\
71{	.mii ;					\
72	nop		0 ;			\
73	mov		r31 = b7 ;		\
74	mov		r28 = pr ;		\
75} ;						\
76{	.mib ;					\
77	nop		0 ;			\
78	mov		r25 = ip ;		\
79	br.sptk		ia64_xtrace_write ;;	\
80} ;						\
81{	.mii ;					\
82	nop		0 ;			\
83	mov		b7 = r31 ;		\
84	mov		pr = r28, 0x1ffff ;;	\
85}
86
87	.section .ivt.text, "ax"
88
89// We can only use r25, r26 & r27
90ENTRY_NOPROFILE(ia64_xtrace_write, 0)
91{	.mlx
92	add	r25 = 16, r25
93	movl	r26 = ia64_xtrace_enabled
94	;;
95}
96{	.mmi
97	mov	r27 = ar.k3
98	ld4	r26 = [r26]
99	mov	b7 = r25
100	;;
101}
102{	.mib
103	add	r25 = -32, r25
104	cmp.eq	p15,p0 = r0, r26
105(p15)	br.dptk.few	b7
106	;;
107}
108{	.mib
109	nop	0
110	cmp.eq	p15,p0 = r0, r27
111(p15)	br.dptk.few	b7
112	;;
113}
114{	.mmi
115	st8	[r27] = r25, 8		// 0x00 IVT
116	mov	r26 = ar.itc
117	nop	0
118	;;
119}
120{	.mmi
121	st8	[r27] = r26, 8		// 0x08 ITC
122	mov	r25 = cr.iip
123	nop	0
124	;;
125}
126{	.mmi
127	st8	[r27] = r25, 8		// 0x10 IIP
128	mov	r26 = cr.ifa
129	nop	0
130	;;
131}
132{	.mmi
133	st8	[r27] = r26, 8		// 0x18 IFA
134	mov	r25 = cr.isr
135	nop	0
136	;;
137}
138{	.mmi
139	st8	[r27] = r25, 8		// 0x20 ISR
140	mov	r26 = cr.ipsr
141	nop	0
142	;;
143}
144{	.mmi
145	st8	[r27] = r26, 8		// 0x28 IPSR
146	mov	r25 = cr.itir
147	nop	0
148	;;
149}
150{	.mmi
151	st8	[r27] = r25, 8		// 0x30 ITIR
152	mov	r26 = cr.iipa
153	nop	0
154	;;
155}
156{	.mmi
157	st8	[r27] = r26, 8		// 0x38 IIPA
158	mov	r25 = cr.ifs
159	nop	0
160	;;
161}
162{	.mmi
163	st8	[r27] = r25, 8		// 0x40 IFS
164	mov	r26 = cr.iim
165	nop	0
166	;;
167}
168{	.mmi
169	st8	[r27] = r26, 8		// 0x48 IIM
170	mov	r25 = cr.iha
171	nop	0
172	;;
173}
174{	.mmi
175	st8	[r27] = r25, 8		// 0x50 IHA
176	mov	r26 = ar.unat
177	nop	0
178	;;
179}
180{	.mmi
181	st8	[r27] = r26, 8		// 0x58 UNAT
182	mov	r25 = ar.rsc
183	nop	0
184	;;
185}
186{	.mmi
187	st8	[r27] = r25, 8		// 0x60 RSC
188	mov	r26 = ar.bsp
189	nop	0
190	;;
191}
192{	.mmi
193	st8	[r27] = r26, 8		// 0x68 BSP
194	mov	r25 = r13
195	nop	0
196	;;
197}
198{	.mmi
199	st8	[r27] = r25, 8		// 0x70 PCPU/TLS
200	mov	r26 = r12
201	nop	0
202	;;
203}
204{	.mlx
205	st8	[r27] = r26, 8		// 0x78 SP
206	movl	r25 = ia64_xtrace_mask
207	;;
208}
209{	.mmi
210	ld8	r26 = [r25]
211	;;
212	and	r25 = r27, r26
213	nop	0
214	;;
215}
216{	.mib
217	mov	ar.k3 = r25
218	nop	0
219	br.sptk	b7
220	;;
221}
222END(ia64_xtrace_write)
223
224#else /* XTRACE */
225
226#define	XTRACE_HOOK(offset)
227
228	.section .ivt.text, "ax"
229
230#endif /* XTRACE */
231
232/*
233 * exception_save: save interrupted state
234 *
235 * Arguments:
236 *	r16	address of bundle that contains the branch. The
237 *		return address will be the next bundle.
238 *	r17	the value to save as ifa in the trapframe. This
239 *		normally is cr.ifa, but some interruptions set
240 *		set cr.iim and not cr.ifa.
241 *
242 * Returns:
243 *	p15	interrupted from user stack
244 *	p14	interrupted from kernel stack
245 *	p13	interrupted from user backing store
246 *	p12	interrupted from kernel backing store
247 *	p11	interrupts were enabled
248 *	p10	interrupts were disabled
249 */
250ENTRY_NOPROFILE(exception_save, 0)
251{	.mii
252	mov		r20=ar.unat
253	extr.u		r31=sp,61,3
254	mov		r18=pr
255	;;
256}
257{	.mmi
258	cmp.le		p14,p15=IA64_VM_MINKERN_REGION,r31
259	;;
260(p15)	mov		r23=ar.k7		// kernel memory stack
261(p14)	mov		r23=sp
262	;;
263}
264{	.mii
265	mov		r21=ar.rsc
266	add		r30=-SIZEOF_TRAPFRAME,r23
267	;;
268	dep		r30=0,r30,0,10
269	;;
270}
271{	.mmi
272	mov		ar.rsc=0
273	mov		r22=cr.iip
274	addl		r29=NTLBRT_SAVE,r0	// 22-bit restart token.
275	;;
276}
277
278	/*
279	 * We have a 1KB aligned trapframe, pointed to by r30. We can't
280	 * reliably write to the trapframe using virtual addressing, due
281	 * to the fact that TC entries we depend on can be removed by:
282	 * 1.  ptc.g instructions issued by other threads/cores/CPUs, or
283	 * 2.  TC modifications in another thread on the same core.
284	 * When our TC entry gets removed, we get nested TLB faults and
285	 * since no state is saved, we can only deal with those when
286	 * explicitly coded and expected.
287	 * As such, we switch to physical addressing and account for the
288	 * fact that the tpa instruction can cause a nested TLB fault.
289	 * Since the data nested TLB fault does not preserve any state,
290	 * we have to be careful what we clobber. Consequently, we have
291	 * to be careful what we use here. Below a list of registers that
292	 * are considered alive:
293	 *	r16,r17=arguments
294	 *	r18=pr, r19=length, r20=unat, r21=rsc, r22=iip, r23=TOS
295	 *	r29=restart token
296	 *	r30=trapframe pointers
297	 *	p14,p15=memory stack switch
298	 */
299exception_save_restart:
300	tpa		r24=r30			// Nested TLB fault possible
301	sub		r19=r23,r30
302	nop		0
303	;;
304
305	rsm		psr.dt
306	add		r29=16,r19		// Clobber restart token
307	mov		r30=r24
308	;;
309	srlz.d
310	add		r31=8,r24
311	;;
312
313	// r18=pr, r19=length, r20=unat, r21=rsc, r22=iip, r23=TOS
314	// r29=delta
315{	.mmi
316	st8		[r30]=r19,16		// length
317	st8		[r31]=r0,16		// flags
318	;;
319}
320{	.mmi
321	st8.spill	[r30]=sp,16		// sp
322	st8		[r31]=r20,16		// unat
323	sub		sp=r23,r29
324	;;
325}
326{	.mmi
327	mov		r19=ar.rnat
328	mov		r20=ar.bspstore
329	mov		r23=rp
330	;;
331}
332	// r18=pr, r19=rnat, r20=bspstore, r21=rsc, r22=iip, r23=rp
333	// r24=pfs
334{	.mmi
335	st8		[r30]=r23,16		// rp
336	st8		[r31]=r18,16		// pr
337	mov		r24=ar.pfs
338	;;
339}
340{	.mmb
341	st8		[r30]=r24,16		// pfs
342	st8		[r31]=r20,16		// bspstore
343	cover
344	;;
345}
346{	.mmi
347	mov		r18=ar.fpsr
348	mov		r23=cr.ipsr
349	extr.u		r24=r20,61,3
350	;;
351}
352	// r18=fpsr, r19=rnat, r20=bspstore, r21=rsc, r22=iip, r23=ipsr
353{	.mmi
354	st8		[r30]=r19,16		// rnat
355	st8		[r31]=r0,16		// __spare
356	cmp.le		p12,p13=IA64_VM_MINKERN_REGION,r24
357	;;
358}
359{	.mmi
360	st8.spill	[r30]=r13,16		// tp
361	st8		[r31]=r21,16		// rsc
362	tbit.nz		p11,p10=r23,14		// p11=interrupts enabled
363	;;
364}
365{	.mmi
366(p13)	mov		r21=ar.k6		// kernel register stack
367	;;
368	st8		[r30]=r18,16		// fpsr
369(p13)	dep		r20=r20,r21,0,9		// align dirty registers
370	;;
371}
372	// r19=rnat, r20=bspstore, r22=iip, r23=ipsr
373{	.mmi
374	st8		[r31]=r23,16		// psr
375(p13)	mov		ar.bspstore=r20
376	nop		0
377	;;
378}
379{	.mmi
380(p13)	mov		ar.rnat=r19
381	mov		r18=ar.bsp
382	nop		0
383	;;
384}
385{	.mmi
386	mov		r19=cr.ifs
387	st8.spill	[r30]=gp,16		// gp
388	sub		r18=r18,r20
389	;;
390}
391	// r18=ndirty, r19=ifs, r22=iip
392{	.mmi
393	st8		[r31]=r18,16		// ndirty
394	st8		[r30]=r19,16		// cfm
395	nop		0
396	;;
397}
398{	.mmi
399	mov		r18=cr.isr
400	st8		[r31]=r22,16		// iip
401	add		r29=16,r30
402	;;
403}
404{	.mmi
405	st8		[r30]=r17,24		// ifa
406	st8		[r31]=r18,24		// isr
407	nop		0
408	;;
409}
410{	.mmi
411	.mem.offset	0,0
412	st8.spill	[r30]=r2,16		// r2
413	.mem.offset	8,0
414	st8.spill	[r31]=r3,16		// r3
415	add		r2=9*8,r29
416	;;
417}
418{	.mmi
419	.mem.offset	0,0
420	st8.spill	[r30]=r8,16		// r8
421	.mem.offset	8,0
422	st8.spill	[r31]=r9,16		// r9
423	add		r3=8,r2
424	;;
425}
426{	.mmi
427	.mem.offset	0,0
428	st8.spill	[r30]=r10,16		// r10
429	.mem.offset	8,0
430	st8.spill	[r31]=r11,16		// r11
431	add		r8=16,r16
432	;;
433}
434{	.mmi
435	.mem.offset	0,0
436	st8.spill	[r30]=r14		// r14
437	.mem.offset	8,0
438	st8.spill	[r31]=r15		// r15
439	mov		r9=r29
440}
441{	.mmb
442	mov		r10=ar.csd
443	mov		r11=ar.ssd
444	bsw.1
445	;;
446}
447{	.mmi
448	.mem.offset	0,0
449	st8.spill	[r2]=r16,16		// r16
450	.mem.offset	8,0
451	st8.spill	[r3]=r17,16		// r17
452	mov		r14=b6
453	;;
454}
455{	.mmi
456	.mem.offset	0,0
457	st8.spill	[r2]=r18,16		// r18
458	.mem.offset	8,0
459	st8.spill	[r3]=r19,16		// r19
460	mov		r15=b7
461	;;
462}
463{	.mmi
464	.mem.offset	0,0
465	st8.spill	[r2]=r20,16		// r20
466	.mem.offset	8,0
467	st8.spill	[r3]=r21,16		// r21
468	mov		b7=r8
469	;;
470}
471{	.mmi
472	.mem.offset	0,0
473	st8.spill	[r2]=r22,16		// r22
474	.mem.offset	8,0
475	st8.spill	[r3]=r23,16		// r23
476	;;
477}
478
479	.mem.offset	0,0
480	st8.spill	[r2]=r24,16		// r24
481	.mem.offset	8,0
482	st8.spill	[r3]=r25,16		// r25
483	;;
484	.mem.offset	0,0
485	st8.spill	[r2]=r26,16		// r26
486	.mem.offset	8,0
487	st8.spill	[r3]=r27,16		// r27
488	;;
489	.mem.offset	0,0
490	st8.spill	[r2]=r28,16		// r28
491	.mem.offset	8,0
492	st8.spill	[r3]=r29,16		// r29
493	;;
494	.mem.offset	0,0
495	st8.spill	[r2]=r30,16		// r30
496	.mem.offset	8,0
497	st8.spill	[r3]=r31,16		// r31
498	;;
499
500{	.mmi
501	st8		[r2]=r14,16		// b6
502	mov		r17=ar.unat
503	nop		0
504	;;
505}
506{	.mmi
507	st8		[r3]=r15,16		// b7
508	mov		r16=ar.ccv
509	nop		0
510	;;
511}
512{	.mmi
513	st8		[r2]=r16,16		// ccv
514	st8		[r3]=r10,16		// csd
515	nop		0
516	;;
517}
518{	.mmi
519	st8		[r2]=r11,24		// ssd
520	st8		[r9]=r17
521	nop		0
522	;;
523}
524
525	stf.spill	[r3]=f6,32		// f6
526	stf.spill	[r2]=f7,32		// f7
527	;;
528	stf.spill	[r3]=f8,32		// f8
529	stf.spill	[r2]=f9,32		// f9
530	;;
531	stf.spill	[r3]=f10,32		// f10
532	stf.spill	[r2]=f11,32		// f11
533	;;
534	stf.spill	[r3]=f12,32		// f12
535	stf.spill	[r2]=f13,32		// f13
536	;;
537	stf.spill	[r3]=f14		// f14
538	stf.spill	[r2]=f15		// f15
539	;;
540{	.mmi
541	mov		ar.rsc=3
542	mov		r13=ar.k4
543	nop		0
544	;;
545}
546{	.mlx
547	ssm		psr.dt|psr.ic|psr.dfh
548	movl		gp=__gp
549	;;
550}
551{	.mib
552	srlz.d
553	nop		0
554	br.sptk		b7
555	;;
556}
557END(exception_save)
558
559/*
560 * exception_restore:	restore interrupted state
561 *
562 * Arguments:
563 *	sp+16	trapframe pointer
564 */
565ENTRY_NOPROFILE(exception_restore, 0)
566{	.mmi
567	rsm		psr.i
568	add		sp=16,sp
569	nop		0
570	;;
571}
572
573	// The next instruction can fault. Let it be...
574	tpa		r9=sp
575	;;
576	rsm		psr.dt|psr.ic
577	add		r8=SIZEOF_SPECIAL+16,r9
578	;;
579	srlz.d
580	add		r2=SIZEOF_TRAPFRAME-16,r9
581	add		r3=SIZEOF_TRAPFRAME-32,r9
582	;;
583
584{	.mmi
585	ldf.fill	f15=[r2],-32		// f15
586	ldf.fill	f14=[r3],-32		// f14
587	nop		0
588	;;
589}
590{	.mmi
591	ldf.fill	f13=[r2],-32		// f13
592	ldf.fill	f12=[r3],-32		// f12
593	nop		0
594	;;
595}
596{	.mmi
597	ldf.fill	f11=[r2],-32		// f11
598	ldf.fill	f10=[r3],-32		// f10
599	nop		0
600	;;
601}
602{	.mmi
603	ldf.fill	f9=[r2],-32		// f9
604	ldf.fill	f8=[r3],-32		// f8
605	nop		0
606	;;
607}
608{	.mmi
609	ldf.fill	f7=[r2],-24		// f7
610	ldf.fill	f6=[r3],-16		// f6
611	nop		0
612	;;
613}
614{	.mmi
615	ld8		r8=[r8]			// unat (after)
616	;;
617	mov		ar.unat=r8
618	nop		0
619	;;
620}
621
622	ld8		r10=[r2],-16		// ssd
623	ld8		r11=[r3],-16		// csd
624	;;
625	mov		ar.ssd=r10
626	mov		ar.csd=r11
627
628	ld8		r14=[r2],-16		// ccv
629	ld8		r15=[r3],-16		// b7
630	;;
631
632{	.mmi
633	mov		ar.ccv=r14
634	ld8		r8=[r2],-16		// b6
635	mov		b7=r15
636	;;
637}
638{	.mmi
639	ld8.fill	r31=[r3],-16		// r31
640	ld8.fill	r30=[r2],-16		// r30
641	mov		b6=r8
642	;;
643}
644
645	ld8.fill	r29=[r3],-16		// r29
646	ld8.fill	r28=[r2],-16		// r28
647	;;
648	ld8.fill	r27=[r3],-16		// r27
649	ld8.fill	r26=[r2],-16		// r26
650	;;
651	ld8.fill	r25=[r3],-16		// r25
652	ld8.fill	r24=[r2],-16		// r24
653	;;
654	ld8.fill	r23=[r3],-16		// r23
655	ld8.fill	r22=[r2],-16		// r22
656	;;
657	ld8.fill	r21=[r3],-16		// r21
658	ld8.fill	r20=[r2],-16		// r20
659	;;
660	ld8.fill	r19=[r3],-16		// r19
661	ld8.fill	r18=[r2],-16		// r18
662	;;
663
664{	.mmb
665	ld8.fill	r17=[r3],-16		// r17
666	ld8.fill	r16=[r2],-16		// r16
667	bsw.0
668	;;
669}
670{	.mii
671	ld8		r16=[r9]		// tf_length
672	add		r31=16,r9
673	add		r30=24,r9
674}
675{	.mmi
676	ld8.fill	r15=[r3],-16		// r15
677	ld8.fill	r14=[r2],-16		// r14
678	nop		0
679	;;
680}
681{	.mmi
682	ld8.fill	r11=[r3],-16		// r11
683	ld8.fill	r10=[r2],-16		// r10
684	add		r16=r16,sp		// ar.k7
685	;;
686}
687{	.mmi
688	ld8.fill	r9=[r3],-16		// r9
689	ld8.fill	r8=[r2],-16		// r8
690	nop		0
691	;;
692}
693{	.mmi
694	ld8.fill	r3=[r3]			// r3
695	ld8.fill	r2=[r2]			// r2
696	nop		0
697	;;
698}
699
700	ld8.fill	sp=[r31],16		// sp
701	ld8		r17=[r30],16		// unat
702	;;
703	ld8		r29=[r31],16		// rp
704	ld8		r18=[r30],16		// pr
705	;;
706	ld8		r28=[r31],16		// pfs
707	ld8		r20=[r30],24		// bspstore
708	mov		rp=r29
709	;;
710	ld8		r21=[r31],24		// rnat
711	mov		ar.pfs=r28
712	;;
713	ld8.fill	r26=[r30],16		// tp
714	ld8		r22=[r31],16		// rsc
715	;;
716
717{	.mmi
718	ld8		r23=[r30],16		// fpsr
719	ld8		r24=[r31],16		// psr
720	extr.u		r28=r20,61,3
721	;;
722}
723{	.mmi
724	ld8.fill	r1=[r30],16		// gp
725	ld8		r27=[r31],16		// ndirty
726	cmp.le		p14,p15=IA64_VM_MINKERN_REGION,r28
727	;;
728}
729{	.mmi
730	ld8		r25=[r30]		// cfm
731	ld8		r19=[r31]		// ip
732	nop		0
733	;;
734}
735{	.mii
736	// Switch register stack
737	alloc		r30=ar.pfs,0,0,0,0	// discard current frame
738	shl		r31=r27,16		// value for ar.rsc
739(p15)	mov		r13=r26
740	;;
741}
742	// The loadrs can fault if the backing store is not currently
743	// mapped. We assured forward progress by getting everything we
744	// need from the trapframe so that we don't care if the CPU
745	// purges that translation when it needs to insert a new one for
746	// the backing store.
747{	.mmi
748	mov		ar.rsc=r31		// setup for loadrs
749	mov		ar.k7=r16
750	addl		r29=NTLBRT_RESTORE,r0	// 22-bit restart token
751	;;
752}
753
754	ssm		psr.dt
755	;;
756	srlz.d
757	mov		r16 = r25
758
759exception_restore_restart:
760{	.mmi
761	mov		r30=ar.bspstore
762	;;
763	loadrs					// load user regs
764	mov		r29=0			// Clobber restart token
765	;;
766}
767{	.mmi
768	mov		r31=ar.bspstore
769	;;
770	mov		ar.bspstore=r20
771	dep		r31=0,r31,0,13		// 8KB aligned
772	;;
773}
774{	.mmi
775	mov		cr.ifs=r16
776	mov		ar.k6=r31
777	mov		pr=r18,0x1ffff
778	;;
779}
780{	.mmi
781	mov		cr.iip=r19
782	mov		ar.unat=r17
783	nop		0
784	;;
785}
786{	.mmi
787	mov		cr.ipsr=r24
788	mov		ar.rnat=r21
789	nop		0
790	;;
791}
792{	.mmb
793	mov		ar.rsc=r22
794	mov		ar.fpsr=r23
795	rfi
796	;;
797}
798END(exception_restore)
799
800/*
801 * Call exception_save_regs to preserve the interrupted state in a
802 * trapframe. Note that we don't use a call instruction because we
803 * must be careful not to lose track of the RSE state. We then call
804 * trap() with the value of _n_ as an argument to handle the
805 * exception. We arrange for trap() to return to exception_restore
806 * which will restore the interrupted state before executing an rfi to
807 * resume it.
808 */
809#define CALL(_func_, _n_, _ifa_)		\
810{	.mib ;					\
811	mov		r17=_ifa_ ;		\
812	mov		r16=ip ;		\
813	br.sptk		exception_save ;;	\
814} ;						\
815{	.mmi ;					\
816	alloc		r15=ar.pfs,0,0,2,0 ;;	\
817(p11)	ssm		psr.i ;			\
818	mov		out0=_n_ ;;		\
819} ;						\
820{	.mib ;					\
821(p11)	srlz.d ;				\
822	add		out1=16,sp ;		\
823	br.call.sptk	rp=_func_ ;;		\
824} ;						\
825{	.mib ;					\
826	nop		0 ;			\
827	nop		0 ;			\
828	br.sptk		exception_restore ;;	\
829}
830
831#define	IVT_ENTRY(name, offset)			\
832	.org	ia64_vector_table + offset;	\
833	.global	ivt_##name;			\
834	.proc	ivt_##name;			\
835	.prologue;				\
836	.unwabi	@svr4, 'I';			\
837	.save	rp, r0;				\
838	.body;					\
839ivt_##name:					\
840	XTRACE_HOOK(offset)
841
842#define	IVT_END(name)				\
843	.endp	ivt_##name
844
845#ifdef COMPAT_FREEBSD32
846#define	IA32_TRAP	ia32_trap
847#else
848#define	IA32_TRAP	trap
849#endif
850
851/*
852 * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64
853 * bundles per vector and 48 slots with 16 bundles per vector.
854 */
855
856	.section .ivt, "ax"
857
858	.align	32768
859	.global ia64_vector_table
860	.size	ia64_vector_table, 32768
861ia64_vector_table:
862
863IVT_ENTRY(VHPT_Translation, 0x0000)
864	CALL(trap, 0, cr.ifa)
865IVT_END(VHPT_Translation)
866
867IVT_ENTRY(Instruction_TLB, 0x0400)
868	mov	r16=cr.ifa
869	mov	r17=pr
870	;;
871	thash	r18=r16
872	ttag	r19=r16
873	;;
874	add	r21=16,r18		// tag
875	add	r20=24,r18		// collision chain
876	;;
877	ld8	r21=[r21]		// check VHPT tag
878	ld8	r20=[r20]		// bucket head
879	;;
880	cmp.ne	p15,p0=r21,r19
881(p15)	br.dpnt.few 1f
882	;;
883	ld8	r21=[r18]		// read pte
884	;;
885	itc.i	r21			// insert pte
886	mov	pr=r17,0x1ffff
887	;;
888	rfi				// done
889	;;
8901:	rsm	psr.dt			// turn off data translations
891	dep	r20=0,r20,61,3		// convert vhpt ptr to physical
892	;;
893	srlz.d				// serialize
894	ld8	r20=[r20]		// first entry
895	;;
8962:	cmp.eq	p15,p0=r0,r20		// done?
897(p15)	br.cond.spnt.few 9f		// bail if done
898	;;
899	add	r21=16,r20		// tag location
900	;;
901	ld8	r21=[r21]		// read tag
902	;;
903	cmp.ne	p15,p0=r21,r19		// compare tags
904(p15)	br.cond.sptk.few 3f		// if not, read next in chain
905	;;
906	ld8	r21=[r20]		// read pte
907	mov	r22=PTE_ACCESSED
908	;;
909	or	r21=r21,r22
910	;;
911	st8	[r20]=r21,8
912	;;
913	ld8	r22=[r20]		// read rest of pte
914	;;
915	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
916	;;
917	add	r20=16,r18		// address of tag
918	;;
919	ld8.acq	r23=[r20]		// read old tag
920	;;
921	dep	r23=-1,r23,63,1		// set ti bit
922	;;
923	st8.rel	[r20]=r23		// store old tag + ti
924	;;
925	mf				// make sure everyone sees
926	;;
927	st8	[r18]=r21,8		// store pte
928	;;
929	st8	[r18]=r22,8
930	;;
931	st8.rel	[r18]=r19		// store new tag
932	;;
933	itc.i	r21			// and place in TLB
934	ssm	psr.dt
935	;;
936	srlz.d
937	mov	pr=r17,0x1ffff		// restore predicates
938	rfi
939	;;
9403:	add	r20=24,r20		// next in chain
941	;;
942	ld8	r20=[r20]		// read chain
943	br.sptk	2b			// loop
944	;;
9459:	ssm	psr.dt
946	mov	pr=r17,0x1ffff		// restore predicates
947	;;
948	srlz.d
949	;;
950	CALL(trap, 20, cr.ifa)		// Page Not Present trap
951IVT_END(Instruction_TLB)
952
953IVT_ENTRY(Data_TLB, 0x0800)
954	mov	r16=cr.ifa
955	mov	r17=pr
956	;;
957	thash	r18=r16
958	ttag	r19=r16
959	;;
960	add	r21=16,r18		// tag
961	add	r20=24,r18		// collision chain
962	;;
963	ld8	r21=[r21]		// check VHPT tag
964	ld8	r20=[r20]		// bucket head
965	;;
966	cmp.ne	p15,p0=r21,r19
967(p15)	br.dpnt.few 1f
968	;;
969	ld8	r21=[r18]		// read pte
970	;;
971	itc.d	r21			// insert pte
972	mov	pr=r17,0x1ffff
973	;;
974	rfi				// done
975	;;
9761:	rsm	psr.dt			// turn off data translations
977	dep	r20=0,r20,61,3		// convert vhpt ptr to physical
978	;;
979	srlz.d				// serialize
980	ld8	r20=[r20]		// first entry
981	;;
9822:	cmp.eq	p15,p0=r0,r20		// done?
983(p15)	br.cond.spnt.few 9f		// bail if done
984	;;
985	add	r21=16,r20		// tag location
986	;;
987	ld8	r21=[r21]		// read tag
988	;;
989	cmp.ne	p15,p0=r21,r19		// compare tags
990(p15)	br.cond.sptk.few 3f		// if not, read next in chain
991	;;
992	ld8	r21=[r20]		// read pte
993	mov	r22=PTE_ACCESSED
994	;;
995	or	r21=r21,r22
996	;;
997	st8	[r20]=r21,8
998	;;
999	ld8	r22=[r20]		// read rest of pte
1000	;;
1001	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
1002	;;
1003	add	r20=16,r18		// address of tag
1004	;;
1005	ld8.acq	r23=[r20]		// read old tag
1006	;;
1007	dep	r23=-1,r23,63,1		// set ti bit
1008	;;
1009	st8.rel	[r20]=r23		// store old tag + ti
1010	;;
1011	mf				// make sure everyone sees
1012	;;
1013	st8	[r18]=r21,8		// store pte
1014	;;
1015	st8	[r18]=r22,8
1016	;;
1017	st8.rel	[r18]=r19		// store new tag
1018	;;
1019	itc.d	r21			// and place in TLB
1020	ssm	psr.dt
1021	;;
1022	srlz.d
1023	mov	pr=r17,0x1ffff		// restore predicates
1024	rfi
1025	;;
10263:	add	r20=24,r20		// next in chain
1027	;;
1028	ld8	r20=[r20]		// read chain
1029	br.sptk	2b			// loop
1030	;;
10319:	ssm	psr.dt
1032	mov	pr=r17,0x1ffff		// restore predicates
1033	;;
1034	srlz.d
1035	;;
1036	CALL(trap, 20, cr.ifa)		// Page Not Present trap
1037IVT_END(Data_TLB)
1038
1039IVT_ENTRY(Alternate_Instruction_TLB, 0x0c00)
1040	mov	r16=cr.ifa		// where did it happen
1041	mov	r18=pr			// save predicates
1042	;;
1043	extr.u	r17=r16,61,3		// get region number
1044	mov	r19=PTE_PRESENT+PTE_ACCESSED+PTE_DIRTY+PTE_PL_KERN+PTE_AR_RWX
1045	;;
1046	cmp.eq	p13,p0=IA64_PBVM_RR,r17		// RR4?
1047(p13)	br.cond.sptk.few	4f
1048	;;
1049	cmp.ge	p13,p0=5,r17		// RR0-RR5?
1050	cmp.eq	p14,p15=7,r17		// RR7?
1051(p13)	br.cond.spnt.few	9f
1052	;;
1053(p14)	add	r19=PTE_MA_WB,r19
1054(p15)	add	r19=PTE_MA_UC,r19
1055	dep	r17=0,r16,50,14		// clear bits above PPN
1056	;;
10571:	dep	r16=r19,r17,0,12	// put pte bits in 0..11
1058	;;
1059	itc.i	r16
1060	mov	pr=r18,0x1ffff		// restore predicates
1061	;;
1062	rfi
1063	;;
10644:
1065	add	r19=PTE_MA_WB,r19
1066	movl	r17=IA64_PBVM_BASE
1067	;;
1068	sub	r17=r16,r17
1069	movl	r16=IA64_PBVM_PGTBL
1070	;;
1071	extr.u	r17=r17,IA64_PBVM_PAGE_SHIFT,61-IA64_PBVM_PAGE_SHIFT
1072	;;
1073	shladd	r16=r17,3,r16
1074	;;
1075	ld8	r17=[r16]
1076	br.sptk	1b
1077	;;
10789:	mov	pr=r18,0x1ffff		// restore predicates
1079	CALL(trap, 3, cr.ifa)
1080IVT_END(Alternate_Instruction_TLB)
1081
1082IVT_ENTRY(Alternate_Data_TLB, 0x1000)
1083	mov	r16=cr.ifa		// where did it happen
1084	mov	r18=pr			// save predicates
1085	;;
1086	extr.u	r17=r16,61,3		// get region number
1087	mov	r19=PTE_PRESENT+PTE_ACCESSED+PTE_DIRTY+PTE_PL_KERN+PTE_AR_RWX
1088	;;
1089	cmp.eq	p13,p0=IA64_PBVM_RR,r17		// RR4?
1090(p13)	br.cond.sptk.few	4f
1091	;;
1092	cmp.ge	p13,p0=5,r17		// RR0-RR5?
1093	cmp.eq	p14,p15=7,r17		// RR7?
1094(p13)	br.cond.spnt.few	9f
1095	;;
1096(p14)	add	r19=PTE_MA_WB,r19
1097(p15)	add	r19=PTE_MA_UC,r19
1098	dep	r17=0,r16,50,14		// clear bits above PPN
1099	;;
11001:	dep	r16=r19,r17,0,12	// put pte bits in 0..11
1101	;;
1102	itc.d	r16
1103	mov	pr=r18,0x1ffff		// restore predicates
1104	;;
1105	rfi
1106	;;
11074:
1108	add	r19=PTE_MA_WB,r19
1109	movl	r17=IA64_PBVM_BASE
1110	;;
1111	sub	r17=r16,r17
1112	movl	r16=IA64_PBVM_PGTBL
1113	;;
1114	extr.u	r17=r17,IA64_PBVM_PAGE_SHIFT,61-IA64_PBVM_PAGE_SHIFT
1115	;;
1116	shladd	r16=r17,3,r16
1117	;;
1118	ld8	r17=[r16]
1119	br.sptk	1b
1120	;;
11219:	mov	pr=r18,0x1ffff		// restore predicates
1122	CALL(trap, 4, cr.ifa)
1123IVT_END(Alternate_Data_TLB)
1124
1125IVT_ENTRY(Data_Nested_TLB, 0x1400)
1126	// See exception_save_restart and exception_restore_restart for the
1127	// contexts that may cause a data nested TLB. We can only use the
1128	// banked general registers and predicates, but don't use:
1129	//	p14 & p15	-	Set in exception save
1130	//	r16 & r17	-	Arguments to exception save
1131	//	r30		-	Faulting address (modulo page size)
1132	// We assume r30 has the virtual addresses that relate to the data
1133	// nested TLB fault. The address does not have to be exact, as long
1134	// as it's in the same page. We use physical addressing to avoid
1135	// double nested faults. Since all virtual addresses we encounter
1136	// here are direct mapped region 7 addresses, we have no problem
1137	// constructing physical addresses.
1138
1139{	.mmi
1140	mov		cr.ifa=r30
1141	mov		r26=rr[r30]
1142	extr.u		r27=r30,61,3
1143	;;
1144}
1145{	.mii
1146	nop		0
1147	dep		r26=0,r26,0,2
1148	cmp.eq		p12,p13=7,r27
1149	;;
1150}
1151{	.mii
1152	mov		cr.itir=r26
1153(p12)	dep		r28=0,r30,0,12
1154(p13)	extr.u		r28=r30,3*PAGE_SHIFT-8, PAGE_SHIFT-3	// dir L0 index
1155	;;
1156}
1157{	.mlx
1158(p12)	add		r28=PTE_PRESENT+PTE_ACCESSED+PTE_DIRTY+PTE_PL_KERN+PTE_AR_RWX+PTE_MA_WB,r28
1159(p13)	movl		r27=ia64_kptdir
1160	;;
1161}
1162{	.mib
1163(p13)	ld8		r27=[r27]
1164(p13)	extr.u		r26=r30,2*PAGE_SHIFT-5, PAGE_SHIFT-3	// dir L1 index
1165(p12)	br.cond.spnt.few 1f
1166	;;
1167}
1168{	.mmi
1169	rsm		psr.dt
1170	;;
1171	srlz.d
1172	dep		r27=0,r27,61,3
1173	;;
1174}
1175{	.mmi
1176	shladd		r27=r28,3,r27
1177	;;
1178	ld8		r27=[r27]				// dir L1 page
1179	extr.u		r28=r30,PAGE_SHIFT,PAGE_SHIFT-5		// pte index
1180	;;
1181}
1182{	.mii
1183	shladd		r27=r26,3,r27
1184	shl		r28=r28,5
1185	;;
1186	dep		r27=0,r27,61,3
1187	;;
1188}
1189	ld8		r27=[r27]				// pte page
1190	;;
1191	add		r27=r28,r27
1192	;;
1193	dep		r27=0,r27,61,3
1194	;;
1195	ld8		r28=[r27]				// pte
1196	;;
1197	or		r28=PTE_DIRTY+PTE_ACCESSED,r28
1198	;;
1199	st8		[r27]=r28
1200	;;
1201	ssm		psr.dt
1202	;;
12031:
1204{	.mmi
1205	itc.d		r28
1206	;;
1207	addl		r26=NTLBRT_SAVE,r0
1208	addl		r27=NTLBRT_RESTORE,r0
1209	;;
1210}
1211{	.mmi
1212	srlz.d
1213	cmp.eq		p12,p0=r29,r26
1214	cmp.eq		p13,p0=r29,r27
1215	;;
1216}
1217{	.mbb
1218	nop		0
1219(p12)	br.cond.sptk.few	exception_save_restart
1220(p13)	br.cond.sptk.few	exception_restore_restart
1221	;;
1222}
1223
1224{	.mlx
1225	mov		r26=ar.bsp
1226	movl		r29=kstack
1227	;;
1228}
1229{	.mlx
1230	mov		r28=sp
1231	movl		r27=kstack_top
1232	;;
1233}
1234{	.mmi
1235	add		sp=-16,r27
1236	;;
1237	mov		r27=ar.bspstore
1238	nop		0
1239	;;
1240}
1241	mov		ar.rsc=0
1242	dep		r29=r27,r29,0,9
1243	;;
1244	mov		ar.bspstore=r29
1245	;;
1246	CALL(trap, 5, r30)
1247IVT_END(Data_Nested_TLB)
1248
1249IVT_ENTRY(Instruction_Key_Miss, 0x1800)
1250	CALL(trap, 6, cr.ifa)
1251IVT_END(Instruction_Key_Miss)
1252
1253IVT_ENTRY(Data_Key_Miss, 0x1c00)
1254	CALL(trap, 7, cr.ifa)
1255IVT_END(Data_Key_Miss)
1256
1257IVT_ENTRY(Dirty_Bit, 0x2000)
1258	mov	r16=cr.ifa
1259	mov	r17=pr
1260	;;
1261	thash	r18=r16
1262	;;
1263	ttag	r19=r16
1264	add	r20=24,r18		// collision chain
1265	;;
1266	ld8	r20=[r20]		// bucket head
1267	;;
1268	rsm	psr.dt			// turn off data translations
1269	dep	r20=0,r20,61,3		// convert vhpt ptr to physical
1270	;;
1271	srlz.d				// serialize
1272	ld8	r20=[r20]		// first entry
1273	;;
12741:	cmp.eq	p15,p0=r0,r20		// done?
1275(p15)	br.cond.spnt.few 9f		// bail if done
1276	;;
1277	add	r21=16,r20		// tag location
1278	;;
1279	ld8	r21=[r21]		// read tag
1280	;;
1281	cmp.ne	p15,p0=r21,r19		// compare tags
1282(p15)	br.cond.sptk.few 2f		// if not, read next in chain
1283	;;
1284	ld8	r21=[r20]		// read pte
1285	mov	r22=PTE_DIRTY+PTE_ACCESSED
1286	;;
1287	or	r21=r22,r21		// set dirty & access bit
1288	;;
1289	st8	[r20]=r21,8		// store back
1290	;;
1291	ld8	r22=[r20]		// read rest of pte
1292	;;
1293	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
1294	;;
1295	add	r20=16,r18		// address of tag
1296	;;
1297	ld8.acq	r23=[r20]		// read old tag
1298	;;
1299	dep	r23=-1,r23,63,1		// set ti bit
1300	;;
1301	st8.rel	[r20]=r23		// store old tag + ti
1302	;;
1303	mf				// make sure everyone sees
1304	;;
1305	st8	[r18]=r21,8		// store pte
1306	;;
1307	st8	[r18]=r22,8
1308	;;
1309	st8.rel	[r18]=r19		// store new tag
1310	;;
1311	itc.d	r21			// and place in TLB
1312	ssm	psr.dt
1313	;;
1314	srlz.d
1315	mov	pr=r17,0x1ffff		// restore predicates
1316	rfi
1317	;;
13182:	add	r20=24,r20		// next in chain
1319	;;
1320	ld8	r20=[r20]		// read chain
1321	br.sptk	1b			// loop
1322	;;
13239:	ssm	psr.dt
1324	mov	pr=r17,0x1ffff		// restore predicates
1325	;;
1326	srlz.d
1327	;;
1328	CALL(trap, 8, cr.ifa)			// die horribly
1329IVT_END(Dirty_Bit)
1330
1331IVT_ENTRY(Instruction_Access_Bit, 0x2400)
1332	mov	r16=cr.ifa
1333	mov	r17=pr
1334	;;
1335	thash	r18=r16
1336	;;
1337	ttag	r19=r16
1338	add	r20=24,r18		// collision chain
1339	;;
1340	ld8	r20=[r20]		// bucket head
1341	;;
1342	rsm	psr.dt			// turn off data translations
1343	dep	r20=0,r20,61,3		// convert vhpt ptr to physical
1344	;;
1345	srlz.d				// serialize
1346	ld8	r20=[r20]		// first entry
1347	;;
13481:	cmp.eq	p15,p0=r0,r20		// done?
1349(p15)	br.cond.spnt.few 9f		// bail if done
1350	;;
1351	add	r21=16,r20		// tag location
1352	;;
1353	ld8	r21=[r21]		// read tag
1354	;;
1355	cmp.ne	p15,p0=r21,r19		// compare tags
1356(p15)	br.cond.sptk.few 2f		// if not, read next in chain
1357	;;
1358	ld8	r21=[r20]		// read pte
1359	mov	r22=PTE_ACCESSED
1360	;;
1361	or	r21=r22,r21		// set accessed bit
1362	;;
1363	st8	[r20]=r21,8		// store back
1364	;;
1365	ld8	r22=[r20]		// read rest of pte
1366	;;
1367	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
1368	;;
1369	add	r20=16,r18		// address of tag
1370	;;
1371	ld8.acq	r23=[r20]		// read old tag
1372	;;
1373	dep	r23=-1,r23,63,1		// set ti bit
1374	;;
1375	st8.rel	[r20]=r23		// store old tag + ti
1376	;;
1377	mf				// make sure everyone sees
1378	;;
1379	st8	[r18]=r21,8		// store pte
1380	;;
1381	st8	[r18]=r22,8
1382	;;
1383	st8.rel	[r18]=r19		// store new tag
1384	;;
1385	itc.i	r21			// and place in TLB
1386	ssm	psr.dt
1387	;;
1388	srlz.d
1389	mov	pr=r17,0x1ffff		// restore predicates
1390	rfi				// walker will retry the access
1391	;;
13922:	add	r20=24,r20		// next in chain
1393	;;
1394	ld8	r20=[r20]		// read chain
1395	br.sptk	1b			// loop
1396	;;
13979:	ssm	psr.dt
1398	mov	pr=r17,0x1ffff		// restore predicates
1399	;;
1400	srlz.d
1401	;;
1402	CALL(trap, 9, cr.ifa)
1403IVT_END(Instruction_Access_Bit)
1404
1405IVT_ENTRY(Data_Access_Bit, 0x2800)
1406	mov	r16=cr.ifa
1407	mov	r17=pr
1408	;;
1409	thash	r18=r16
1410	;;
1411	ttag	r19=r16
1412	add	r20=24,r18		// collision chain
1413	;;
1414	ld8	r20=[r20]		// bucket head
1415	;;
1416	rsm	psr.dt			// turn off data translations
1417	dep	r20=0,r20,61,3		// convert vhpt ptr to physical
1418	;;
1419	srlz.d				// serialize
1420	ld8	r20=[r20]		// first entry
1421	;;
14221:	cmp.eq	p15,p0=r0,r20		// done?
1423(p15)	br.cond.spnt.few 9f		// bail if done
1424	;;
1425	add	r21=16,r20		// tag location
1426	;;
1427	ld8	r21=[r21]		// read tag
1428	;;
1429	cmp.ne	p15,p0=r21,r19		// compare tags
1430(p15)	br.cond.sptk.few 2f		// if not, read next in chain
1431	;;
1432	ld8	r21=[r20]		// read pte
1433	mov	r22=PTE_ACCESSED
1434	;;
1435	or	r21=r22,r21		// set accessed bit
1436	;;
1437	st8	[r20]=r21,8		// store back
1438	;;
1439	ld8	r22=[r20]		// read rest of pte
1440	;;
1441	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
1442	;;
1443	add	r20=16,r18		// address of tag
1444	;;
1445	ld8.acq	r23=[r20]		// read old tag
1446	;;
1447	dep	r23=-1,r23,63,1		// set ti bit
1448	;;
1449	st8.rel	[r20]=r23		// store old tag + ti
1450	;;
1451	mf				// make sure everyone sees
1452	;;
1453	st8	[r18]=r21,8		// store pte
1454	;;
1455	st8	[r18]=r22,8
1456	;;
1457	st8.rel	[r18]=r19		// store new tag
1458	;;
1459	itc.d	r21			// and place in TLB
1460	ssm	psr.dt
1461	;;
1462	srlz.d
1463	mov	pr=r17,0x1ffff		// restore predicates
1464	rfi				// walker will retry the access
1465	;;
14662:	add	r20=24,r20		// next in chain
1467	;;
1468	ld8	r20=[r20]		// read chain
1469	br.sptk	1b			// loop
1470	;;
14719:	ssm	psr.dt
1472	mov	pr=r17,0x1ffff		// restore predicates
1473	;;
1474	srlz.d
1475	;;
1476	CALL(trap, 10, cr.ifa)
1477IVT_END(Data_Access_Bit)
1478
1479IVT_ENTRY(Break_Instruction, 0x2c00)
1480{	.mib
1481	mov		r17=cr.iim
1482	mov		r16=ip
1483	br.sptk		exception_save
1484	;;
1485}
1486{	.mmi
1487	alloc		r15=ar.pfs,0,0,2,0
1488	;;
1489(p11)	ssm		psr.i
1490	mov		out0=11
1491	;;
1492}
1493{	.mmi
1494	flushrs
1495	;;
1496(p11)	srlz.d
1497	add		out1=16,sp
1498}
1499{	.mib
1500	nop		0
1501	nop		0
1502	br.call.sptk	rp=trap
1503	;;
1504}
1505{	.mib
1506	nop		0
1507	nop		0
1508	br.sptk		exception_restore
1509	;;
1510}
1511IVT_END(Break_Instruction)
1512
1513IVT_ENTRY(External_Interrupt, 0x3000)
1514{	.mib
1515	mov		r17=0
1516	mov		r16=ip
1517	br.sptk		exception_save
1518	;;
1519}
1520{	.mmi
1521	alloc		r15=ar.pfs,0,0,1,0
1522	nop		0
1523	nop		0
1524	;;
1525}
1526{	.mib
1527	add		out0=16,sp
1528	nop		0
1529	br.call.sptk	rp=ia64_handle_intr
1530	;;
1531}
1532{	.mib
1533	nop		0
1534	nop		0
1535	br.sptk		exception_restore
1536	;;
1537}
1538IVT_END(External_Interrupt)
1539
1540IVT_ENTRY(Reserved_3400, 0x3400)
1541	CALL(trap, 13, cr.ifa)
1542IVT_END(Reserved_3400)
1543
1544IVT_ENTRY(Reserved_3800, 0x3800)
1545	CALL(trap, 14, cr.ifa)
1546IVT_END(Reserved_3800)
1547
1548IVT_ENTRY(Reserved_3c00, 0x3c00)
1549	CALL(trap, 15, cr.ifa)
1550IVT_END(Reserved_3c00)
1551
1552IVT_ENTRY(Reserved_4000, 0x4000)
1553	CALL(trap, 16, cr.ifa)
1554IVT_END(Reserved_4000)
1555
1556IVT_ENTRY(Reserved_4400, 0x4400)
1557	CALL(trap, 17, cr.ifa)
1558IVT_END(Reserved_4400)
1559
1560IVT_ENTRY(Reserved_4800, 0x4800)
1561	CALL(trap, 18, cr.ifa)
1562IVT_END(Reserved_4800)
1563
1564IVT_ENTRY(Reserved_4c00, 0x4c00)
1565	CALL(trap, 19, cr.ifa)
1566IVT_END(Reserved_4c00)
1567
1568IVT_ENTRY(Page_Not_Present, 0x5000)
1569	CALL(trap, 20, cr.ifa)
1570IVT_END(Page_Not_Present)
1571
1572IVT_ENTRY(Key_Permission, 0x5100)
1573	CALL(trap, 21, cr.ifa)
1574IVT_END(Key_Permission)
1575
1576IVT_ENTRY(Instruction_Access_Rights, 0x5200)
1577	CALL(trap, 22, cr.ifa)
1578IVT_END(Instruction_Access_Rights)
1579
1580IVT_ENTRY(Data_Access_Rights, 0x5300)
1581	CALL(trap, 23, cr.ifa)
1582IVT_END(Data_Access_Rights)
1583
1584IVT_ENTRY(General_Exception, 0x5400)
1585	CALL(trap, 24, cr.ifa)
1586IVT_END(General_Exception)
1587
1588IVT_ENTRY(Disabled_FP_Register, 0x5500)
1589	CALL(trap, 25, cr.ifa)
1590IVT_END(Disabled_FP_Register)
1591
1592IVT_ENTRY(NaT_Consumption, 0x5600)
1593	CALL(trap, 26, cr.ifa)
1594IVT_END(NaT_Consumption)
1595
1596IVT_ENTRY(Speculation, 0x5700)
1597	CALL(trap, 27, cr.iim)
1598IVT_END(Speculation)
1599
1600IVT_ENTRY(Reserved_5800, 0x5800)
1601	CALL(trap, 28, cr.ifa)
1602IVT_END(Reserved_5800)
1603
1604IVT_ENTRY(Debug, 0x5900)
1605	CALL(trap, 29, cr.ifa)
1606IVT_END(Debug)
1607
1608IVT_ENTRY(Unaligned_Reference, 0x5a00)
1609	CALL(trap, 30, cr.ifa)
1610IVT_END(Unaligned_Reference)
1611
1612IVT_ENTRY(Unsupported_Data_Reference, 0x5b00)
1613	CALL(trap, 31, cr.ifa)
1614IVT_END(Unsupported_Data_Reference)
1615
1616IVT_ENTRY(Floating_Point_Fault, 0x5c00)
1617	CALL(trap, 32, cr.ifa)
1618IVT_END(Floating_Point_Fault)
1619
1620IVT_ENTRY(Floating_Point_Trap, 0x5d00)
1621	CALL(trap, 33, cr.ifa)
1622IVT_END(Floating_Point_Trap)
1623
1624IVT_ENTRY(Lower_Privilege_Transfer_Trap, 0x5e00)
1625	CALL(trap, 34, cr.ifa)
1626IVT_END(Lower_Privilege_Transfer_Trap)
1627
1628IVT_ENTRY(Taken_Branch_Trap, 0x5f00)
1629	CALL(trap, 35, cr.ifa)
1630IVT_END(Taken_Branch_Trap)
1631
1632IVT_ENTRY(Single_Step_Trap, 0x6000)
1633	CALL(trap, 36, cr.ifa)
1634IVT_END(Single_Step_Trap)
1635
1636IVT_ENTRY(Reserved_6100, 0x6100)
1637	CALL(trap, 37, cr.ifa)
1638IVT_END(Reserved_6100)
1639
1640IVT_ENTRY(Reserved_6200, 0x6200)
1641	CALL(trap, 38, cr.ifa)
1642IVT_END(Reserved_6200)
1643
1644IVT_ENTRY(Reserved_6300, 0x6300)
1645	CALL(trap, 39, cr.ifa)
1646IVT_END(Reserved_6300)
1647
1648IVT_ENTRY(Reserved_6400, 0x6400)
1649	CALL(trap, 40, cr.ifa)
1650IVT_END(Reserved_6400)
1651
1652IVT_ENTRY(Reserved_6500, 0x6500)
1653	CALL(trap, 41, cr.ifa)
1654IVT_END(Reserved_6500)
1655
1656IVT_ENTRY(Reserved_6600, 0x6600)
1657	CALL(trap, 42, cr.ifa)
1658IVT_END(Reserved_6600)
1659
1660IVT_ENTRY(Reserved_6700, 0x6700)
1661	CALL(trap, 43, cr.ifa)
1662IVT_END(Reserved_6700)
1663
1664IVT_ENTRY(Reserved_6800, 0x6800)
1665	CALL(trap, 44, cr.ifa)
1666IVT_END(Reserved_6800)
1667
1668IVT_ENTRY(IA_32_Exception, 0x6900)
1669	CALL(IA32_TRAP, 45, cr.ifa)
1670IVT_END(IA_32_Exception)
1671
1672IVT_ENTRY(IA_32_Intercept, 0x6a00)
1673	CALL(IA32_TRAP, 46, cr.iim)
1674IVT_END(IA_32_Intercept)
1675
1676IVT_ENTRY(IA_32_Interrupt, 0x6b00)
1677	CALL(IA32_TRAP, 47, cr.ifa)
1678IVT_END(IA_32_Interrupt)
1679
1680IVT_ENTRY(Reserved_6c00, 0x6c00)
1681	CALL(trap, 48, cr.ifa)
1682IVT_END(Reserved_6c00)
1683
1684IVT_ENTRY(Reserved_6d00, 0x6d00)
1685	CALL(trap, 49, cr.ifa)
1686IVT_END(Reserved_6d00)
1687
1688IVT_ENTRY(Reserved_6e00, 0x6e00)
1689	CALL(trap, 50, cr.ifa)
1690IVT_END(Reserved_6e00)
1691
1692IVT_ENTRY(Reserved_6f00, 0x6f00)
1693	CALL(trap, 51, cr.ifa)
1694IVT_END(Reserved_6f00)
1695
1696IVT_ENTRY(Reserved_7000, 0x7000)
1697	CALL(trap, 52, cr.ifa)
1698IVT_END(Reserved_7000)
1699
1700IVT_ENTRY(Reserved_7100, 0x7100)
1701	CALL(trap, 53, cr.ifa)
1702IVT_END(Reserved_7100)
1703
1704IVT_ENTRY(Reserved_7200, 0x7200)
1705	CALL(trap, 54, cr.ifa)
1706IVT_END(Reserved_7200)
1707
1708IVT_ENTRY(Reserved_7300, 0x7300)
1709	CALL(trap, 55, cr.ifa)
1710IVT_END(Reserved_7300)
1711
1712IVT_ENTRY(Reserved_7400, 0x7400)
1713	CALL(trap, 56, cr.ifa)
1714IVT_END(Reserved_7400)
1715
1716IVT_ENTRY(Reserved_7500, 0x7500)
1717	CALL(trap, 57, cr.ifa)
1718IVT_END(Reserved_7500)
1719
1720IVT_ENTRY(Reserved_7600, 0x7600)
1721	CALL(trap, 58, cr.ifa)
1722IVT_END(Reserved_7600)
1723
1724IVT_ENTRY(Reserved_7700, 0x7700)
1725	CALL(trap, 59, cr.ifa)
1726IVT_END(Reserved_7700)
1727
1728IVT_ENTRY(Reserved_7800, 0x7800)
1729	CALL(trap, 60, cr.ifa)
1730IVT_END(Reserved_7800)
1731
1732IVT_ENTRY(Reserved_7900, 0x7900)
1733	CALL(trap, 61, cr.ifa)
1734IVT_END(Reserved_7900)
1735
1736IVT_ENTRY(Reserved_7a00, 0x7a00)
1737	CALL(trap, 62, cr.ifa)
1738IVT_END(Reserved_7a00)
1739
1740IVT_ENTRY(Reserved_7b00, 0x7b00)
1741	CALL(trap, 63, cr.ifa)
1742IVT_END(Reserved_7b00)
1743
1744IVT_ENTRY(Reserved_7c00, 0x7c00)
1745	CALL(trap, 64, cr.ifa)
1746IVT_END(Reserved_7c00)
1747
1748IVT_ENTRY(Reserved_7d00, 0x7d00)
1749	CALL(trap, 65, cr.ifa)
1750IVT_END(Reserved_7d00)
1751
1752IVT_ENTRY(Reserved_7e00, 0x7e00)
1753	CALL(trap, 66, cr.ifa)
1754IVT_END(Reserved_7e00)
1755
1756IVT_ENTRY(Reserved_7f00, 0x7f00)
1757	CALL(trap, 67, cr.ifa)
1758IVT_END(Reserved_7f00)
1759