166458Sdfr/*-
266458Sdfr * Copyright (c) 1998 Doug Rabson
366458Sdfr * All rights reserved.
466458Sdfr *
566458Sdfr * Redistribution and use in source and binary forms, with or without
666458Sdfr * modification, are permitted provided that the following conditions
766458Sdfr * are met:
866458Sdfr * 1. Redistributions of source code must retain the above copyright
966458Sdfr *    notice, this list of conditions and the following disclaimer.
1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1166458Sdfr *    notice, this list of conditions and the following disclaimer in the
1266458Sdfr *    documentation and/or other materials provided with the distribution.
1366458Sdfr *
1466458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1566458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1666458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1766458Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1866458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1966458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2066458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2166458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2266458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2366458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2466458Sdfr * SUCH DAMAGE.
2566458Sdfr *
2666458Sdfr * $FreeBSD$
2766458Sdfr */
28139790Simp/*-
2966458Sdfr * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
3066458Sdfr * All rights reserved.
3166458Sdfr *
3266458Sdfr * Author: Chris G. Demetriou
3366458Sdfr *
3466458Sdfr * Permission to use, copy, modify and distribute this software and
3566458Sdfr * its documentation is hereby granted, provided that both the copyright
3666458Sdfr * notice and this permission notice appear in all copies of the
3766458Sdfr * software, derivative works or modified versions, and any portions
3866458Sdfr * thereof, and that both notices appear in supporting documentation.
3966458Sdfr *
4066458Sdfr * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
4166458Sdfr * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
4266458Sdfr * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
4366458Sdfr *
4466458Sdfr * Carnegie Mellon requests users of this software to return to
4566458Sdfr *
4666458Sdfr *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
4766458Sdfr *  School of Computer Science
4866458Sdfr *  Carnegie Mellon University
4966458Sdfr *  Pittsburgh PA 15213-3890
5066458Sdfr *
5166458Sdfr * any improvements or extensions that they make and grant Carnegie the
5266458Sdfr * rights to redistribute these changes.
5366458Sdfr */
5466458Sdfr
5566458Sdfr#include <machine/asm.h>
5683893Sdfr#include <machine/ia64_cpu.h>
5766458Sdfr#include <assym.s>
5866458Sdfr
5966458Sdfr	.text
6066458Sdfr
61115341SmarcelENTRY(fusufault, 0)
62115341Smarcel{	.mib
63115341Smarcel	st8.rel		[r15]=r0		// Clear onfault.
64115341Smarcel	add		ret0=-1,r0
65115341Smarcel	br.ret.sptk	rp
66115341Smarcel	;;
67115341Smarcel}
68115341SmarcelEND(fusufault)
69115341Smarcel
7066458Sdfr/*
71163449Sdavidxu * casuword(u_long *p, u_long old, u_long new)
72115341Smarcel *	Perform a compare-exchange in user space.
7366458Sdfr */
74163449SdavidxuENTRY(casuword, 3)
75115341Smarcel{	.mlx
76246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
77219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
78115341Smarcel	;;
79115341Smarcel}
80115341Smarcel{	.mib
81246715Smarcel	add		r15=TD_PCB,r15
82115341Smarcel	cmp.geu		p6,p0=in0,r14
83115341Smarcel(p6)	br.dpnt.few	1f
84115341Smarcel	;;
85115341Smarcel}
86115341Smarcel{	.mlx
87246715Smarcel	ld8		r15=[r15]		// r15 = PCB
88115341Smarcel	movl		r14=fusufault
89115341Smarcel	;;
90115341Smarcel}
91115341Smarcel{	.mmi
92115341Smarcel	mov		ar.ccv=in1
93115341Smarcel	add		r15=PCB_ONFAULT,r15
94246715Smarcel	nop		0
95115341Smarcel	;;
96115341Smarcel}
97115341Smarcel{	.mmi
98115341Smarcel	st8		[r15]=r14		// Set onfault
99115341Smarcel	;;
100115341Smarcel	cmpxchg8.rel	ret0=[in0],in2,ar.ccv
101115341Smarcel	nop		0
102115341Smarcel	;;
103115341Smarcel}
104204184Smarcel{	.mib
105115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
106115341Smarcel	nop		0
107115341Smarcel	br.ret.sptk	rp
108115341Smarcel	;;
109115341Smarcel}
110115341Smarcel1:
111204184Smarcel{	.mib
112115341Smarcel	add		ret0=-1,r0
113115341Smarcel	nop		0
114115341Smarcel	br.ret.sptk	rp
115115341Smarcel	;;
116115341Smarcel}
117163449SdavidxuEND(casuword)
11866458Sdfr
119115341Smarcel/*
120163449Sdavidxu * casuword32(uint32_t *p, uint32_t old, uint32_t new)
121161675Sdavidxu *	Perform a 32-bit compare-exchange in user space.
122161675Sdavidxu */
123161675SdavidxuENTRY(casuword32, 3)
124161675Sdavidxu{	.mlx
125219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
126161675Sdavidxu	;;
127161675Sdavidxu}
128161675Sdavidxu{	.mib
129246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
130161675Sdavidxu	cmp.geu		p6,p0=in0,r14
131161675Sdavidxu(p6)	br.dpnt.few	1f
132161675Sdavidxu	;;
133161675Sdavidxu}
134161675Sdavidxu{	.mlx
135161675Sdavidxu	add		r15=TD_PCB,r15
136161675Sdavidxu	movl		r14=fusufault
137161675Sdavidxu	;;
138161675Sdavidxu}
139161675Sdavidxu{	.mmi
140161675Sdavidxu	ld8		r15=[r15]		// r15 = PCB
141161675Sdavidxu	;;
142161675Sdavidxu	mov		ar.ccv=in1
143161675Sdavidxu	add		r15=PCB_ONFAULT,r15
144161675Sdavidxu	;;
145161675Sdavidxu}
146161675Sdavidxu{	.mmi
147161675Sdavidxu	st8		[r15]=r14		// Set onfault
148161675Sdavidxu	;;
149161675Sdavidxu	cmpxchg4.rel	ret0=[in0],in2,ar.ccv
150161675Sdavidxu	nop		0
151161675Sdavidxu	;;
152161675Sdavidxu}
153204184Smarcel{	.mib
154161675Sdavidxu	st8.rel		[r15]=r0		// Clear onfault
155161675Sdavidxu	nop		0
156161675Sdavidxu	br.ret.sptk	rp
157161675Sdavidxu	;;
158161675Sdavidxu}
159161675Sdavidxu1:
160204184Smarcel{	.mib
161161675Sdavidxu	add		ret0=-1,r0
162161675Sdavidxu	nop		0
163161675Sdavidxu	br.ret.sptk	rp
164161675Sdavidxu	;;
165161675Sdavidxu}
166161675SdavidxuEND(casuword32)
167161675Sdavidxu
168161675Sdavidxu/*
169115341Smarcel * subyte(void *addr, int byte)
170115341Smarcel * suword16(void *addr, int word)
171115341Smarcel * suword32(void *addr, int word)
172115341Smarcel * suword64|suword(void *addr, long word)
173115341Smarcel *	Store in user space
174115341Smarcel */
175115341Smarcel
176115341SmarcelENTRY(subyte, 2)
177115341Smarcel{	.mlx
178219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
17966633Sdfr	;;
180115341Smarcel}
181115341Smarcel{	.mib
182246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
183115341Smarcel	cmp.geu		p6,p0=in0,r14
184115341Smarcel(p6)	br.dpnt.few	1f
18566633Sdfr	;;
186115341Smarcel}
187115341Smarcel{	.mlx
188115341Smarcel	add		r15=TD_PCB,r15
189115341Smarcel	movl		r14=fusufault
19066633Sdfr	;;
191115341Smarcel}
192115341Smarcel{	.mmi
193115341Smarcel	ld8		r15=[r15]		// r15 = PCB
19466633Sdfr	;;
195115341Smarcel	nop		0
196115341Smarcel	add		r15=PCB_ONFAULT,r15
19766633Sdfr	;;
198115341Smarcel}
199115341Smarcel{	.mmi
200115341Smarcel	st8		[r15]=r14		// Set onfault
20166633Sdfr	;;
202115341Smarcel	st1.rel		[in0]=in1
203115341Smarcel	nop		0
20466633Sdfr	;;
205115341Smarcel}
206115341Smarcel{	.mib
207115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
208115341Smarcel	mov		ret0=r0
209115341Smarcel	br.ret.sptk	rp
210115341Smarcel	;;
211115341Smarcel}
212115341Smarcel1:
213204184Smarcel{	.mib
214115341Smarcel	add		ret0=-1,r0
215115341Smarcel	nop		0
216115341Smarcel	br.ret.sptk	rp
217115341Smarcel	;;
218115341Smarcel}
219115341SmarcelEND(subyte)
22066458Sdfr
221115341SmarcelENTRY(suword16, 2)
222115341Smarcel{	.mlx
223219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
224115341Smarcel	;;
225115341Smarcel}
226115341Smarcel{	.mib
227246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
228115341Smarcel	cmp.geu		p6,p0=in0,r14
229115341Smarcel(p6)	br.dpnt.few	1f
230115341Smarcel	;;
231115341Smarcel}
232115341Smarcel{	.mlx
233115341Smarcel	add		r15=TD_PCB,r15
234115341Smarcel	movl		r14=fusufault
235115341Smarcel	;;
236115341Smarcel}
237115341Smarcel{	.mmi
238115341Smarcel	ld8		r15=[r15]		// r15 = PCB
239115341Smarcel	;;
240115341Smarcel	nop		0
241115341Smarcel	add		r15=PCB_ONFAULT,r15
242115341Smarcel	;;
243115341Smarcel}
244115341Smarcel{	.mmi
245115341Smarcel	st8		[r15]=r14		// Set onfault
246115341Smarcel	;;
247115341Smarcel	st2.rel		[in0]=in1
248115341Smarcel	nop		0
249115341Smarcel	;;
250115341Smarcel}
251115341Smarcel{	.mib
252115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
253115341Smarcel	mov		ret0=r0
254115341Smarcel	br.ret.sptk	rp
255115341Smarcel	;;
256115341Smarcel}
257115341Smarcel1:
258204184Smarcel{	.mib
259115341Smarcel	add		ret0=-1,r0
260115341Smarcel	nop		0
261115341Smarcel	br.ret.sptk	rp
262115341Smarcel	;;
263115341Smarcel}
264115341SmarcelEND(suword16)
265115341Smarcel
26698473SpeterENTRY(suword32, 2)
267115341Smarcel{	.mlx
268219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
26994377Sdfr	;;
270115341Smarcel}
271115341Smarcel{	.mib
272246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
273115341Smarcel	cmp.geu		p6,p0=in0,r14
274115341Smarcel(p6)	br.dpnt.few	1f
27594377Sdfr	;;
276115341Smarcel}
277115341Smarcel{	.mlx
278115341Smarcel	add		r15=TD_PCB,r15
279115341Smarcel	movl		r14=fusufault
28094377Sdfr	;;
281115341Smarcel}
282115341Smarcel{	.mmi
283115341Smarcel	ld8		r15=[r15]		// r15 = PCB
28494377Sdfr	;;
285115341Smarcel	nop		0
286115341Smarcel	add		r15=PCB_ONFAULT,r15
28794377Sdfr	;;
288115341Smarcel}
289115341Smarcel{	.mmi
290115341Smarcel	st8		[r15]=r14		// Set onfault
29194377Sdfr	;;
292115341Smarcel	st4.rel		[in0]=in1
293115341Smarcel	nop		0
29494377Sdfr	;;
295115341Smarcel}
296115341Smarcel{	.mib
297115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
298115341Smarcel	mov		ret0=r0
299115341Smarcel	br.ret.sptk	rp
300115341Smarcel	;;
301115341Smarcel}
302115341Smarcel1:
303204184Smarcel{	.mib
304115341Smarcel	add		ret0=-1,r0
305115341Smarcel	nop		0
306115341Smarcel	br.ret.sptk	rp
307115341Smarcel	;;
308115341Smarcel}
30998473SpeterEND(suword32)
31066458Sdfr
311115341SmarcelENTRY(suword64, 2)
312115341SmarcelXENTRY(suword)
313115341Smarcel{	.mlx
314219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
31566633Sdfr	;;
316115341Smarcel}
317115341Smarcel{	.mib
318246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
319115341Smarcel	cmp.geu		p6,p0=in0,r14
320115341Smarcel(p6)	br.dpnt.few	1f
32166633Sdfr	;;
322115341Smarcel}
323115341Smarcel{	.mlx
324115341Smarcel	add		r15=TD_PCB,r15
325115341Smarcel	movl		r14=fusufault
32666633Sdfr	;;
327115341Smarcel}
328115341Smarcel{	.mmi
329115341Smarcel	ld8		r15=[r15]		// r15 = PCB
33066633Sdfr	;;
331115341Smarcel	nop		0
332115341Smarcel	add		r15=PCB_ONFAULT,r15
33366633Sdfr	;;
334115341Smarcel}
335115341Smarcel{	.mmi
336115341Smarcel	st8		[r15]=r14		// Set onfault
33766633Sdfr	;;
338115341Smarcel	st8.rel		[in0]=in1
339115341Smarcel	nop		0
34066633Sdfr	;;
341115341Smarcel}
342115341Smarcel{	.mib
343115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
344115341Smarcel	mov		ret0=r0
345115341Smarcel	br.ret.sptk	rp
346115341Smarcel	;;
347115341Smarcel}
348115341Smarcel1:
349204184Smarcel{	.mib
350115341Smarcel	add		ret0=-1,r0
351115341Smarcel	nop		0
352115341Smarcel	br.ret.sptk	rp
353115341Smarcel	;;
354115341Smarcel}
355115341SmarcelEND(suword64)
35666458Sdfr
357115341Smarcel/*
358115341Smarcel * fubyte(void *addr, int byte)
359115341Smarcel * fuword16(void *addr, int word)
360115341Smarcel * fuword32(void *addr, int word)
361115341Smarcel * fuword64|fuword(void *addr, long word)
362115341Smarcel *	Fetch from user space
363115341Smarcel */
36466458Sdfr
365115341SmarcelENTRY(fubyte, 1)
366115341Smarcel{	.mlx
367219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
368115341Smarcel	;;
369115341Smarcel}
370115341Smarcel{	.mib
371246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
372115341Smarcel	cmp.geu		p6,p0=in0,r14
373115341Smarcel(p6)	br.dpnt.few	1f
374115341Smarcel	;;
375115341Smarcel}
376115341Smarcel{	.mlx
377115341Smarcel	add		r15=TD_PCB,r15
378115341Smarcel	movl		r14=fusufault
379115341Smarcel	;;
380115341Smarcel}
381115341Smarcel{	.mmi
382115341Smarcel	ld8		r15=[r15]		// r15 = PCB
383115341Smarcel	;;
384115341Smarcel	nop		0
385115341Smarcel	add		r15=PCB_ONFAULT,r15
386115341Smarcel	;;
387115341Smarcel}
388115341Smarcel{	.mmi
389115341Smarcel	st8		[r15]=r14		// Set onfault
390115341Smarcel	;;
391115341Smarcel	mf
392115341Smarcel	nop		0
393115341Smarcel	;;
394115341Smarcel}
395115341Smarcel{	.mmb
396115341Smarcel	ld1		ret0=[in0]
397115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
398115341Smarcel	br.ret.sptk	rp
399115341Smarcel	;;
400115341Smarcel}
401115341Smarcel1:
402204184Smarcel{	.mib
403115341Smarcel	add		ret0=-1,r0
404115341Smarcel	nop		0
405115341Smarcel	br.ret.sptk	rp
406115341Smarcel	;;
407115341Smarcel}
408115341SmarcelEND(fubyte)
40966458Sdfr
410115341SmarcelENTRY(fuword16, 2)
411115341Smarcel{	.mlx
412219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
41366633Sdfr	;;
414115341Smarcel}
415115341Smarcel{	.mib
416246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
417115341Smarcel	cmp.geu		p6,p0=in0,r14
418115341Smarcel(p6)	br.dpnt.few	1f
41966633Sdfr	;;
420115341Smarcel}
421115341Smarcel{	.mlx
422115341Smarcel	add		r15=TD_PCB,r15
423115341Smarcel	movl		r14=fusufault
42466633Sdfr	;;
425115341Smarcel}
426115341Smarcel{	.mmi
427115341Smarcel	ld8		r15=[r15]		// r15 = PCB
42866633Sdfr	;;
429115341Smarcel	nop		0
430115341Smarcel	add		r15=PCB_ONFAULT,r15
43166633Sdfr	;;
432115341Smarcel}
433115341Smarcel{	.mmi
434115341Smarcel	st8		[r15]=r14		// Set onfault
43566633Sdfr	;;
436115341Smarcel	mf
437115341Smarcel	nop		0
43866633Sdfr	;;
439115341Smarcel}
440115341Smarcel{	.mmb
441115341Smarcel	ld2		ret0=[in0]
442115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
443115341Smarcel	br.ret.sptk	rp
444115341Smarcel	;;
445115341Smarcel}
446115341Smarcel1:
447204184Smarcel{	.mib
448115341Smarcel	add		ret0=-1,r0
449115341Smarcel	nop		0
450115341Smarcel	br.ret.sptk	rp
451115341Smarcel	;;
452115341Smarcel}
453115341SmarcelEND(fuword16)
45466458Sdfr
455115341SmarcelENTRY(fuword32, 2)
456115341Smarcel{	.mlx
457219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
45894377Sdfr	;;
459115341Smarcel}
460115341Smarcel{	.mib
461246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
462115341Smarcel	cmp.geu		p6,p0=in0,r14
463115341Smarcel(p6)	br.dpnt.few	1f
46494377Sdfr	;;
465115341Smarcel}
466115341Smarcel{	.mlx
467115341Smarcel	add		r15=TD_PCB,r15
468115341Smarcel	movl		r14=fusufault
46994377Sdfr	;;
470115341Smarcel}
471115341Smarcel{	.mmi
472115341Smarcel	ld8		r15=[r15]		// r15 = PCB
47394377Sdfr	;;
474115341Smarcel	nop		0
475115341Smarcel	add		r15=PCB_ONFAULT,r15
47694377Sdfr	;;
477115341Smarcel}
478115341Smarcel{	.mmi
479115341Smarcel	st8		[r15]=r14		// Set onfault
48094377Sdfr	;;
481115341Smarcel	mf
482115341Smarcel	nop		0
48394377Sdfr	;;
484115341Smarcel}
485115341Smarcel{	.mmb
486115341Smarcel	ld4		ret0=[in0]
487115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
488115341Smarcel	br.ret.sptk	rp
489115341Smarcel	;;
490115341Smarcel}
491115341Smarcel1:
492204184Smarcel{	.mib
493115341Smarcel	add		ret0=-1,r0
494115341Smarcel	nop		0
495115341Smarcel	br.ret.sptk	rp
496115341Smarcel	;;
497115341Smarcel}
49898473SpeterEND(fuword32)
49994377Sdfr
500115341SmarcelENTRY(fuword64, 2)
501115341SmarcelXENTRY(fuword)
502115341Smarcel{	.mlx
503219741Smarcel	movl		r14=VM_MAXUSER_ADDRESS
50466633Sdfr	;;
505115341Smarcel}
506115341Smarcel{	.mib
507246715Smarcel	ld8.acq		r15=[r13]		// r15 = curthread
508115341Smarcel	cmp.geu		p6,p0=in0,r14
509115341Smarcel(p6)	br.dpnt.few	1f
51066633Sdfr	;;
511115341Smarcel}
512115341Smarcel{	.mlx
513115341Smarcel	add		r15=TD_PCB,r15
514115341Smarcel	movl		r14=fusufault
51566633Sdfr	;;
516115341Smarcel}
517115341Smarcel{	.mmi
518115341Smarcel	ld8		r15=[r15]		// r15 = PCB
51966633Sdfr	;;
520115341Smarcel	nop		0
521115341Smarcel	add		r15=PCB_ONFAULT,r15
52266633Sdfr	;;
523115341Smarcel}
524115341Smarcel{	.mmi
525115341Smarcel	st8		[r15]=r14		// Set onfault
52666633Sdfr	;;
527115341Smarcel	mf
528115341Smarcel	nop		0
52966633Sdfr	;;
530115341Smarcel}
531115341Smarcel{	.mmb
532115341Smarcel	ld8		ret0=[in0]
533115341Smarcel	st8.rel		[r15]=r0		// Clear onfault
534115341Smarcel	br.ret.sptk	rp
535115341Smarcel	;;
536115341Smarcel}
537115341Smarcel1:
538204184Smarcel{	.mib
539115341Smarcel	add		ret0=-1,r0
540115341Smarcel	nop		0
541115341Smarcel	br.ret.sptk	rp
542115341Smarcel	;;
543115341Smarcel}
544115341SmarcelEND(fuword64)
54566458Sdfr
546115341Smarcel/*
547115341Smarcel * fuswintr(void *addr)
548115341Smarcel * suswintr(void *addr)
549115341Smarcel */
550115341Smarcel
551115341SmarcelENTRY(fuswintr, 1)
552204184Smarcel{	.mib
553115341Smarcel	add		ret0=-1,r0
554115341Smarcel	nop		0
555115341Smarcel	br.ret.sptk	rp
556115341Smarcel	;;
557115341Smarcel}
558115341SmarcelEND(fuswintr)
559115341Smarcel
560115341SmarcelENTRY(suswintr, 0)
561204184Smarcel{	.mib
562115341Smarcel	add		ret0=-1,r0
563115341Smarcel	nop		0
564115341Smarcel	br.ret.sptk	rp
565115341Smarcel	;;
566115341Smarcel}
567115341SmarcelEND(suswintr)
568115341Smarcel
56966458Sdfr/**************************************************************************/
57066458Sdfr
57166458Sdfr/*
57266458Sdfr * Copy a null-terminated string within the kernel's address space.
57366458Sdfr * If lenp is not NULL, store the number of chars copied in *lenp
57466458Sdfr *
57566458Sdfr * int copystr(char *from, char *to, size_t len, size_t *lenp);
57666458Sdfr */
57766633SdfrENTRY(copystr, 4)
57866486Sdfr	mov	r14=in2			// r14 = i = len
57966486Sdfr	cmp.eq	p6,p0=r0,in2
58066486Sdfr(p6)	br.cond.spnt.few 2f		// if (len == 0), bail out
58166458Sdfr
58266486Sdfr1:	ld1	r15=[in0],1		// read one byte
58366486Sdfr	;;
58466486Sdfr	st1	[in1]=r15,1		// write that byte
58566486Sdfr	add	in2=-1,in2		// len--
58666486Sdfr	;;
58766486Sdfr	cmp.eq	p6,p0=r0,r15
58866486Sdfr	cmp.ne	p7,p0=r0,in2
58966486Sdfr	;;
59066486Sdfr(p6)	br.cond.spnt.few 2f		// if (*from == 0), bail out
59166486Sdfr(p7)	br.cond.sptk.few 1b		// if (len != 0) copy more
59266458Sdfr
59366486Sdfr2:	cmp.eq	p6,p0=r0,in3
59466486Sdfr(p6)	br.cond.dpnt.few 3f		// if (lenp != NULL)
59567020Sdfr	sub	r14=r14,in2		// *lenp = (i - len)
59666486Sdfr	;;
59766486Sdfr	st8	[in3]=r14
59866486Sdfr
59966486Sdfr3:	cmp.eq	p6,p0=r0,r15
60066486Sdfr(p6)	br.cond.spnt.few 4f		// *from == '\0'; leave quietly
60166458Sdfr
60266486Sdfr	mov	ret0=ENAMETOOLONG	// *from != '\0'; error.
60366486Sdfr	br.ret.sptk.few rp
60466458Sdfr
60566486Sdfr4:	mov	ret0=0			// return 0.
60666486Sdfr	br.ret.sptk.few rp
60766486SdfrEND(copystr)
60866458Sdfr
60966633SdfrENTRY(copyinstr, 4)
61085682Sdfr	.prologue
61185682Sdfr	.regstk	4, 3, 4, 0
61285682Sdfr	.save	ar.pfs,loc0
61366486Sdfr	alloc	loc0=ar.pfs,4,3,4,0
61485682Sdfr	.save	rp,loc1
61566486Sdfr	mov	loc1=rp
61685682Sdfr	.body
61766458Sdfr
618219741Smarcel	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
61966486Sdfr	;;
62066633Sdfr	cmp.geu	p6,p0=in0,loc2			// is in user space.
62166486Sdfr	;;
62266486Sdfr(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
623246715Smarcel	ld8.acq	r15=[r13]
62466486Sdfr	movl	r14=copyerr			// set up fault handler.
62566486Sdfr	;;
62683366Sjulian	add	r15=TD_PCB,r15			// find pcb
62766486Sdfr	;;
62866486Sdfr	ld8	r15=[r15]
62966486Sdfr	;;
63083366Sjulian	add	loc2=PCB_ONFAULT,r15
63166486Sdfr	;;
63266486Sdfr	st8	[loc2]=r14
63366486Sdfr	;;
63466486Sdfr	mov	out0=in0
63566486Sdfr	mov	out1=in1
63666486Sdfr	mov	out2=in2
63766486Sdfr	mov	out3=in3
63866486Sdfr	;;
63966486Sdfr	br.call.sptk.few rp=copystr		// do the copy.
64066486Sdfr	st8	[loc2]=r0			// kill the fault handler.
64167020Sdfr	mov	ar.pfs=loc0			// restore ar.pfs
64266486Sdfr	mov	rp=loc1				// restore ra.
64366486Sdfr	br.ret.sptk.few rp			// ret0 left over from copystr
64466486SdfrEND(copyinstr)
64566458Sdfr
64666458Sdfr/*
64766486Sdfr * Not the fastest bcopy in the world.
64866458Sdfr */
64966633SdfrENTRY(bcopy, 3)
65066486Sdfr	mov	ret0=r0				// return zero for copy{in,out}
65166486Sdfr	;;
65266486Sdfr	cmp.le	p6,p0=in2,r0			// bail if len <= 0
65366486Sdfr(p6)	br.ret.spnt.few rp
65466458Sdfr
65566486Sdfr	sub	r14=in1,in0 ;;			// check for overlap
65666486Sdfr	cmp.ltu	p6,p0=r14,in2			// dst-src < len
65766486Sdfr(p6)	br.cond.spnt.few 5f
65866458Sdfr
65966486Sdfr	extr.u	r14=in0,0,3			// src & 7
66066486Sdfr	extr.u	r15=in1,0,3 ;;			// dst & 7
66166486Sdfr	cmp.eq	p6,p0=r14,r15			// different alignment?
66266486Sdfr(p6)	br.cond.spnt.few 2f			// branch if same alignment
66366458Sdfr
66466486Sdfr1:	ld1	r14=[in0],1 ;;			// copy bytewise
66566486Sdfr	st1	[in1]=r14,1
66666486Sdfr	add	in2=-1,in2 ;;			// len--
66766486Sdfr	cmp.ne	p6,p0=r0,in2
66866486Sdfr(p6)	br.cond.dptk.few 1b			// loop
66966486Sdfr	br.ret.sptk.few rp			// done
67066458Sdfr
67166486Sdfr2:	cmp.eq	p6,p0=r14,r0			// aligned?
67266486Sdfr(p6)	br.cond.sptk.few 4f
67366458Sdfr
67466486Sdfr3:	ld1	r14=[in0],1 ;;			// copy bytewise
67566486Sdfr	st1	[in1]=r14,1
67666486Sdfr	extr.u	r15=in0,0,3			// src & 7
67766486Sdfr	add	in2=-1,in2 ;;			// len--
67866486Sdfr	cmp.eq	p6,p0=r0,in2			// done?
67966486Sdfr	cmp.eq	p7,p0=r0,r15 ;;			// aligned now?
68066486Sdfr(p6)	br.ret.spnt.few rp			// return if done
68166486Sdfr(p7)	br.cond.spnt.few 4f			// go to main copy
68266486Sdfr	br.cond.sptk.few 3b			// more bytes to copy
68366458Sdfr
68466486Sdfr	// At this point, in2 is non-zero
68566458Sdfr
68666486Sdfr4:	mov	r14=8 ;;
68766486Sdfr	cmp.ltu	p6,p0=in2,r14 ;;		// len < 8?
68866486Sdfr(p6)	br.cond.spnt.few 1b			// byte copy the end
68966486Sdfr	ld8	r15=[in0],8 ;;			// copy word
69066486Sdfr	st8	[in1]=r15,8
69166486Sdfr	add	in2=-8,in2 ;;			// len -= 8
69266486Sdfr	cmp.ne	p6,p0=r0,in2			// done?
69366486Sdfr(p6)	br.cond.spnt.few 4b			// again
69466458Sdfr
69566486Sdfr	br.ret.sptk.few rp			// return
69666458Sdfr
69766486Sdfr	// Don't bother optimising overlap case
69866458Sdfr
69966486Sdfr5:	add	in0=in0,in2
70066486Sdfr	add	in1=in1,in2 ;;
70166486Sdfr	add	in0=-1,in0
70266486Sdfr	add	in1=-1,in1 ;;
70366458Sdfr
70466486Sdfr6:	ld1	r14=[in0],-1 ;;
70566486Sdfr	st1	[in1]=r14,-1
70666486Sdfr	add	in2=-1,in2 ;;
70766486Sdfr	cmp.ne	p6,p0=r0,in2
70866486Sdfr(p6)	br.cond.spnt.few 6b
70966458Sdfr
71066486Sdfr	br.ret.sptk.few rp
71166486SdfrEND(bcopy)
71266458Sdfr
71366633SdfrENTRY(memcpy,3)
71466486Sdfr	mov	r14=in0 ;;
71566486Sdfr	mov	in0=in1 ;;
71666486Sdfr	mov	in1=r14
71766486Sdfr	br.cond.sptk.few bcopy
71866486SdfrEND(memcpy)
71966486Sdfr
72066633SdfrENTRY(copyin, 3)
72185682Sdfr	.prologue
722115084Smarcel	.regstk	3, 3, 3, 0
72385682Sdfr	.save	ar.pfs,loc0
724115084Smarcel	alloc	loc0=ar.pfs,3,3,3,0
72585682Sdfr	.save	rp,loc1
72666486Sdfr	mov	loc1=rp
72785682Sdfr	.body
72866458Sdfr
729219741Smarcel	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
73066486Sdfr	;;
73167020Sdfr	cmp.geu	p6,p0=in0,loc2			// is in user space.
73266486Sdfr	;;
73366486Sdfr(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
734246715Smarcel	ld8.acq	r15=[r13]
73566486Sdfr	movl	r14=copyerr			// set up fault handler.
73666486Sdfr	;;
73783366Sjulian	add	r15=TD_PCB,r15			// find pcb
73866486Sdfr	;;
73966486Sdfr	ld8	r15=[r15]
74066486Sdfr	;;
74183366Sjulian	add	loc2=PCB_ONFAULT,r15
74266486Sdfr	;;
74366486Sdfr	st8	[loc2]=r14
74466486Sdfr	;;
74566486Sdfr	mov	out0=in0
74666486Sdfr	mov	out1=in1
74766486Sdfr	mov	out2=in2
74866486Sdfr	;;
74966486Sdfr	br.call.sptk.few rp=bcopy		// do the copy.
75066486Sdfr	st8	[loc2]=r0			// kill the fault handler.
75167020Sdfr	mov	ar.pfs=loc0			// restore ar.pfs
75266486Sdfr	mov	rp=loc1				// restore ra.
75366486Sdfr	br.ret.sptk.few rp			// ret0 left over from bcopy
75466486SdfrEND(copyin)
75566458Sdfr
75666633SdfrENTRY(copyout, 3)
75785682Sdfr	.prologue
758115084Smarcel	.regstk	3, 3, 3, 0
75985682Sdfr	.save	ar.pfs,loc0
760115084Smarcel	alloc	loc0=ar.pfs,3,3,3,0
76185682Sdfr	.save	rp,loc1
76266486Sdfr	mov	loc1=rp
76385682Sdfr	.body
76466458Sdfr
765219741Smarcel	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that dest addr
76666486Sdfr	;;
76767020Sdfr	cmp.geu	p6,p0=in1,loc2			// is in user space.
76866486Sdfr	;;
76966486Sdfr(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
770246715Smarcel	ld8.acq	r15=[r13]
77166486Sdfr	movl	r14=copyerr			// set up fault handler.
77266486Sdfr	;;
77383366Sjulian	add	r15=TD_PCB,r15			// find pcb
77466486Sdfr	;;
77566486Sdfr	ld8	r15=[r15]
77666486Sdfr	;;
77783366Sjulian	add	loc2=PCB_ONFAULT,r15
77866486Sdfr	;;
77966486Sdfr	st8	[loc2]=r14
78066486Sdfr	;;
78166486Sdfr	mov	out0=in0
78266486Sdfr	mov	out1=in1
78366486Sdfr	mov	out2=in2
78466486Sdfr	;;
78566486Sdfr	br.call.sptk.few rp=bcopy		// do the copy.
78666486Sdfr	st8	[loc2]=r0			// kill the fault handler.
78767020Sdfr	mov	ar.pfs=loc0			// restore ar.pfs
78866486Sdfr	mov	rp=loc1				// restore ra.
78966486Sdfr	br.ret.sptk.few rp			// ret0 left over from bcopy
79066486SdfrEND(copyout)
79166458Sdfr
79266633SdfrENTRY(copyerr, 0)
793246715Smarcel	ld8.acq	r14=[r13] ;;
79483366Sjulian	add	r14=TD_PCB,r14 ;;		// curthread->td_addr
79566486Sdfr	ld8	r14=[r14] ;;
79683366Sjulian	add	r14=PCB_ONFAULT,r14 ;;		// &curthread->td_pcb->pcb_onfault
79766486Sdfr	st8	[r14]=r0			// reset fault handler
79866458Sdfr
79966486Sdfr	mov	ret0=EFAULT			// return EFAULT
80066486Sdfr	br.ret.sptk.few rp
80166486SdfrEND(copyerr)
802121410Smarcel
803134287Smarcel#if defined(GPROF)
804134287Smarcel/*
805134287Smarcel * Important registers:
806134287Smarcel *      r8      structure return address
807134287Smarcel *      rp      our return address
808134287Smarcel *      in0     caller's ar.pfs
809134287Smarcel *      in1     caller's gp
810134287Smarcel *      in2     caller's rp
811134287Smarcel *      in3     GOT entry
812134287Smarcel *      ar.pfs  our pfs
813134287Smarcel */
814134287SmarcelENTRY_NOPROFILE(_mcount, 4)
815134287Smarcel	alloc		loc0 = ar.pfs, 4, 3, 2, 0
816134287Smarcel	mov		loc1 = r8
817134287Smarcel	mov		loc2 = rp
818134287Smarcel	;;
819134287Smarcel	mov		out0 = in2
820134287Smarcel	mov		out1 = rp
821134287Smarcel	br.call.sptk	rp = __mcount
822134287Smarcel	;;
823134287Smarcel1:
824134287Smarcel	mov		gp = in1
825134287Smarcel	mov		r14 = ip
826134287Smarcel	mov		b7 = loc2
827134287Smarcel	;;
828134287Smarcel	add		r14 = 2f - 1b, r14
829134287Smarcel	mov		ar.pfs = loc0
830134287Smarcel	mov		rp = in2
831134287Smarcel	;;
832134287Smarcel	mov		b7 = r14
833134287Smarcel	mov		b6 = loc2
834134287Smarcel	mov		r8 = loc1
835134287Smarcel	mov		r14 = in0
836134287Smarcel	br.ret.sptk	b7
837134287Smarcel	;;
838134287Smarcel2:
839134287Smarcel	mov		ar.pfs = r14
840134287Smarcel	br.sptk		b6
841134287Smarcel	;;
842134287SmarcelEND(_mcount)
843134287Smarcel#endif
844