support.S revision 66633
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 66633 2000-10-04 17:53:03Z 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
66ENTRY(suword, 2)
67
68	movl	r14=VM_MAXUSER_ADDRESS;;	// make sure address is ok
69	cmp.geu	p6,p0=in0,r14
70(p6)	br.dpnt.few fusufault
71
72	movl	r14=fusufault			// set up fault handler.
73	add	r15=GD_CURPROC,r13		// find curproc
74	;;
75	ld8	r15=[r15]
76	;;
77	add	r15=P_ADDR,r15			// find pcb
78	;;
79	ld8	r15=[r15]
80	;;
81	add	r15=U_PCB_ONFAULT,r15
82	;;
83	st8	[r15]=r14
84	;;
85	st8.rel	[in0]=in1			// try the store
86	;;
87	st8	[r15]=r0			// clean up
88
89	mov	ret0=r0
90	br.ret.sptk.few rp
91
92END(suword)
93
94ENTRY(subyte, 2)
95
96	movl	r14=VM_MAXUSER_ADDRESS;;	// make sure address is ok
97	cmp.geu	p6,p0=in0,r14
98(p6)	br.dpnt.few fusufault
99
100	movl	r14=fusufault			// set up fault handler.
101	add	r15=GD_CURPROC,r13		// find curproc
102	;;
103	ld8	r15=[r15]
104	;;
105	add	r15=P_ADDR,r15			// find pcb
106	;;
107	ld8	r15=[r15]
108	;;
109	add	r15=U_PCB_ONFAULT,r15
110	;;
111	st8	[r15]=r14
112	;;
113	st1.rel	[in0]=in1			// try the store
114	;;
115	st8	[r15]=r0			// clean up
116
117	mov	ret0=r0
118	br.ret.sptk.few rp
119
120END(subyte)
121
122ENTRY(fuword, 1)
123
124	movl	r14=VM_MAXUSER_ADDRESS;;	// make sure address is ok
125	cmp.geu	p6,p0=in0,r14
126(p6)	br.dpnt.few fusufault
127
128	movl	r14=fusufault			// set up fault handler.
129	add	r15=GD_CURPROC,r13		// find curproc
130	;;
131	ld8	r15=[r15]
132	;;
133	add	r15=P_ADDR,r15			// find pcb
134	;;
135	ld8	r15=[r15]
136	;;
137	add	r15=U_PCB_ONFAULT,r15
138	;;
139	st8	[r15]=r14
140	;;
141	ld8.acq	ret0=[in0]			// try the fetch
142	;;
143	st8	[r15]=r0			// clean up
144
145	br.ret.sptk.few rp
146
147END(fuword)
148
149ENTRY(fubyte, 1)
150
151	movl	r14=VM_MAXUSER_ADDRESS;;	// make sure address is ok
152	cmp.geu	p6,p0=in0,r14
153(p6)	br.dpnt.few fusufault
154
155	movl	r14=fusufault			// set up fault handler.
156	add	r15=GD_CURPROC,r13		// find curproc
157	;;
158	ld8	r15=[r15]
159	;;
160	add	r15=P_ADDR,r15			// find pcb
161	;;
162	ld8	r15=[r15]
163	;;
164	add	r15=U_PCB_ONFAULT,r15
165	;;
166	st8	[r15]=r14
167	;;
168	ld1.acq	ret0=[in0]			// try the fetch
169	;;
170	st8	[r15]=r0			// clean up
171
172	br.ret.sptk.few rp
173
174END(fubyte)
175
176ENTRY(suibyte, 2)
177	mov	ret0=-1
178	br.ret.sptk.few rp
179END(suibyte)
180
181ENTRY(fusufault, 0)
182	st8	[r15]=r0 ;;			// r15 points at onfault
183	mov	ret0=r0
184	br.ret.sptk.few rp
185END(fusufault)
186
187ENTRY(fswintrberr, 0)
188XENTRY(fuswintr)					/* XXX what is a 'word'? */
189XENTRY(suswintr)					/* XXX what is a 'word'? */
190	mov	ret0=-1
191	br.ret.sptk.few rp
192END(fswintrberr)
193
194/**************************************************************************/
195
196/*
197 * Copy a null-terminated string within the kernel's address space.
198 * If lenp is not NULL, store the number of chars copied in *lenp
199 *
200 * int copystr(char *from, char *to, size_t len, size_t *lenp);
201 */
202ENTRY(copystr, 4)
203	mov	r14=in2			// r14 = i = len
204	cmp.eq	p6,p0=r0,in2
205(p6)	br.cond.spnt.few 2f		// if (len == 0), bail out
206
2071:	ld1	r15=[in0],1		// read one byte
208	;;
209	st1	[in1]=r15,1		// write that byte
210	add	in2=-1,in2		// len--
211	;;
212	cmp.eq	p6,p0=r0,r15
213	cmp.ne	p7,p0=r0,in2
214	;;
215(p6)	br.cond.spnt.few 2f		// if (*from == 0), bail out
216(p7)	br.cond.sptk.few 1b		// if (len != 0) copy more
217
2182:	cmp.eq	p6,p0=r0,in3
219(p6)	br.cond.dpnt.few 3f		// if (lenp != NULL)
220	sub	r14=in2,r14		// *lenp = (i - len)
221	;;
222	st8	[in3]=r14
223
2243:	cmp.eq	p6,p0=r0,r15
225(p6)	br.cond.spnt.few 4f		// *from == '\0'; leave quietly
226
227	mov	ret0=ENAMETOOLONG	// *from != '\0'; error.
228	br.ret.sptk.few rp
229
2304:	mov	ret0=0			// return 0.
231	br.ret.sptk.few rp
232
233END(copystr)
234
235ENTRY(copyinstr, 4)
236	alloc	loc0=ar.pfs,4,3,4,0
237	mov	loc1=rp
238
239	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
240	;;
241	cmp.geu	p6,p0=in0,loc2			// is in user space.
242	;;
243(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
244	movl	r14=copyerr			// set up fault handler.
245	add	r15=GD_CURPROC,r13		// find curproc
246	;;
247	ld8	r15=[r15]
248	;;
249	add	r15=P_ADDR,r15			// find pcb
250	;;
251	ld8	r15=[r15]
252	;;
253	add	loc2=U_PCB_ONFAULT,r15
254	;;
255	st8	[loc2]=r14
256	;;
257	mov	out0=in0
258	mov	out1=in1
259	mov	out2=in2
260	mov	out3=in3
261	;;
262	br.call.sptk.few rp=copystr		// do the copy.
263	st8	[loc2]=r0			// kill the fault handler.
264	mov	rp=loc1				// restore ra.
265	br.ret.sptk.few rp			// ret0 left over from copystr
266
267END(copyinstr)
268
269ENTRY(copyoutstr, 4)
270	alloc	loc0=ar.pfs,4,3,4,0
271	mov	loc1=rp
272
273	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that dest addr
274	;;
275	cmp.geu	p6,p0=in1,loc2			// is in user space.
276	;;
277(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
278	movl	r14=copyerr			// set up fault handler.
279	add	r15=GD_CURPROC,r13		// find curproc
280	;;
281	ld8	r15=[r15]
282	;;
283	add	r15=P_ADDR,r15			// find pcb
284	;;
285	ld8	r15=[r15]
286	;;
287	add	loc2=U_PCB_ONFAULT,r15
288	;;
289	st8	[loc2]=r14
290	;;
291	mov	out0=in0
292	mov	out1=in1
293	mov	out2=in2
294	mov	out3=in3
295	;;
296	br.call.sptk.few rp=copystr		// do the copy.
297	st8	[loc2]=r0			// kill the fault handler.
298	mov	rp=loc1				// restore ra.
299	br.ret.sptk.few rp			// ret0 left over from copystr
300
301END(copyoutstr)
302
303/*
304 * Not the fastest bcopy in the world.
305 */
306ENTRY(bcopy, 3)
307XENTRY(ovbcopy)
308
309	mov	ret0=r0				// return zero for copy{in,out}
310	;;
311	cmp.le	p6,p0=in2,r0			// bail if len <= 0
312(p6)	br.ret.spnt.few rp
313
314	sub	r14=in1,in0 ;;			// check for overlap
315	cmp.ltu	p6,p0=r14,in2			// dst-src < len
316(p6)	br.cond.spnt.few 5f
317
318	extr.u	r14=in0,0,3			// src & 7
319	extr.u	r15=in1,0,3 ;;			// dst & 7
320	cmp.eq	p6,p0=r14,r15			// different alignment?
321(p6)	br.cond.spnt.few 2f			// branch if same alignment
322
3231:	ld1	r14=[in0],1 ;;			// copy bytewise
324	st1	[in1]=r14,1
325	add	in2=-1,in2 ;;			// len--
326	cmp.ne	p6,p0=r0,in2
327(p6)	br.cond.dptk.few 1b			// loop
328	br.ret.sptk.few rp			// done
329
3302:	cmp.eq	p6,p0=r14,r0			// aligned?
331(p6)	br.cond.sptk.few 4f
332
3333:	ld1	r14=[in0],1 ;;			// copy bytewise
334	st1	[in1]=r14,1
335	extr.u	r15=in0,0,3			// src & 7
336	add	in2=-1,in2 ;;			// len--
337	cmp.eq	p6,p0=r0,in2			// done?
338	cmp.eq	p7,p0=r0,r15 ;;			// aligned now?
339(p6)	br.ret.spnt.few rp			// return if done
340(p7)	br.cond.spnt.few 4f			// go to main copy
341	br.cond.sptk.few 3b			// more bytes to copy
342
343	// At this point, in2 is non-zero
344
3454:	mov	r14=8 ;;
346	cmp.ltu	p6,p0=in2,r14 ;;		// len < 8?
347(p6)	br.cond.spnt.few 1b			// byte copy the end
348	ld8	r15=[in0],8 ;;			// copy word
349	st8	[in1]=r15,8
350	add	in2=-8,in2 ;;			// len -= 8
351	cmp.ne	p6,p0=r0,in2			// done?
352(p6)	br.cond.spnt.few 4b			// again
353
354	br.ret.sptk.few rp			// return
355
356	// Don't bother optimising overlap case
357
3585:	add	in0=in0,in2
359	add	in1=in1,in2 ;;
360	add	in0=-1,in0
361	add	in1=-1,in1 ;;
362
3636:	ld1	r14=[in0],-1 ;;
364	st1	[in1]=r14,-1
365	add	in2=-1,in2 ;;
366	cmp.ne	p6,p0=r0,in2
367(p6)	br.cond.spnt.few 6b
368
369	br.ret.sptk.few rp
370
371END(bcopy)
372
373ENTRY(memcpy,3)
374
375	mov	r14=in0 ;;
376	mov	in0=in1 ;;
377	mov	in1=r14
378	br.cond.sptk.few bcopy
379
380END(memcpy)
381
382ENTRY(copyin, 3)
383
384	alloc	loc0=ar.pfs,3,3,3,0
385	mov	loc1=rp
386
387	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that src addr
388	;;
389	cmp.ltu	p6,p0=in0,loc2			// is in user space.
390	;;
391(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
392	movl	r14=copyerr			// set up fault handler.
393	add	r15=GD_CURPROC,r13		// find curproc
394	;;
395	ld8	r15=[r15]
396	;;
397	add	r15=P_ADDR,r15			// find pcb
398	;;
399	ld8	r15=[r15]
400	;;
401	add	loc2=U_PCB_ONFAULT,r15
402	;;
403	st8	[loc2]=r14
404	;;
405	mov	out0=in0
406	mov	out1=in1
407	mov	out2=in2
408	;;
409	br.call.sptk.few rp=bcopy		// do the copy.
410	st8	[loc2]=r0			// kill the fault handler.
411	mov	rp=loc1				// restore ra.
412	br.ret.sptk.few rp			// ret0 left over from bcopy
413
414END(copyin)
415
416ENTRY(copyout, 3)
417
418	alloc	loc0=ar.pfs,3,3,3,0
419	mov	loc1=rp
420
421	movl	loc2=VM_MAXUSER_ADDRESS		// make sure that dest addr
422	;;
423	cmp.ltu	p6,p0=in1,loc2			// is in user space.
424	;;
425(p6)	br.cond.spnt.few copyerr		// if it's not, error out.
426	movl	r14=copyerr			// set up fault handler.
427	add	r15=GD_CURPROC,r13		// find curproc
428	;;
429	ld8	r15=[r15]
430	;;
431	add	r15=P_ADDR,r15			// find pcb
432	;;
433	ld8	r15=[r15]
434	;;
435	add	loc2=U_PCB_ONFAULT,r15
436	;;
437	st8	[loc2]=r14
438	;;
439	mov	out0=in0
440	mov	out1=in1
441	mov	out2=in2
442	;;
443	br.call.sptk.few rp=bcopy		// do the copy.
444	st8	[loc2]=r0			// kill the fault handler.
445	mov	rp=loc1				// restore ra.
446	br.ret.sptk.few rp			// ret0 left over from bcopy
447
448END(copyout)
449
450ENTRY(copyerr, 0)
451
452	add	r14=GD_CURPROC,r13 ;;		// find curproc
453	ld8	r14=[r14] ;;
454	add	r14=P_ADDR,r14 ;;		// curproc->p_addr
455	ld8	r14=[r14] ;;
456	add	r14=U_PCB_ONFAULT,r14 ;;	// &curproc->p_addr->u_pcb.pcb_onfault
457	st8	[r14]=r0			// reset fault handler
458
459	mov	ret0=EFAULT			// return EFAULT
460	br.ret.sptk.few rp
461
462END(copyerr)
463
464/**************************************************************************/
465
466/*
467 * Kernel setjmp and longjmp.  Rather minimalist.
468 *
469 *	longjmp(label_t *a)
470 * will generate a "return (1)" from the last call to
471 *	setjmp(label_t *a)
472 * by restoring registers from the stack,
473 */
474
475
476ENTRY(setjmp, 1)
477#if 0
478	LDGP(pv)
479
480	stq	ra, (0 * 8)(a0)			/* return address */
481	stq	s0, (1 * 8)(a0)			/* callee-saved registers */
482	stq	s1, (2 * 8)(a0)
483	stq	s2, (3 * 8)(a0)
484	stq	s3, (4 * 8)(a0)
485	stq	s4, (5 * 8)(a0)
486	stq	s5, (6 * 8)(a0)
487	stq	s6, (7 * 8)(a0)
488	stq	sp, (8 * 8)(a0)
489
490	ldiq	t0, 0xbeeffedadeadbabe		/* set magic number */
491	stq	t0, (9 * 8)(a0)
492
493	mov	zero, v0			/* return zero */
494	RET
495#endif
496END(setjmp)
497
498ENTRY(longjmp, 1)
499#if 0
500	LDGP(pv)
501
502	ldiq	t0, 0xbeeffedadeadbabe		/* check magic number */
503	ldq	t1, (9 * 8)(a0)
504	cmpeq	t0, t1, t0
505	beq	t0, longjmp_botch		/* if bad, punt */
506
507	ldq	ra, (0 * 8)(a0)			/* return address */
508	ldq	s0, (1 * 8)(a0)			/* callee-saved registers */
509	ldq	s1, (2 * 8)(a0)
510	ldq	s2, (3 * 8)(a0)
511	ldq	s3, (4 * 8)(a0)
512	ldq	s4, (5 * 8)(a0)
513	ldq	s5, (6 * 8)(a0)
514	ldq	s6, (7 * 8)(a0)
515	ldq	sp, (8 * 8)(a0)
516
517	ldiq	v0, 1
518	RET
519
520longjmp_botch:
521	lda	a0, longjmp_botchmsg
522	mov	ra, a1
523	CALL(panic)
524	call_pal PAL_bugchk
525
526	.data
527longjmp_botchmsg:
528	.asciz	"longjmp botch from %p"
529	.text
530#endif
531END(longjmp)
532