xref: /netbsd/sys/arch/vax/vax/emulate.S (revision bf9ec67e)
1/*	$NetBSD: emulate.S,v 1.2 2002/02/24 01:04:26 matt Exp $ */
2/*
3 * Copyright (c) 1986, 1987 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Mt. Xinu.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *	@(#)emulate.s	7.5 (Berkeley) 6/28/90
38 */
39
40#include <machine/asm.h>
41
42/*
43 * String instruction emulation - MicroVAX only.  These routines are called
44 * from locore.s when an "emulate" fault occurs on the MicroVAX.  They are
45 * called with the stack set up as follows:
46 *
47 *	  (%sp): Return address of trap handler
48 *	 4(%sp): Instruction Opcode	(also holds PSL result from emulator)
49 *	 8(%sp): Instruction PC
50 *	12(%sp): Operand 1
51 *	16(%sp): Operand 2
52 *	20(%sp): Operand 3
53 *	24(%sp): Operand 4
54 *	28(%sp): Operand 5
55 *	32(%sp): Operand 6
56 *	36(%sp): old Register 11
57 *	40(%sp): old Register 10
58 *	44(%sp): Return PC
59 *	48(%sp): Return PSL
60 *	52(%sp): TOS before instruction
61 *
62 * R11 and %r10 are available for use.  If any routine needs to use %r9-%r1
63 * they need to save them first (unless those registers are SUPPOSED to be
64 * messed with by the "instruction").  These routines leave their results
65 * in registers 0-5 explicitly, as needed, and use the macros defined below
66 * to link up with calling routine.
67 */
68
69#define return		rsb
70#define savepsl		movpsl	4(%sp)
71#define setpsl(reg)	movl	reg,4(%sp)
72#define overflowpsl	movl	$2,4(%sp)
73#define arg1		12(%sp)
74#define arg2		16(%sp)
75#define arg3		20(%sp)
76#define arg4		24(%sp)
77#define arg5		28(%sp)
78#define arg6		32(%sp)
79#define argub(num,reg)	movzbl	8+4*num(%sp),reg
80#define arguw(num,reg)	movzwl	8+4*num(%sp),reg
81#define argul(num,reg)	movl	8+4*num(%sp),reg
82#define argb(num,reg)	cvtbl	8+4*num(%sp),reg
83#define argw(num,reg)	cvtwl	8+4*num(%sp),reg
84#define argl(num,reg)	movl	8+4*num(%sp),reg
85#define toarg(reg,num)	movl	reg,8+4*num(%sp)
86
87
88	.text
89	.align	1
90ALTENTRY(EMcrc)
91	argl(1,%r11)		# (1) table address == %r11
92	argl(2,%r0)		# (2) initial crc == %r0
93	argl(4,%r3)		# (4) source address == %r3
94	arguw(3,%r2)		# (3) source length == %r2
95	jeql	Lcrc_out
96Lcrc_loop:
97	xorb2	(%r3)+,%r0
98	extzv	$0,$4,%r0,%r10
99	extzv	$4,$28,%r0,%r1
100	xorl3	%r1,(%r11)[%r10],%r0
101	extzv	$0,$4,%r0,%r10
102	extzv	$4,$28,%r0,%r1
103	xorl3	%r1,(%r11)[%r10],%r0
104	sobgtr	%r2,Lcrc_loop
105	tstl	%r0
106Lcrc_out:
107	savepsl
108	clrl	%r1
109	return
110
111
112	.align	1
113ALTENTRY(EMmovtc)
114	arguw(1,%r0)		# (1) source length == %r0
115	argl(2,%r1)		# (2) source address == %r1
116	argub(3,%r11)		# (3) fill character == %r11
117	argl(4,%r3)		# (4) table address == %r3
118	argl(6,%r5)		# (6) destination address == %r5
119	arguw(5,%r4)		# (5) destination length == %r4
120	jeql	Lmovtc_out
121Lmovtc_loop:
122	tstl	%r0
123	jeql	Lmovtc_2loop
124	movzbl	(%r1)+,%r2
125	movb	(%r3)[%r2],(%r5)+
126	decl	%r0
127	sobgtr	%r4,Lmovtc_loop
128	jbr	Lmovtc_out
129Lmovtc_2loop:
130	movb	%r11,(%r5)+
131	sobgtr	%r4,Lmovtc_2loop
132Lmovtc_out:
133	cmpl	%r4,%r0
134	savepsl
135	clrl	%r2
136	return
137
138
139	.align	1
140ALTENTRY(EMmovtuc)
141	arguw(1,%r0)		# (1) source length == %r0
142	argl(2,%r1)		# (2) source address == %r1
143	argub(3,%r11)		# (3) escape character == %r11
144	argl(4,%r3)		# (4) table address == %r3
145	argl(6,%r5)		# (6) destination address == %r5
146	arguw(5,%r4)		# (5) destination length == %r4
147	jeql	Lmovtuc_out
148Lmovtuc_loop:
149	tstl	%r0
150	jeql	Lmovtuc_out
151	movzbl	(%r1),%r2
152	movzbl	(%r3)[%r2],%r2
153	cmpl	%r2,%r11
154	jeql	Lmovtuc_out
155	movzbl	(%r1)+,%r2
156	movb	(%r3)[%r2],(%r5)+
157	decl	%r0
158	sobgtr	%r4,Lmovtuc_loop
159Lmovtuc_out:
160	cmpl	%r4,%r0
161	savepsl
162	clrl	%r2
163	return
164
165
166	.align	1
167ALTENTRY(EMmatchc)
168	argl(2,%r10)		# (2) substring address == %r10
169	arguw(3,%r2)		# (3) source length == %r2
170	argl(4,%r3)		# (4) source address == %r3
171	arguw(1,%r11)		# (1) substring length == %r11
172	jeql	Lmatchc_out	# temp source address == %r1
173	addl2	%r10,%r11		# temp substring address == %r0
174	tstl	%r2
175	jeql	Lmatchc_out
176Lmatchc_loop:
177	cmpb	(%r10),(%r3)
178	jneq	Lmatchc_fail
179	movl	%r3,%r1
180	movl	%r10,%r0
181Lmatchc_2loop:
182	cmpl	%r0,%r11
183	jeql	Lmatchc_succ
184	cmpb	(%r0)+,(%r1)+
185	jeql	Lmatchc_2loop
186Lmatchc_fail:
187	incl	%r3
188	sobgtr	%r2,Lmatchc_loop
189	movl	%r10,%r1
190	subl3	%r10,%r11,%r0
191	jbr	Lmatchc_out
192Lmatchc_succ:
193	movl	%r1,%r3
194	movl	%r11,%r1
195	clrl	%r0
196Lmatchc_out:
197	savepsl
198	return
199
200
201	.align	1
202ALTENTRY(EMspanc)
203	argl(2,%r1)		# (2) string address == %r1
204	argub(4,%r2)		# (4) character-mask == %r2
205	argl(3,%r3)		# (3) table address == %r3
206	arguw(1,%r0)		# (1) string length == %r0
207	jeql	Lspanc_out
208Lspanc_loop:
209	movzbl	(%r1),%r11
210	mcomb	(%r3)[%r11],%r11
211	bicb3	%r11,%r2,%r11
212	jeql	Lspanc_out
213	incl	%r1
214	sobgtr	%r0,Lspanc_loop
215Lspanc_out:
216	savepsl
217	clrl	%r2
218	return
219
220
221	.align	1
222ALTENTRY(EMscanc)
223	argl(2,%r1)		# (2) string address == %r1
224	argub(4,%r2)		# (4) character-mask == %r2
225	argl(3,%r3)		# (3) table address == %r3
226	arguw(1,%r0)		# (1) string length == %r0
227	jeql	Lscanc_out
228Lscanc_loop:
229	movzbl	(%r1),%r11
230	mcomb	(%r3)[%r11],%r11
231	bicb3	%r11,%r2,%r11
232	jneq	Lscanc_out
233	incl	%r1
234	sobgtr	%r0,Lscanc_loop
235Lscanc_out:
236	savepsl
237	clrl	%r2
238	return
239
240
241	.align	1
242ALTENTRY(EMskpc)
243	argub(1,%r11)		# (1) character == %r11
244	argl(3,%r1)		# (3) string address == %r1
245	arguw(2,%r0)		# (2) string length == %r0
246	jeql	Lskpc_out	# forget zero length strings
247Lskpc_loop:
248	cmpb	(%r1),%r11
249	jneq	Lskpc_out
250	incl	%r1
251	sobgtr	%r0,Lskpc_loop
252Lskpc_out:
253	tstl	%r0		# be sure of condition codes
254	savepsl
255	return
256
257
258	.align	1
259ALTENTRY(EMlocc)
260	argub(1,%r11)		# (1) character == %r11
261	argl(3,%r1)		# (3) string address == %r1
262	arguw(2,%r0)		# (2) string length == %r0
263	jeql	Lskpc_out	# forget zero length strings
264Llocc_loop:
265	cmpb	(%r1),%r11
266	jeql	Llocc_out
267	incl	%r1
268	sobgtr  %r0,Llocc_loop
269Llocc_out:
270	tstl	%r0		# be sure of condition codes
271	savepsl
272	return
273
274
275	.align	1
276ALTENTRY(EMcmpc3)
277	argl(2,%r1)		# (2) string1 address == %r1
278	argl(3,%r3)		# (3) string2 address == %r3
279	arguw(1,%r0)		# (1) strings length == %r0
280	jeql	Lcmpc3_out
281Lcmpc3_loop:
282	cmpb	(%r1),(%r3)
283	jneq	Lcmpc3_out
284	incl	%r1
285	incl	%r3
286	sobgtr	%r0,Lcmpc3_loop
287Lcmpc3_out:
288	savepsl
289	movl	%r0,%r2
290	return
291
292
293	.align	1
294ALTENTRY(EMcmpc5)
295	argl(2,%r1)		# (2) string1 address == %r1
296	argub(3,%r11)		# (1) fill character == %r11
297	arguw(4,%r2)		# (1) string2 length == %r2
298	argl(5,%r3)		# (3) string2 address == %r3
299	arguw(1,%r0)		# (1) string1 length == %r0
300	jeql	Lcmpc5_str2
301Lcmpc5_loop:
302	tstl	%r2
303	jeql	Lcmpc5_str1loop
304	cmpb	(%r1),(%r3)
305	jneq	Lcmpc5_out
306	incl	%r1
307	incl	%r3
308	decl	%r2
309	sobgtr	%r0,Lcmpc5_loop
310Lcmpc5_str2:
311	tstl	%r2
312	jeql	Lcmpc5_out
313Lcmpc5_str2loop:
314	cmpb	%r11,(%r3)
315	jneq	Lcmpc5_out
316	incl	%r3
317	sobgtr	%r2,Lcmpc5_str2loop
318	jbr	Lcmpc5_out
319Lcmpc5_str1loop:
320	cmpb	(%r1),%r11
321	jneq	Lcmpc5_out
322	incl	%r1
323	sobgtr	%r0,Lcmpc5_str1loop
324Lcmpc5_out:
325	savepsl
326	return
327
328
329/*
330 * Packed Decimal string operations
331 */
332
333#define POSITIVE	$12
334#define NEGATIVE	$13
335#define NEGATIVEalt	$11
336
337
338	.align	1
339ALTENTRY(EMaddp4)
340	toarg(%r9,6)		# save register %r9 in arg6 spot
341	arguw(1,%r11)		# (1) source length == %r11
342	argl(2,%r10)		# (2) source address == %r10
343	arguw(3,%r9)		# (3) destination length == %r9
344	argl(4,%r3)		# (4) destination address == %r3
345	ashl	$-1,%r11,%r11
346	addl2	%r11,%r10		# source address of LSNibble
347	incl	%r11		# source length is in bytes
348	ashl	$-1,%r9,%r9
349	addl2	%r9,%r3		# %r3 = destination address of LSNibble
350	incl	%r9		# destination length is in bytes
351	toarg(%r3,5)
352	extzv	$0,$4,(%r3),%r2	# set standard +/- indicators in destination
353	cmpl	%r2,NEGATIVE
354	jeql	L112
355	cmpl	%r2,NEGATIVEalt
356	jeql	L111
357	insv	POSITIVE,$0,$4,(%r3)
358	jbr	L112
359L111:
360	insv	NEGATIVE,$0,$4,(%r3)
361L112:
362	extzv	$0,$4,(%r10),%r2	# %r2 = standard +/- of source
363	cmpl	%r2,NEGATIVE
364	jeql	L114
365	cmpl	%r2,NEGATIVEalt
366	jeql	L113
367	movl	POSITIVE,%r2
368	jbr	L114
369L113:
370	movl	NEGATIVE,%r2
371L114:
372	cmpl	%r11,%r9		# if source is longer than destination
373	jleq	L115
374	movl	%r9,%r11		#	set source length == destination length
375L115:
376	extzv	$4,$4,(%r3),%r9	# %r9 = LSDigit of destination
377	extzv	$4,$4,(%r10),%r1	# %r1 = LSDigit of source
378	extzv	$0,$4,(%r3),%r0
379	cmpl	%r0,%r2		# if signs of operands are not equal
380	jeql	Laddp4_same	#	do a subtraction
381	clrl	%r2		# %r2 is non-zero if result is non-zero
382	subl2	%r1,%r9		# %r9 = "addition" of operands high nibble
383	jbr	L119		# jump into addition loop
384Laddp4_diff_loop:
385	decl	%r3
386	extzv	$0,$4,(%r3),%r0
387	addl2	%r0,%r1		# %r1 = carry + next (low) nibble of source
388	decl	%r10
389	extzv	$0,$4,(%r10),%r0
390	subl2	%r0,%r1		# %r1 -= next (low) nibble of destination
391	jgeq	L121		# if negative result
392	mnegl	$1,%r9		#	%r9 == carry = -1
393	addl2	$10,%r1		#	%r1 == result += 10
394	jbr	L122		# else
395L121:
396	clrl	%r9		#	%r9 == carry = 0
397L122:
398	insv	%r1,$0,$4,(%r3)	# store result low nibble
399	bisl2	%r1,%r2
400	extzv	$4,$4,(%r3),%r0
401	addl2	%r0,%r9		# %r9 = carry + next (high) nibble of source
402	extzv	$4,$4,(%r10),%r0
403	subl2	%r0,%r9		# %r9 -= next (high) nibble of destination
404L119:
405	jgeq	L117		# if negative result
406	mnegl	$1,%r1		#	%r1 == carry = -1
407	addl2	$10,%r9		#	%r9 == result += 10
408	jbr	L118		# else
409L117:
410	clrl	%r1		#	%r1 == carry = 0
411L118:
412	insv	%r9,$4,$4,(%r3)	# store result high nibble
413	bisl2	%r9,%r2		# %r2 is non-zero if result is non-zero
414	decl	%r11		# while (--source length)
415	jneq	Laddp4_diff_loop
416	argl(4,%r10)		# %r10 = address of destination MSNibble
417	jbr	Laddp4_diff_carry
418Laddp4_diff_carlop:
419	decl	%r3
420	extzv	$0,$4,(%r3),%r0
421	addl2	%r0,%r1		# %r1 == carry += next (low) nibble
422	jgeq	L127		# if less than zero
423	movl	%r1,%r9		#	%r9 == carry (must be -1)
424	movl	$9,%r1		#	%r1 == result = 9
425	jbr	L128
426L127:				# else
427	clrl	%r9		#	%r9 == carry = 0
428L128:
429	insv	%r1,$0,$4,(%r3)	# store result
430	bisl2	%r1,%r2
431	extzv	$4,$4,(%r3),%r0
432	addl2	%r0,%r9		# %r9 == carry += next (high) nibble
433	jgeq	L129		# if less than zero
434	movl	%r9,%r1		# %r1 == carry (must be -1)
435	movl	$9,%r9		# %r9 == result = 9
436	jbr	L130
437L129:
438	clrl	%r1
439L130:
440	insv	%r9,$4,$4,(%r3)	# store result
441	bisl2	%r9,%r2
442Laddp4_diff_carry:
443	cmpl	%r3,%r10
444	jneq	Laddp4_diff_carlop
445	tstl	%r1		#	if carry out of MSN then fix up result
446	jeql	Laddp4_add_done
447	argl(5,%r3)		# %r3 == address of LSN of destination
448	extzv	$0,$4,(%r3),%r0
449	cmpl	%r0,NEGATIVE	# switch sign of result
450	jneq	L132
451	insv	POSITIVE,$0,$4,(%r3)
452	jbr	L133
453L132:
454	insv	NEGATIVE,$0,$4,(%r3)
455L133:
456	extzv	$4,$4,(%r3),%r0	# normalize result (carry out of MSN into LSN)
457	subl3	%r0,$10,%r9	# %r9 = 10 - destination LSNibble
458	jbr	L134
459L137:
460	movl	$9,%r1
461Laddp4_diff_norm:
462	insv	%r9,$4,$4,(%r3)
463	cmpl	%r3,%r10		# while (not at MSNibble)
464	jeql	Laddp4_add_done
465	decl	%r3
466	extzv	$0,$4,(%r3),%r0	# low nibble = (9 + carry) - low nibble
467	subl2	%r0,%r1
468	cmpl	%r1,$9
469	jleq	L135
470	clrl	%r1
471	movl	$10,%r9
472	jbr	L136
473L135:
474	movl	$9,%r9
475L136:
476	insv	%r1,$0,$4,(%r3)
477	extzv	$4,$4,(%r3),%r0	# high nibble = (9 + carry) - high nibble
478	subl2	%r0,%r9
479L134:
480	cmpl	%r9,$9
481	jleq	L137
482	clrl	%r9
483	movl	$10,%r1
484	jbr	Laddp4_diff_norm
485
486Laddp4_same:			# operands are of the same sign
487	clrl	%r2
488	addl2	%r1,%r9
489	jbr	L139
490Laddp4_same_loop:
491	decl	%r3
492	extzv	$0,$4,(%r3),%r0
493	addl2	%r0,%r1		# %r1 == carry += next (low) nibble of dest
494	decl	%r10
495	extzv	$0,$4,(%r10),%r0
496	addl2	%r0,%r1		# %r1 += next (low) nibble of source
497	cmpl	%r1,$9		# if result > 9
498	jleq	L141
499	movl	$1,%r9		#	%r9 == carry = 1
500	subl2	$10,%r1		#	%r1 == result -= 10
501	jbr	L142
502L141:				# else
503	clrl	%r9		#	%r9 == carry = 0
504L142:
505	insv	%r1,$0,$4,(%r3)	# store result
506	bisl2	%r1,%r2
507	extzv	$4,$4,(%r10),%r0
508	addl2	%r0,%r9		# ditto for high nibble
509	extzv	$4,$4,(%r3),%r0
510	addl2	%r0,%r9
511L139:
512	cmpl	%r9,$9
513	jleq	L143
514	movl	$1,%r1
515	subl2	$10,%r9
516	jbr	L144
517L143:
518	clrl	%r1
519L144:
520	insv	%r9,$4,$4,(%r3)
521	bisl2	%r9,%r2
522	sobgtr	%r11,Laddp4_same_loop	# while (--source length)
523	argl(4,%r10)		# %r10 = destination address of MSNibble
524	jbr	Laddp4_same_carry
525Laddp4_same_cloop:
526	decl	%r3
527	extzv	$0,$4,(%r3),%r0	# propagate carry up to MSNibble of destination
528	addl2	%r0,%r1
529	cmpl	%r1,$10
530	jneq	L147
531	movl	$1,%r9
532	clrl	%r1
533	jbr	L148
534L147:
535	clrl	%r9
536L148:
537	insv	%r1,$0,$4,(%r3)
538	bisl2	%r1,%r2
539	extzv	$4,$4,(%r3),%r0
540	addl2	%r0,%r9
541	cmpl	%r9,$10
542	jneq	L149
543	movl	$1,%r1
544	clrl	%r9
545	jbr	L150
546L149:
547	clrl	%r1
548L150:
549	insv	%r9,$4,$4,(%r3)
550	bisl2	%r9,%r2
551Laddp4_same_carry:
552	cmpl	%r3,%r10
553	jneq	Laddp4_same_cloop
554
555Laddp4_add_done:
556	argl(5,%r3)		# %r3 = destination address of LSNibble
557	tstl	%r2		# if zero result
558	jneq	L151
559	savepsl			#	remember that for condition codes
560	insv	POSITIVE,$0,$4,(%r3) #	make sure sign of result is positive
561	jbr	Laddp4_out
562L151:				# else
563	extzv	$0,$4,(%r3),%r0
564	cmpl	%r0,NEGATIVE	#	if result is negative
565	jneq	Laddp4_out
566	mnegl	%r2,%r2		#		remember THAT in Cond Codes
567	savepsl
568Laddp4_out:
569	argl(4,%r3)
570	argl(2,%r1)
571	clrl	%r0
572	clrl	%r2
573	argl(6,%r9)		# restore %r9 from stack
574	return
575
576
577	.align	1
578ALTENTRY(EMmovp)
579	arguw(1,%r11)		# (1) string length == %r11
580	argl(2,%r10)		# (1) source address == %r10
581	argl(3,%r3)		# (1) destination address == %r3
582			# we will need arg2 and arg3 later
583	clrl	%r2		# %r2 == non-zero if source is non-zero
584	ashl	$-1,%r11,%r11	# length is number of bytes, not nibbles
585	jeql	Lmovp_zlen
586Lmovp_copy:
587	bisb2	(%r10),%r2	# keep track of non-zero source
588	movb	(%r10)+,(%r3)+	# move two nibbles
589	sobgtr	%r11,Lmovp_copy	# loop for length of source
590Lmovp_zlen:
591	extzv	$4,$4,(%r10),%r0	# look at least significant nibble
592	bisl2	%r0,%r2
593	extzv	$0,$4,(%r10),%r0	# check sign nibble
594	cmpl	%r0,NEGATIVEalt
595	jeql	Lmovp_neg
596	cmpl	%r0,NEGATIVE
597	jneq	Lmovp_pos
598Lmovp_neg:			# source was negative
599	mnegl	%r2,%r2
600Lmovp_pos:
601	tstl	%r2		# set condition codes
602	savepsl
603	jeql	Lmovp_zero
604	movb	(%r10),(%r3)	# move last byte if non-zero result
605	jbr	Lmovp_out
606Lmovp_zero:
607	movb	POSITIVE,(%r3)	#	otherwise, make result zero and positive
608Lmovp_out:
609	clrl	%r0
610	argl(2,%r1)
611	clrl	%r2
612	argl(3,%r3)
613	return
614
615
616/*
617 *	Definitions for Editpc instruction
618 *
619 *  Here are the commands and their corresponding hex values:
620 *
621 *	EPend		0x00
622 *	EPend_float	0x01
623 *	EPclear_signif	0x02
624 *	EPset_signif	0x03
625 *	EPstore_sign	0x04
626 *	EPload_fill	0x40
627 *	EPload_sign	0x41
628 *	EPload_plus	0x42
629 *	EPload_minus	0x43
630 *	EPinsert	0x44
631 *	EPblank_zero	0x45
632 *	EPreplace_sign	0x46
633 *	EPadjust_input	0x47
634 *	EPfill		0x80
635 *	EPmove		0x90
636 *	EPfloat		0xa0
637 *
638 *
639 *  %r4 is carved up as follows:
640 *
641 *	-------------------------------------------
642 *     |                                   N Z V C |
643 *	-------------------------------------------
644 *
645 *	fill character is stuffed into arg5 space
646 *	sign character is stuffed into arg6 space
647 */
648
649#define SIGNIFBIT	$0
650#define setsignif	bisl2	$1,%r4
651#define clsignif	bicl2	$1,%r4
652#define OVERFLOWBIT	$1
653#define setoverflow	bisl2	$2,%r4
654#define cloverflow	bicl2	$2,%r4
655#define ZEROBIT		$2
656#define setzero		bisl2	$4,%r4
657#define clzero		bicl2	$4,%r4
658#define NEGATIVEBIT	$3
659#define setnegative	bisl2	$8,%r4
660#define clnegative	bicl2	$8,%r4
661#define putfill		movb	arg5,(%r5)+
662#define setfill(reg)	movb	reg,arg5
663#define putsign		movb	arg6,(%r5)+
664#define setsign(reg)	movb	reg,arg6
665
666
667	.align	1
668ALTENTRY(EMeditpc)
669	arguw(1,%r11)		# (1) source length == %r11
670	argl(2,%r10)		# (2) source address == %r10
671	argl(3,%r3)		# (3) pattern address == %r3
672	argl(4,%r5)		# (4) destination address == %r5
673/*		# we will need arg1 and arg2 later */
674/*		# arg5 and arg6 are used for fill and sign - %r0 is free */
675	setfill($32)		# fill character is ' '
676	setsign($32)		# sign character is ' '
677	clrl	%r4		# clear flags
678	ashl	$-1,%r11,%r11	# source length / 2
679	addl3	%r11,%r10,%r2
680	extzv	$4,$4,(%r2),%r1	# %r1 == least significant nibble of source
681L169:
682	cmpl	%r2,%r10
683	jeql	L170
684	tstb	-(%r2)		# loop over source packed decimal number
685	jeql	L169
686	incl	%r1		# %r1 is non-zero if source is non-zero
687L170:
688	addl3	%r11,%r10,%r2
689	tstl	%r1
690	jeql	L172		# source is zero - set flags
691	extzv	$0,$4,(%r2),%r11
692	cmpl	%r11,NEGATIVEalt
693	jeql	L9998		# source is negative - set sign and flags
694	cmpl	%r11,NEGATIVE
695	jneq	L175
696L9998:
697	setnegative
698	setsign($45)		# sign character is '-'
699	jbr	L175
700L172:
701	setzero
702L175:
703	arguw(1,%r2)		# (1) source length == %r2
704Ledit_case:
705	movzbl	(%r3)+,%r11	# get next edit command (pattern)
706	cmpl	%r11,$128
707	jlss	L180
708	extzv	$0,$4,%r11,%r1	# command has a "count" arg - into %r1
709	ashl	$-4,%r11,%r11	# and shift over
710L180:
711	jbc	$6,%r11,L181	# "shift" those commands > 64 to 16 and up
712	subl2	$48,%r11
713L181:
714	caseb	%r11,$0,$0x18	# "do" the command
715				# %r11 is available for use, %r1 has "count" in it
716Lcaseb_label:
717	.word	Le_end - Lcaseb_label		# 00
718	.word	Le_end_float - Lcaseb_label	# 01
719	.word	Le_clear_signif - Lcaseb_label	# 02
720	.word	Le_set_signif - Lcaseb_label	# 03
721	.word	Le_store_sign - Lcaseb_label	# 04
722	.word	Le_end - Lcaseb_label		# 05
723	.word	Le_end - Lcaseb_label		# 06
724	.word	Le_end - Lcaseb_label		# 07
725	.word	Le_fill - Lcaseb_label		# 80
726	.word	Le_move - Lcaseb_label		# 90
727	.word	Le_float - Lcaseb_label		# a0
728	.word	Le_end - Lcaseb_label		# b0
729	.word	Le_end - Lcaseb_label		# c0
730	.word	Le_end - Lcaseb_label		# d0
731	.word	Le_end - Lcaseb_label		# e0
732	.word	Le_end - Lcaseb_label		# f0
733	.word	Le_load_fill - Lcaseb_label	# 40
734	.word	Le_load_sign - Lcaseb_label	# 41
735	.word	Le_load_plus - Lcaseb_label	# 42
736	.word	Le_load_minus - Lcaseb_label	# 43
737	.word	Le_insert - Lcaseb_label	# 44
738	.word	Le_blank_zero - Lcaseb_label	# 45
739	.word	Le_replace_sign - Lcaseb_label	# 46
740	.word	Le_adjust_input - Lcaseb_label	# 47
741Le_end:
742	arguw(1,%r0)
743	argl(2,%r1)
744	clrl	%r2
745	decl	%r3
746	setpsl(%r4)
747	clrl	%r4
748	return
749
750Le_end_float:
751	jbs	SIGNIFBIT,%r4,Ledit_case	# if significance not set
752	putsign				# drop in the sign
753					# fall into...
754Le_set_signif:
755	setsignif
756	jbr	Ledit_case
757
758Le_clear_signif:
759	clsignif
760	jbr	Ledit_case
761
762Le_store_sign:
763	putsign
764	jbr	Ledit_case
765
766Le_load_fill:
767	setfill((%r3)+)
768	jbr	Ledit_case
769
770Le_load_plus:
771	jbs	NEGATIVEBIT,%r4,Lpattern_inc	# if non-negative
772					# fall into...
773Le_load_sign:
774	setsign((%r3)+)
775	jbr	Ledit_case
776
777Le_load_minus:
778	jbs	NEGATIVEBIT,%r4,Le_load_sign	# if negative load the sign
779	incl	%r3			# else increment pattern
780	jbr	Ledit_case
781
782Le_insert:
783	jbc	SIGNIFBIT,%r4,L196	# if significance set, put next byte
784	movb	(%r3)+,(%r5)+
785	jbr	Ledit_case
786L196:					# else put in fill character
787	putfill
788					# and throw away character in pattern
789Le_replace_sign:			# we dont do anything with
790Lpattern_inc:				# replace sign cause we dont
791	incl	%r3			# get negative zero
792	jbr	Ledit_case
793
794Le_blank_zero:
795	jbc	ZEROBIT,%r4,Lpattern_inc	# if zero
796	movzbl	(%r3)+,%r11		# next byte is a count
797	jeql	Ledit_case
798	subl2	%r11,%r5			# to back up over output and replace
799L200:
800	putfill				# with fill character
801	sobgtr	%r11,L200
802	jbr	Ledit_case
803
804Le_adjust_input:
805	movzbl	(%r3)+,%r0		# get count of nibbles from pattern
806	subl3	%r2,%r0,%r11
807	jgeq	Ledit_case		# if length of source is > this number
808L204:					# discard digits in source
809	jlbc	%r2,L206			# use low bit of length to choose nibble
810	bitb	$0xf0,(%r10)		# high nibble
811	jeql	L208
812	setsignif			# set significance and overflow if
813	setoverflow			#    wasted digit is non-zero
814	jbr	L208
815L206:
816	bitb	$0xf,(%r10)		# low nibble
817	jeql	L209
818	setsignif
819	setoverflow
820L209:
821	incl	%r10			# increment to next byte
822L208:
823	decl	%r2			# decrement source length
824	incl	%r11			# continue till were out of excess
825	jlss	L204
826	jbr	Ledit_case
827
828Le_fill:
829	tstl	%r1			# put (count in %r1) fill characters
830	jeql	Ledit_case
831Le_fill_loop:
832	putfill
833	sobgtr	%r1,Le_fill_loop
834	jbr	Ledit_case
835
836Le_move:
837	tstl	%r1			# move (count in %r1) characters
838	jeql	Ledit_case		# from source to destination
839L214:
840	jlbc	%r2,L215			# read a nibble
841	extzv	$4,$4,(%r10),%r11
842	jbr	L216
843L215:
844	extzv	$0,$4,(%r10),%r11
845	incl	%r10
846L216:
847	decl	%r2			# source length CAN go negative here...
848	tstl	%r11
849	jeql	L218			# if non-zero
850	setsignif			# set significance
851L218:
852	jbc	SIGNIFBIT,%r4,L219	# if significance set
853	addb3	$48,%r11,(%r5)+		# put 0 + digit into destination
854	jbr	L220
855L219:					# else put fill character
856	putfill
857L220:
858	sobgtr	%r1,L214
859	jbr	Ledit_case
860
861Le_float:				# move with floating sign character
862	tstl	%r1
863	jeql	Ledit_case
864L221:
865	jlbc	%r2,L222
866	extzv	$4,$4,(%r10),%r11
867	jbr	L223
868L222:
869	extzv	$0,$4,(%r10),%r11
870	incl	%r10
871L223:
872	decl	%r2			# source length CAN go negative here...
873	tstl	%r11
874	jeql	L225
875	jbs	SIGNIFBIT,%r4,L226
876	putsign
877L226:
878	setsignif
879L225:
880	jbc	SIGNIFBIT,%r4,L227
881	addb3	$48,%r11,(%r5)+
882	jbr	L228
883L227:
884	putfill
885L228:
886	sobgtr	%r1,L221
887	jbr	Ledit_case
888
889
890	.align	1
891ALTENTRY(EMashp)
892	argb(1,%r11)		# (1) scale (number to shift) == %r11
893	arguw(2,%r10)		# (2) source length == %r10
894	argl(3,%r1)		# (3) source address == %r1
895	argub(4,%r2)		# (4) rounding factor == %r2
896	arguw(5,%r3)		# (5) destination length == %r3
897	toarg(%r6,3)/* 	# arg3 holds register 6 from caller */
898	argl(6,%r6)		# (6) destination address == %r6
899/*
900			# we need arg6 for later
901			# arg1 is used for temporary storage
902			# arg2 holds "even or odd" destination length
903			# arg4 is used as general storage
904			# arg5 is used as general storage
905*/
906	ashl	$-1,%r3,%r0	# destination length is number of bytes
907	addl2	%r0,%r6		# destination address == least sig nibble
908	toarg(%r6,1)		# save in arg1 spot for later
909	ashl	$-1,%r10,%r0
910	addl2	%r0,%r1		# source address == least sig nibble
911	extzv	$0,$4,(%r1),%r0	# determine sign of source
912	cmpl	%r0,NEGATIVEalt
913	jeql	Lashp_neg
914	cmpl	%r0,NEGATIVE
915	jeql	Lashp_neg
916	movb	POSITIVE,(%r6)
917	jbr	L245
918Lashp_neg:
919	movb	NEGATIVE,(%r6)
920L245:
921	clrl	arg2		# arg2 is 1 if dstlen is even, 0 if odd
922	blbs	%r3,L246
923	incl	arg2
924	bisl2	$1,%r3		# %r3<0> counts digits going into destination
925L246:				#	and is flip-flop for which nibble to
926	tstl	%r11		#	write in destination (1 = high, 0 = low)
927	jgeq	Lashp_left	#	(it must start out odd)
928	addl2	%r11,%r10		# scale is negative (right shift)
929	jgeq	Lashp_right
930	clrl	%r10		# test for shifting whole number out
931	jbr	Lashp_setround
932Lashp_right:
933	divl3	$2,%r11,%r0
934	addl2	%r0,%r1		# source address == MSNibble to be shifted off
935	jlbc	%r11,L249
936	extzv	$4,$4,(%r1),%r0
937	addl2	%r0,%r2		# round = last nibble to be shifted off + round
938	jbr	Lashp_setround
939L249:
940	extzv	$0,$4,(%r1),%r0
941	addl2	%r0,%r2		# round = last nibble to be shifted off + round
942Lashp_setround:			# %r11<0> now is flip-flop for which nibble to
943	incl	%r11		#    read from source (1 == high, 0 == low)
944	cmpl	%r2,$9		# set rounding factor to one if nibble shifted
945	jleq	Lashp_noround	#    off + round argument was 10 or greater
946	movl	$1,%r2
947	jbr	Lashp_shift
948Lashp_zloop:
949	jlbs	%r3,L257		# dont need to clear high nibble twice
950	clrb	-(%r6)		# clear low (and high) nib of next byte in dest
951L257:
952	sobgtr	%r3,L258		# move to next nibble in destination, but
953	incl	%r3		#	dont go beyond the end.
954L258:
955	decl	%r11
956Lashp_left:			# while scale is positive
957	jneq	Lashp_zloop
958	incl	%r11		# %r11<0> is flip-plop ... (incl sets it to one)
959Lashp_noround:
960	clrl	%r2		# no more rounding
961Lashp_shift:
962	clrl	arg4		# arg4 will be used for result condition codes
963	tstl	%r10
964	jeql	Lashp_round
965Lashp_shloop:
966	jlbc	%r11,L260
967	extzv	$4,$4,(%r1),%r0
968	jbr	L261
969L260:
970	decl	%r1
971	extzv	$0,$4,(%r1),%r0
972L261:
973	incl	%r11		# flip the source nibble flip/flop
974	addl2	%r0,%r2		# round += next nibble
975	cmpl	%r2,$10		# if round == 10
976	jneq	L262
977	clrl	arg5		#	then result = 0 and round = 1
978	movl	$1,%r2
979	jbr	L263
980L262:				# else
981	movl	%r2,arg5		#	store result and round = 0
982	clrl	%r2
983L263:
984	bisl2	arg5,arg4	# remember if result was nonzero in arg4
985	decl	%r3		# move to next nibble early to check
986	cmpl	%r3,arg2		# if weve moved passed destination limits
987	jgeq	Lashp_noovfl	#	test the result for possible overflow
988	movl	arg2,%r3		#	ignore zero nibbles
989	tstl	arg5		#	if the nibble was non-zero, overflow
990	jeql	L265
991	jbr	Lashp_overfl
992Lashp_noovfl:			# else
993	jlbs	%r3,L264
994	insv	arg5,$4,$4,(%r6)	# put the result into destination (high or low)
995	jbr	L265
996L264:
997	movb	arg5,-(%r6)
998L265:
999	sobgtr	%r10,Lashp_shloop	# loop for length of source
1000
1001Lashp_round:
1002	tstl	%r2		# take care of round out of high nibble
1003	jeql	Lashp_zeroround
1004	decl	%r3
1005	cmpl	%r3,arg2		# if weve moved passed destination limits
1006	jlss	Lashp_overfl	#	then overflow
1007	jlbs	%r3,L266
1008	insv	arg5,$4,$4,(%r6)	# put the round into destination (high or low)
1009	jbr	Lashp_zeroround
1010L266:
1011	movb	arg5,-(%r6)
1012
1013Lashp_zeroround:
1014	argl(1,%r10)		# %r10 = address of destination LSNibble
1015	argl(6,%r3)		# %r3 = address of destination MSNibble
1016	movl	arg4,%r11	# %r11 = non-zero if destination == non-zero
1017	savepsl
1018	jbr	L267
1019Lashp_zerofill:
1020	clrb	-(%r6)		# fill up MSNs of destination with zeros
1021L267:
1022	cmpl	%r3,%r6
1023	jneq	Lashp_zerofill
1024	extzv	$0,$4,(%r10),%r0	# test for negative result
1025	cmpl	%r0,NEGATIVE
1026	jneq	Lashp_out
1027	mnegl	%r11,%r11
1028	savepsl
1029	jneq	Lashp_out	# turn -0 into 0
1030	insv	POSITIVE,$0,$4,(%r10)
1031Lashp_out:
1032	clrl	%r0
1033	argl(3,%r6)		# restore %r6 from stack
1034	return
1035Lashp_overfl:			#    do overflow
1036	clrl	%r2
1037	overflowpsl
1038	jbr	Lashp_out
1039
1040
1041	.align	1
1042ALTENTRY(EMcvtlp)
1043	arguw(2,%r10)		# (2) destination length == %r10
1044	argl(3,%r3)		# (3) destination address == %r3
1045	ashl	$-1,%r10,%r10
1046	addl2	%r10,%r3		# destination address points to Least Sig byte
1047	incl	%r10		# length is # of bytes, not nibbles
1048	argl(1,%r11)		# (1) source == %r11
1049	savepsl
1050	jgeq	Lcvtlp_pos
1051	movb	NEGATIVE,(%r3)	# source is negative
1052	divl3	$10,%r11,%r0
1053	mull3	$10,%r0,%r1
1054	subl3	%r11,%r1,%r2	# %r2 = source mod 10
1055	mnegl	%r0,%r11		# source = -(source / 10)
1056	jbr	Lcvtlp_cvt
1057Lcvtlp_pos:
1058	movb	POSITIVE,(%r3)	# source is non-negative
1059	divl3	$10,%r11,%r0
1060	mull3	$10,%r0,%r1
1061	subl3	%r1,%r11,%r2	# %r2 = source mod 10
1062	movl	%r0,%r11		# source = source / 10
1063Lcvtlp_cvt:
1064	insv	%r2,$4,$4,(%r3)	# store least significant digit
1065	tstl	%r11
1066	jeql	Lcvtlp_zloop
1067Lcvtlp_loop:			# while source is non-zero
1068	decl	%r10		#   and for length of destination ...
1069	jeql	Lcvtlp_over
1070	divl3	$10,%r11,%r1	# %r1 = source / 10
1071	mull3	$10,%r1,%r0
1072	subl2	%r0,%r11		# source = source mod 10
1073	movb	%r11,-(%r3)	# store low "nibble" in next significant byte
1074	divl3	$10,%r1,%r11	# source = %r1 / 10
1075	mull3	$10,%r11,%r0
1076	subl2	%r0,%r1		# %r1 = source mod 10
1077	insv	%r1,$4,$4,(%r3)	# store high nibble
1078	tstl	%r11
1079	jneq	Lcvtlp_loop	# quit if source becomes zero
1080Lcvtlp_zloop:			# fill any remaining bytes with zeros
1081	decl	%r10
1082	jeql	Lcvtlp_out
1083	clrb	-(%r3)
1084	jbr	Lcvtlp_zloop
1085Lcvtlp_over:
1086	overflowpsl
1087Lcvtlp_out:
1088	clrl	%r1		# %r0 is already zero
1089	clrl	%r2
1090	return
1091
1092
1093	.align	1
1094ALTENTRY(EMcvtpl)
1095	arguw(1,%r11)		# (1) source length == %r11
1096	argl(2,%r10)		# (2) source address == %r10
1097	clrl	%r3		# %r3 == destination
1098	movl	%r10,%r1		# %r1 set up now for return
1099	ashl	$-1,%r11,%r11	# source length is number of bytes
1100	jeql	Lcvtpl_zero
1101Lcvtpl_loop:			# for source length
1102	mull2	$10,%r3		# destination *= 10
1103	extzv	$4,$4,(%r10),%r0
1104	addl2	%r0,%r3		# destination += high nibble
1105	mull2	$10,%r3		# destination *= 10
1106	extzv	$0,$4,(%r10),%r0
1107	addl2	%r0,%r3		# destination += low nibble
1108	incl	%r10
1109	sobgtr	%r11,Lcvtpl_loop
1110Lcvtpl_zero:			# least significant byte
1111	mull2	$10,%r3
1112	extzv	$4,$4,(%r10),%r0
1113	addl2	%r0,%r3		# dest = 10 * dest + high nibble
1114	savepsl
1115	extzv	$0,$4,(%r10),%r2	# test sign nibble
1116	cmpl	%r2,NEGATIVE
1117	jeql	Lcvtpl_neg
1118	cmpl	%r2,NEGATIVEalt
1119	jneq	Lcvtpl_out
1120Lcvtpl_neg:			# source was negative - negate destination
1121	mnegl	%r3,%r3
1122	savepsl
1123Lcvtpl_out:
1124	toarg(%r3,3)
1125	clrl	%r0
1126	clrl	%r2
1127	clrl	%r3
1128	return
1129
1130
1131	.align	1
1132ALTENTRY(EMcvtps)
1133	return
1134
1135
1136	.align	1
1137ALTENTRY(EMcvtsp)
1138	return
1139
1140
1141	.align	1
1142ALTENTRY(EMaddp6)
1143	return
1144
1145
1146	.align	1
1147ALTENTRY(EMsubp4)
1148	return
1149
1150
1151	.align	1
1152ALTENTRY(EMsubp6)
1153	return
1154
1155
1156	.align	1
1157ALTENTRY(EMcvtpt)
1158	return
1159
1160
1161	.align	1
1162ALTENTRY(EMmulp)
1163	return
1164
1165
1166	.align	1
1167ALTENTRY(EMcvttp)
1168	return
1169
1170
1171	.align	1
1172ALTENTRY(EMdivp)
1173	return
1174
1175
1176	.align	1
1177ALTENTRY(EMcmpp3)
1178	return
1179
1180
1181	.align	1
1182ALTENTRY(EMcmpp4)
1183	return
1184
1185
1186
1187#ifdef notdef
1188/*
1189 * Emulation OpCode jump table:
1190 *	ONLY GOES FROM 0xf8 (-8) TO 0x3B (59)
1191 */
1192#define EMUTABLE	0x43
1193#define NOEMULATE	.long noemulate
1194#define	EMULATE(a)	.long _EM/**/a
1195	.globl	_C_LABEL(emJUMPtable)
1196_C_LABEL(emJUMPtable)
1197/* f8 */	EMULATE(ashp);	EMULATE(cvtlp);	NOEMULATE;	NOEMULATE
1198/* fc */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1199/* 00 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1200/* 04 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1201/* 08 */	EMULATE(cvtps);	EMULATE(cvtsp);	NOEMULATE;	EMULATE(crc)
1202/* 0c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1203/* 10 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1204/* 14 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1205/* 18 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1206/* 1c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1207/* 20 */	EMULATE(addp4);	EMULATE(addp6);	EMULATE(subp4);	EMULATE(subp6)
1208/* 24 */	EMULATE(cvtpt);	EMULATE(mulp);	EMULATE(cvttp);	EMULATE(divp)
1209/* 28 */	NOEMULATE;	EMULATE(cmpc3);	EMULATE(scanc);	EMULATE(spanc)
1210/* 2c */	NOEMULATE;	EMULATE(cmpc5);	EMULATE(movtc);	EMULATE(movtuc)
1211/* 30 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
1212/* 34 */	EMULATE(movp);	EMULATE(cmpp3);	EMULATE(cvtpl);	EMULATE(cmpp4)
1213/* 38 */	EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc)
1214
1215/*
1216 * The following is called with the stack set up as follows:
1217 *
1218 *	  (%sp):	Opcode
1219 *	 4(%sp):	Instruction PC
1220 *	 8(%sp):	Operand 1
1221 *	12(%sp):	Operand 2
1222 *	16(%sp):	Operand 3
1223 *	20(%sp):	Operand 4
1224 *	24(%sp):	Operand 5
1225 *	28(%sp):	Operand 6
1226 *	32(%sp):	Operand 7 (unused)
1227 *	36(%sp):	Operand 8 (unused)
1228 *	40(%sp):	Return PC
1229 *	44(%sp):	Return PSL
1230 *	48(%sp): TOS before instruction
1231 *
1232 * Each individual routine is called with the stack set up as follows:
1233 *
1234 *	  (%sp):	Return address of trap handler
1235 *	 4(%sp):	Opcode (will get return PSL)
1236 *	 8(%sp):	Instruction PC
1237 *	12(%sp):	Operand 1
1238 *	16(%sp):	Operand 2
1239 *	20(%sp):	Operand 3
1240 *	24(%sp):	Operand 4
1241 *	28(%sp):	Operand 5
1242 *	32(%sp):	Operand 6
1243 *	36(%sp):	saved register 11
1244 *	40(%sp):	saved register 10
1245 *	44(%sp):	Return PC
1246 *	48(%sp):	Return PSL
1247 *	52(%sp): TOS before instruction
1248 */
1249
1250SCBVEC(emulate):
1251	movl	%r11,32(%sp)		# save register %r11 in unused operand
1252	movl	%r10,36(%sp)		# save register %r10 in unused operand
1253	cvtbl	(%sp),%r10		# get opcode
1254	addl2	$8,%r10			# shift negative opcodes
1255	subl3	%r10,$EMUTABLE,%r11	# forget it if opcode is out of range
1256	bcs	noemulate
1257	movl	_C_LABEL(emJUMPtable)[%r10],%r10
1258					# call appropriate emulation routine
1259	jsb	(%r10)		# routines put return values into regs 0-5
1260	movl	32(%sp),%r11		# restore register %r11
1261	movl	36(%sp),%r10		# restore register %r10
1262	insv	(%sp),$0,$4,44(%sp)	# and condition codes in Opcode spot
1263	addl2	$40,%sp			# adjust stack for return
1264	rei
1265noemulate:
1266	addl2	$48,%sp			# adjust stack for
1267	.word	0xffff			# "reserved instruction fault"
1268SCBVEC(emulateFPD):
1269	.word	0xffff			# "reserved instruction fault"
1270#endif
1271