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