support.S revision 66486
1/*-
2 * Copyright (c) 1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/ia64/ia64/support.S 66486 2000-09-30 17:48:44Z dfr $
27 */
28/*
29 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
30 * All rights reserved.
31 *
32 * Author: Chris G. Demetriou
33 *
34 * Permission to use, copy, modify and distribute this software and
35 * its documentation is hereby granted, provided that both the copyright
36 * notice and this permission notice appear in all copies of the
37 * software, derivative works or modified versions, and any portions
38 * thereof, and that both notices appear in supporting documentation.
39 *
40 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
41 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
42 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 *
44 * Carnegie Mellon requests users of this software to return to
45 *
46 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
47 *  School of Computer Science
48 *  Carnegie Mellon University
49 *  Pittsburgh PA 15213-3890
50 *
51 * any improvements or extensions that they make and grant Carnegie the
52 * rights to redistribute these changes.
53 */
54
55#include <machine/asm.h>
56#include <assym.s>
57
58	.text
59
60/**************************************************************************/
61
62/*
63 * fu{byte,word} : fetch a byte (word) from user memory
64 */
65
66LEAF(suword, 1)
67#if 0
68	LDGP(pv)
69
70	ldiq	t0, VM_MAXUSER_ADDRESS /* verify address validity */
71	cmpult	a0, t0, t1
72	beq	t1, fusufault
73
74	lda	t0, fusufault		/* trap faults */
75	ldq	t2, curproc
76	ldq	t2, P_ADDR(t2)
77	stq	t0, U_PCB_ONFAULT(t2)
78
79	stq	a1, 0(a0)		/* try the store */
80
81	stq	zero, U_PCB_ONFAULT(t2)	/* clean up */
82
83	mov	zero, v0
84	RET
85#endif
86END(suword)
87
88LEAF(subyte, 1)
89#if 0
90	LDGP(pv)
91
92	ldiq	t0, VM_MAXUSER_ADDRESS /* verify address validity */
93	cmpult	a0, t0, t1
94	beq	t1, fusufault
95
96	lda	t0, fusufault		/* trap faults */
97	ldq	t2, curproc
98	ldq	t2, P_ADDR(t2)
99	stq	t0, U_PCB_ONFAULT(t2)
100
101	zap	a1, 0xfe, a1		/* mask off the byte to store */
102	insbl	a1, a0, a1		/* shift it to the right place */
103	ldq_u	t0, 0(a0)		/* read the qword to store it in */
104	mskbl	t0, a0, t0		/* make a place for our byte */
105	or	a1, t0, a1		/* move it in */
106	stq_u	a1, 0(a0)		/* and put the byte back */
107
108	stq	zero, U_PCB_ONFAULT(t2)	/* clean up */
109
110	mov	zero, v0
111	RET
112#endif
113END(subyte)
114
115LEAF(fuword, 1)
116#if 0
117	LDGP(pv)
118
119	ldiq	t0, VM_MAXUSER_ADDRESS /* verify address validity */
120	cmpult	a0, t0, t1
121	beq	t1, fusufault
122
123	lda	t0, fusufault		/* trap faults */
124	ldq	t2, curproc
125	ldq	t2, P_ADDR(t2)
126	stq	t0, U_PCB_ONFAULT(t2)
127
128	ldq	v0, 0(a0)		/* try the fetch */
129
130	stq	zero, U_PCB_ONFAULT(t2)	/* clean up */
131
132	RET
133#endif
134END(fuword)
135
136LEAF(fubyte, 1)
137#if 0
138	LDGP(pv)
139
140	ldiq	t0, VM_MAXUSER_ADDRESS /* verify address validity */
141	cmpult	a0, t0, t1
142	beq	t1, fusufault
143
144	lda	t0, fusufault		/* trap faults */
145	ldq	t2, curproc
146	ldq	t2, P_ADDR(t2)
147	stq	t0, U_PCB_ONFAULT(t2)
148
149	ldq_u	v0, 0(a0)		/* get the word containing our byte */
150	extbl	v0, a0, v0		/* extract the byte */
151
152	stq	zero, U_PCB_ONFAULT(t2)	/* clean up */
153
154	RET
155#endif
156END(fubyte)
157
158LEAF(suibyte, 2)
159#if 0
160	ldiq	v0, -1
161	RET
162#endif
163	END(suibyte)
164
165	LEAF(fusufault, 0)
166#if 0
167	ldq	t0, curproc
168	ldq	t0, P_ADDR(t0)
169	stq	zero, U_PCB_ONFAULT(t0)
170	ldiq	v0, -1
171	RET
172#endif
173END(fusufault)
174
175LEAF(fswintrberr, 0)
176XLEAF(fuswintr)					/* XXX what is a 'word'? */
177XLEAF(suswintr)					/* XXX what is a 'word'? */
178#if 0
179	LDGP(pv)
180	ldiq	v0, -1
181	RET
182#endif
183END(fswintrberr)
184
185/**************************************************************************/
186
187/*
188 * Copy a null-terminated string within the kernel's address space.
189 * If lenp is not NULL, store the number of chars copied in *lenp
190 *
191 * int copystr(char *from, char *to, size_t len, size_t *lenp);
192 */
193LEAF(copystr, 4)
194	mov	r14=in2			// r14 = i = len
195	cmp.eq	p6,p0=r0,in2
196(p6)	br.cond.spnt.few 2f		// if (len == 0), bail out
197
1981:	ld1	r15=[in0],1		// read one byte
199	;;
200	st1	[in1]=r15,1		// write that byte
201	add	in2=-1,in2		// len--
202	;;
203	cmp.eq	p6,p0=r0,r15
204	cmp.ne	p7,p0=r0,in2
205	;;
206(p6)	br.cond.spnt.few 2f		// if (*from == 0), bail out
207(p7)	br.cond.sptk.few 1b		// if (len != 0) copy more
208
2092:	cmp.eq	p6,p0=r0,in3
210(p6)	br.cond.dpnt.few 3f		// if (lenp != NULL)
211	sub	r14=in2,r14		// *lenp = (i - len)
212	;;
213	st8	[in3]=r14
214
2153:	cmp.eq	p6,p0=r0,r15
216(p6)	br.cond.spnt.few 4f		// *from == '\0'; leave quietly
217
218	mov	ret0=ENAMETOOLONG	// *from != '\0'; error.
219	br.ret.sptk.few rp
220
2214:	mov	ret0=0			// return 0.
222	br.ret.sptk.few rp
223
224END(copystr)
225
226NESTED(copyinstr, 4)
227	alloc	loc0=ar.pfs,4,3,4,0
228	mov	loc1=rp
229
230	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
231	;;
232	cmp.ltu	p6,p0=in0,loc2			// is in user space.
233	;;
234(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
235	movl	r14=copyerr			// set up fault handler.
236	add	r15=GD_CURPROC,r13		// find curproc
237	;;
238	ld8	r15=[r15]
239	;;
240	add	r15=P_ADDR,r15			// find pcb
241	;;
242	ld8	r15=[r15]
243	;;
244	add	loc2=U_PCB_ONFAULT,r15
245	;;
246	st8	[loc2]=r14
247	;;
248	mov	out0=in0
249	mov	out1=in1
250	mov	out2=in2
251	mov	out3=in3
252	;;
253	br.call.sptk.few rp=copystr		// do the copy.
254	st8	[loc2]=r0			// kill the fault handler.
255	mov	rp=loc1				// restore ra.
256	br.ret.sptk.few rp			// ret0 left over from copystr
257
258END(copyinstr)
259
260NESTED(copyoutstr, 4)
261	alloc	loc0=ar.pfs,4,3,4,0
262	mov	loc1=rp
263
264	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that dest addr
265	;;
266	cmp.ltu	p6,p0=in1,loc2			// is in user space.
267	;;
268(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
269	movl	r14=copyerr			// set up fault handler.
270	add	r15=GD_CURPROC,r13		// find curproc
271	;;
272	ld8	r15=[r15]
273	;;
274	add	r15=P_ADDR,r15			// find pcb
275	;;
276	ld8	r15=[r15]
277	;;
278	add	loc2=U_PCB_ONFAULT,r15
279	;;
280	st8	[loc2]=r14
281	;;
282	mov	out0=in0
283	mov	out1=in1
284	mov	out2=in2
285	mov	out3=in3
286	;;
287	br.call.sptk.few rp=copystr		// do the copy.
288	st8	[loc2]=r0			// kill the fault handler.
289	mov	rp=loc1				// restore ra.
290	br.ret.sptk.few rp			// ret0 left over from copystr
291
292END(copyoutstr)
293
294/*
295 * Not the fastest bcopy in the world.
296 */
297LEAF(bcopy, 3)
298XLEAF(ovbcopy)
299
300	mov	ret0=r0				// return zero for copy{in,out}
301	;;
302	cmp.le	p6,p0=in2,r0			// bail if len <= 0
303(p6)	br.ret.spnt.few rp
304
305	sub	r14=in1,in0 ;;			// check for overlap
306	cmp.ltu	p6,p0=r14,in2			// dst-src < len
307(p6)	br.cond.spnt.few 5f
308
309	extr.u	r14=in0,0,3			// src & 7
310	extr.u	r15=in1,0,3 ;;			// dst & 7
311	cmp.eq	p6,p0=r14,r15			// different alignment?
312(p6)	br.cond.spnt.few 2f			// branch if same alignment
313
3141:	ld1	r14=[in0],1 ;;			// copy bytewise
315	st1	[in1]=r14,1
316	add	in2=-1,in2 ;;			// len--
317	cmp.ne	p6,p0=r0,in2
318(p6)	br.cond.dptk.few 1b			// loop
319	br.ret.sptk.few rp			// done
320
3212:	cmp.eq	p6,p0=r14,r0			// aligned?
322(p6)	br.cond.sptk.few 4f
323
3243:	ld1	r14=[in0],1 ;;			// copy bytewise
325	st1	[in1]=r14,1
326	extr.u	r15=in0,0,3			// src & 7
327	add	in2=-1,in2 ;;			// len--
328	cmp.eq	p6,p0=r0,in2			// done?
329	cmp.eq	p7,p0=r0,r15 ;;			// aligned now?
330(p6)	br.ret.spnt.few rp			// return if done
331(p7)	br.cond.spnt.few 4f			// go to main copy
332	br.cond.sptk.few 3b			// more bytes to copy
333
334	// At this point, in2 is non-zero
335
3364:	mov	r14=8 ;;
337	cmp.ltu	p6,p0=in2,r14 ;;		// len < 8?
338(p6)	br.cond.spnt.few 1b			// byte copy the end
339	ld8	r15=[in0],8 ;;			// copy word
340	st8	[in1]=r15,8
341	add	in2=-8,in2 ;;			// len -= 8
342	cmp.ne	p6,p0=r0,in2			// done?
343(p6)	br.cond.spnt.few 4b			// again
344
345	br.ret.sptk.few rp			// return
346
347	// Don't bother optimising overlap case
348
3495:	add	in0=in0,in2
350	add	in1=in1,in2 ;;
351	add	in0=-1,in0
352	add	in1=-1,in1 ;;
353
3546:	ld1	r14=[in0],-1 ;;
355	st1	[in1]=r14,-1
356	add	in2=-1,in2 ;;
357	cmp.ne	p6,p0=r0,in2
358(p6)	br.cond.spnt.few 6b
359
360	br.ret.sptk.few rp
361
362END(bcopy)
363
364LEAF(memcpy,3)
365
366	mov	r14=in0 ;;
367	mov	in0=in1 ;;
368	mov	in1=r14
369	br.cond.sptk.few bcopy
370
371END(memcpy)
372
373NESTED(copyin, 3)
374
375	alloc	loc0=ar.pfs,3,3,3,0
376	mov	loc1=rp
377
378	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
379	;;
380	cmp.ltu	p6,p0=in0,loc2			// is in user space.
381	;;
382(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
383	movl	r14=copyerr			// set up fault handler.
384	add	r15=GD_CURPROC,r13		// find curproc
385	;;
386	ld8	r15=[r15]
387	;;
388	add	r15=P_ADDR,r15			// find pcb
389	;;
390	ld8	r15=[r15]
391	;;
392	add	loc2=U_PCB_ONFAULT,r15
393	;;
394	st8	[loc2]=r14
395	;;
396	mov	out0=in0
397	mov	out1=in1
398	mov	out2=in2
399	;;
400	br.call.sptk.few rp=bcopy		// do the copy.
401	st8	[loc2]=r0			// kill the fault handler.
402	mov	rp=loc1				// restore ra.
403	br.ret.sptk.few rp			// ret0 left over from bcopy
404
405END(copyin)
406
407NESTED(copyout, 3)
408
409	alloc	loc0=ar.pfs,3,3,3,0
410	mov	loc1=rp
411
412	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that dest addr
413	;;
414	cmp.ltu	p6,p0=in1,loc2			// is in user space.
415	;;
416(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
417	movl	r14=copyerr			// set up fault handler.
418	add	r15=GD_CURPROC,r13		// find curproc
419	;;
420	ld8	r15=[r15]
421	;;
422	add	r15=P_ADDR,r15			// find pcb
423	;;
424	ld8	r15=[r15]
425	;;
426	add	loc2=U_PCB_ONFAULT,r15
427	;;
428	st8	[loc2]=r14
429	;;
430	mov	out0=in0
431	mov	out1=in1
432	mov	out2=in2
433	;;
434	br.call.sptk.few rp=bcopy		// do the copy.
435	st8	[loc2]=r0			// kill the fault handler.
436	mov	rp=loc1				// restore ra.
437	br.ret.sptk.few rp			// ret0 left over from bcopy
438
439END(copyout)
440
441LEAF(copyerr, 0)
442
443	add	r14=GD_CURPROC,r13 ;;		// find curproc
444	ld8	r14=[r14] ;;
445	add	r14=P_ADDR,r14 ;;		// curproc->p_addr
446	ld8	r14=[r14] ;;
447	add	r14=U_PCB_ONFAULT,r14 ;;	// &curproc->p_addr->u_pcb.pcb_onfault
448	st8	[r14]=r0			// reset fault handler
449
450	mov	ret0=EFAULT			// return EFAULT
451	br.ret.sptk.few rp
452
453END(copyerr)
454
455/**************************************************************************/
456
457/*
458 * Kernel setjmp and longjmp.  Rather minimalist.
459 *
460 *	longjmp(label_t *a)
461 * will generate a "return (1)" from the last call to
462 *	setjmp(label_t *a)
463 * by restoring registers from the stack,
464 */
465
466
467LEAF(setjmp, 1)
468#if 0
469	LDGP(pv)
470
471	stq	ra, (0 * 8)(a0)			/* return address */
472	stq	s0, (1 * 8)(a0)			/* callee-saved registers */
473	stq	s1, (2 * 8)(a0)
474	stq	s2, (3 * 8)(a0)
475	stq	s3, (4 * 8)(a0)
476	stq	s4, (5 * 8)(a0)
477	stq	s5, (6 * 8)(a0)
478	stq	s6, (7 * 8)(a0)
479	stq	sp, (8 * 8)(a0)
480
481	ldiq	t0, 0xbeeffedadeadbabe		/* set magic number */
482	stq	t0, (9 * 8)(a0)
483
484	mov	zero, v0			/* return zero */
485	RET
486#endif
487END(setjmp)
488
489LEAF(longjmp, 1)
490#if 0
491	LDGP(pv)
492
493	ldiq	t0, 0xbeeffedadeadbabe		/* check magic number */
494	ldq	t1, (9 * 8)(a0)
495	cmpeq	t0, t1, t0
496	beq	t0, longjmp_botch		/* if bad, punt */
497
498	ldq	ra, (0 * 8)(a0)			/* return address */
499	ldq	s0, (1 * 8)(a0)			/* callee-saved registers */
500	ldq	s1, (2 * 8)(a0)
501	ldq	s2, (3 * 8)(a0)
502	ldq	s3, (4 * 8)(a0)
503	ldq	s4, (5 * 8)(a0)
504	ldq	s5, (6 * 8)(a0)
505	ldq	s6, (7 * 8)(a0)
506	ldq	sp, (8 * 8)(a0)
507
508	ldiq	v0, 1
509	RET
510
511longjmp_botch:
512	lda	a0, longjmp_botchmsg
513	mov	ra, a1
514	CALL(panic)
515	call_pal PAL_bugchk
516
517	.data
518longjmp_botchmsg:
519	.asciz	"longjmp botch from %p"
520	.text
521#endif
522END(longjmp)
523