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