Home | History | Annotate | Line # | Download | only in vax
      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
     86 ALTENTRY(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
     92 Lcrc_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
    102 Lcrc_out:
    103 	savepsl
    104 	clrl	%r1
    105 	return
    106 
    107 
    108 	.align	1
    109 ALTENTRY(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
    117 Lmovtc_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
    125 Lmovtc_2loop:
    126 	movb	%r11,(%r5)+
    127 	sobgtr	%r4,Lmovtc_2loop
    128 Lmovtc_out:
    129 	cmpw	arg1,arg5
    130 	savepsl
    131 	clrl	%r2
    132 	return
    133 
    134 
    135 	.align	1
    136 ALTENTRY(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
    144 Lmovtuc_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
    155 Lmovtuc_out1:
    156 	clrl	%r2		# clear V-bit
    157 	brb	Lmovtuc_out
    158 Lmovtuc_out2:
    159 	movl	$2,%r2		# set V-bit
    160 Lmovtuc_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
    169 ALTENTRY(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
    178 Lmatchc_loop:
    179 	cmpb	(%r10),(%r3)
    180 	jneq	Lmatchc_fail
    181 	movl	%r3,%r1
    182 	movl	%r10,%r0
    183 Lmatchc_2loop:
    184 	cmpl	%r0,%r11
    185 	jeql	Lmatchc_succ
    186 	cmpb	(%r0)+,(%r1)+
    187 	jeql	Lmatchc_2loop
    188 Lmatchc_fail:
    189 	incl	%r3
    190 	sobgtr	%r2,Lmatchc_loop
    191 	movl	%r10,%r1
    192 	subl3	%r10,%r11,%r0
    193 	jbr	Lmatchc_out
    194 Lmatchc_succ:
    195 	movl	%r1,%r3
    196 	movl	%r11,%r1
    197 	clrl	%r0
    198 Lmatchc_out:
    199 	savepsl
    200 	return
    201 
    202 
    203 	.align	1
    204 ALTENTRY(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
    210 Lspanc_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
    217 Lspanc_out:
    218 	savepsl
    219 	clrl	%r2
    220 	return
    221 
    222 
    223 	.align	1
    224 ALTENTRY(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
    230 Lscanc_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
    237 Lscanc_out:
    238 	savepsl
    239 	clrl	%r2
    240 	return
    241 
    242 
    243 	.align	1
    244 ALTENTRY(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
    249 Lskpc_loop:
    250 	cmpb	(%r1),%r11
    251 	jneq	Lskpc_out
    252 	incl	%r1
    253 	sobgtr	%r0,Lskpc_loop
    254 Lskpc_out:
    255 	tstl	%r0		# be sure of condition codes
    256 	savepsl
    257 	return
    258 
    259 
    260 	.align	1
    261 ALTENTRY(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
    266 Llocc_loop:
    267 	cmpb	(%r1),%r11
    268 	jeql	Llocc_out
    269 	incl	%r1
    270 	sobgtr  %r0,Llocc_loop
    271 Llocc_out:
    272 	tstl	%r0		# be sure of condition codes
    273 	savepsl
    274 	return
    275 
    276 
    277 	.align	1
    278 ALTENTRY(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
    283 Lcmpc3_loop:
    284 	cmpb	(%r1),(%r3)
    285 	jneq	Lcmpc3_out
    286 	incl	%r1
    287 	incl	%r3
    288 	sobgtr	%r0,Lcmpc3_loop
    289 Lcmpc3_out:
    290 	savepsl
    291 	movl	%r0,%r2
    292 	return
    293 
    294 
    295 	.align	1
    296 ALTENTRY(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
    303 Lcmpc5_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
    312 Lcmpc5_str2:
    313 	tstl	%r2
    314 	jeql	Lcmpc5_out
    315 Lcmpc5_str2loop:
    316 	cmpb	%r11,(%r3)
    317 	jneq	Lcmpc5_out
    318 	incl	%r3
    319 	sobgtr	%r2,Lcmpc5_str2loop
    320 	jbr	Lcmpc5_out
    321 Lcmpc5_str1loop:
    322 	cmpb	(%r1),%r11
    323 	jneq	Lcmpc5_out
    324 	incl	%r1
    325 	sobgtr	%r0,Lcmpc5_str1loop
    326 Lcmpc5_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
    341 ALTENTRY(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
    361 L111:
    362 	insv	NEGATIVE,$0,$4,(%r3)
    363 L112:
    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
    371 L113:
    372 	movl	NEGATIVE,%r2
    373 L114:
    374 	cmpl	%r11,%r9		# if source is longer than destination
    375 	jleq	L115
    376 	movl	%r9,%r11		#	set source length == destination length
    377 L115:
    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
    386 Laddp4_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
    397 L121:
    398 	clrl	%r9		#	%r9 == carry = 0
    399 L122:
    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
    406 L119:
    407 	jgeq	L117		# if negative result
    408 	mnegl	$1,%r1		#	%r1 == carry = -1
    409 	addl2	$10,%r9		#	%r9 == result += 10
    410 	jbr	L118		# else
    411 L117:
    412 	clrl	%r1		#	%r1 == carry = 0
    413 L118:
    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
    420 Laddp4_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
    428 L127:				# else
    429 	clrl	%r9		#	%r9 == carry = 0
    430 L128:
    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
    439 L129:
    440 	clrl	%r1
    441 L130:
    442 	insv	%r9,$4,$4,(%r3)	# store result
    443 	bisl2	%r9,%r2
    444 Laddp4_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
    455 L132:
    456 	insv	NEGATIVE,$0,$4,(%r3)
    457 L133:
    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
    461 L137:
    462 	movl	$9,%r1
    463 Laddp4_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
    475 L135:
    476 	movl	$9,%r9
    477 L136:
    478 	insv	%r1,$0,$4,(%r3)
    479 	extzv	$4,$4,(%r3),%r0	# high nibble = (9 + carry) - high nibble
    480 	subl2	%r0,%r9
    481 L134:
    482 	cmpl	%r9,$9
    483 	jleq	L137
    484 	clrl	%r9
    485 	movl	$10,%r1
    486 	jbr	Laddp4_diff_norm
    487 
    488 Laddp4_same:			# operands are of the same sign
    489 	clrl	%r2
    490 	addl2	%r1,%r9
    491 	jbr	L139
    492 Laddp4_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
    504 L141:				# else
    505 	clrl	%r9		#	%r9 == carry = 0
    506 L142:
    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
    513 L139:
    514 	cmpl	%r9,$9
    515 	jleq	L143
    516 	movl	$1,%r1
    517 	subl2	$10,%r9
    518 	jbr	L144
    519 L143:
    520 	clrl	%r1
    521 L144:
    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
    527 Laddp4_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
    536 L147:
    537 	clrl	%r9
    538 L148:
    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
    548 L149:
    549 	clrl	%r1
    550 L150:
    551 	insv	%r9,$4,$4,(%r3)
    552 	bisl2	%r9,%r2
    553 Laddp4_same_carry:
    554 	cmpl	%r3,%r10
    555 	jneq	Laddp4_same_cloop
    556 
    557 Laddp4_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
    564 L151:				# 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
    570 Laddp4_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
    580 ALTENTRY(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
    588 Lmovp_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
    592 Lmovp_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
    600 Lmovp_neg:			# source was negative
    601 	mnegl	%r2,%r2
    602 Lmovp_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
    608 Lmovp_zero:
    609 	movb	POSITIVE,(%r3)	#	otherwise, make result zero and positive
    610 Lmovp_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
    670 ALTENTRY(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
    683 L169:
    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
    689 L170:
    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
    698 L9998:
    699 	setnegative
    700 	setsign($45)		# sign character is '-'
    701 	jbr	L175
    702 L172:
    703 	setzero
    704 L175:
    705 	arguw(1,%r2)		# (1) source length == %r2
    706 Ledit_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
    712 L180:
    713 	jbc	$6,%r11,L181	# "shift" those commands > 64 to 16 and up
    714 	subl2	$48,%r11
    715 L181:
    716 	caseb	%r11,$0,$0x18	# "do" the command
    717 				# %r11 is available for use, %r1 has "count" in it
    718 Lcaseb_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
    743 Le_end:
    744 	arguw(1,%r0)
    745 	argl(2,%r1)
    746 	clrl	%r2
    747 	decl	%r3
    748 	setpsl(%r4)
    749 	clrl	%r4
    750 	return
    751 
    752 Le_end_float:
    753 	jbs	SIGNIFBIT,%r4,Ledit_case	# if significance not set
    754 	putsign				# drop in the sign
    755 					# fall into...
    756 Le_set_signif:
    757 	setsignif
    758 	jbr	Ledit_case
    759 
    760 Le_clear_signif:
    761 	clsignif
    762 	jbr	Ledit_case
    763 
    764 Le_store_sign:
    765 	putsign
    766 	jbr	Ledit_case
    767 
    768 Le_load_fill:
    769 	setfill((%r3)+)
    770 	jbr	Ledit_case
    771 
    772 Le_load_plus:
    773 	jbs	NEGATIVEBIT,%r4,Lpattern_inc	# if non-negative
    774 					# fall into...
    775 Le_load_sign:
    776 	setsign((%r3)+)
    777 	jbr	Ledit_case
    778 
    779 Le_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 
    784 Le_insert:
    785 	jbc	SIGNIFBIT,%r4,L196	# if significance set, put next byte
    786 	movb	(%r3)+,(%r5)+
    787 	jbr	Ledit_case
    788 L196:					# else put in fill character
    789 	putfill
    790 					# and throw away character in pattern
    791 Le_replace_sign:			# we dont do anything with
    792 Lpattern_inc:				# replace sign cause we dont
    793 	incl	%r3			# get negative zero
    794 	jbr	Ledit_case
    795 
    796 Le_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
    801 L200:
    802 	putfill				# with fill character
    803 	sobgtr	%r11,L200
    804 	jbr	Ledit_case
    805 
    806 Le_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
    810 L204:					# 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
    817 L206:
    818 	bitb	$0xf,(%r10)		# low nibble
    819 	jeql	L209
    820 	setsignif
    821 	setoverflow
    822 L209:
    823 	incl	%r10			# increment to next byte
    824 L208:
    825 	decl	%r2			# decrement source length
    826 	incl	%r11			# continue till were out of excess
    827 	jlss	L204
    828 	jbr	Ledit_case
    829 
    830 Le_fill:
    831 	tstl	%r1			# put (count in %r1) fill characters
    832 	jeql	Ledit_case
    833 Le_fill_loop:
    834 	putfill
    835 	sobgtr	%r1,Le_fill_loop
    836 	jbr	Ledit_case
    837 
    838 Le_move:
    839 	tstl	%r1			# move (count in %r1) characters
    840 	jeql	Ledit_case		# from source to destination
    841 L214:
    842 	jlbc	%r2,L215			# read a nibble
    843 	extzv	$4,$4,(%r10),%r11
    844 	jbr	L216
    845 L215:
    846 	extzv	$0,$4,(%r10),%r11
    847 	incl	%r10
    848 L216:
    849 	decl	%r2			# source length CAN go negative here...
    850 	tstl	%r11
    851 	jeql	L218			# if non-zero
    852 	setsignif			# set significance
    853 L218:
    854 	jbc	SIGNIFBIT,%r4,L219	# if significance set
    855 	addb3	$48,%r11,(%r5)+		# put 0 + digit into destination
    856 	jbr	L220
    857 L219:					# else put fill character
    858 	putfill
    859 L220:
    860 	sobgtr	%r1,L214
    861 	jbr	Ledit_case
    862 
    863 Le_float:				# move with floating sign character
    864 	tstl	%r1
    865 	jeql	Ledit_case
    866 L221:
    867 	jlbc	%r2,L222
    868 	extzv	$4,$4,(%r10),%r11
    869 	jbr	L223
    870 L222:
    871 	extzv	$0,$4,(%r10),%r11
    872 	incl	%r10
    873 L223:
    874 	decl	%r2			# source length CAN go negative here...
    875 	tstl	%r11
    876 	jeql	L225
    877 	jbs	SIGNIFBIT,%r4,L226
    878 	putsign
    879 L226:
    880 	setsignif
    881 L225:
    882 	jbc	SIGNIFBIT,%r4,L227
    883 	addb3	$48,%r11,(%r5)+
    884 	jbr	L228
    885 L227:
    886 	putfill
    887 L228:
    888 	sobgtr	%r1,L221
    889 	jbr	Ledit_case
    890 
    891 
    892 	.align	1
    893 ALTENTRY(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
    920 Lashp_neg:
    921 	movb	NEGATIVE,(%r6)
    922 L245:
    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
    927 L246:				#	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
    934 Lashp_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
    941 L249:
    942 	extzv	$0,$4,(%r1),%r0
    943 	addl2	%r0,%r2		# round = last nibble to be shifted off + round
    944 Lashp_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
    950 Lashp_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
    953 L257:
    954 	sobgtr	%r3,L258		# move to next nibble in destination, but
    955 	incl	%r3		#	dont go beyond the end.
    956 L258:
    957 	decl	%r11
    958 Lashp_left:			# while scale is positive
    959 	jneq	Lashp_zloop
    960 	incl	%r11		# %r11<0> is flip-plop ... (incl sets it to one)
    961 Lashp_noround:
    962 	clrl	%r2		# no more rounding
    963 Lashp_shift:
    964 	clrl	arg4		# arg4 will be used for result condition codes
    965 	tstl	%r10
    966 	jeql	Lashp_round
    967 Lashp_shloop:
    968 	jlbc	%r11,L260
    969 	extzv	$4,$4,(%r1),%r0
    970 	jbr	L261
    971 L260:
    972 	decl	%r1
    973 	extzv	$0,$4,(%r1),%r0
    974 L261:
    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
    982 L262:				# else
    983 	movl	%r2,arg5		#	store result and round = 0
    984 	clrl	%r2
    985 L263:
    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
    994 Lashp_noovfl:			# else
    995 	jlbs	%r3,L264
    996 	insv	arg5,$4,$4,(%r6)	# put the result into destination (high or low)
    997 	jbr	L265
    998 L264:
    999 	movb	arg5,-(%r6)
   1000 L265:
   1001 	sobgtr	%r10,Lashp_shloop	# loop for length of source
   1002 
   1003 Lashp_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
   1012 L266:
   1013 	movb	arg5,-(%r6)
   1014 
   1015 Lashp_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
   1021 Lashp_zerofill:
   1022 	clrb	-(%r6)		# fill up MSNs of destination with zeros
   1023 L267:
   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)
   1033 Lashp_out:
   1034 	clrl	%r0
   1035 	argl(3,%r6)		# restore %r6 from stack
   1036 	return
   1037 Lashp_overfl:			#    do overflow
   1038 	clrl	%r2
   1039 	overflowpsl
   1040 	jbr	Lashp_out
   1041 
   1042 
   1043 	.align	1
   1044 ALTENTRY(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
   1059 Lcvtlp_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
   1065 Lcvtlp_cvt:
   1066 	insv	%r2,$4,$4,(%r3)	# store least significant digit
   1067 	tstl	%r11
   1068 	jeql	Lcvtlp_zloop
   1069 Lcvtlp_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
   1082 Lcvtlp_zloop:			# fill any remaining bytes with zeros
   1083 	decl	%r10
   1084 	jeql	Lcvtlp_out
   1085 	clrb	-(%r3)
   1086 	jbr	Lcvtlp_zloop
   1087 Lcvtlp_over:
   1088 	overflowpsl
   1089 Lcvtlp_out:
   1090 	clrl	%r1		# %r0 is already zero
   1091 	clrl	%r2
   1092 	return
   1093 
   1094 
   1095 	.align	1
   1096 ALTENTRY(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
   1103 Lcvtpl_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
   1112 Lcvtpl_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
   1122 Lcvtpl_neg:			# source was negative - negate destination
   1123 	mnegl	%r3,%r3
   1124 	savepsl
   1125 Lcvtpl_out:
   1126 	toarg(%r3,3)
   1127 	clrl	%r0
   1128 	clrl	%r2
   1129 	clrl	%r3
   1130 	return
   1131 
   1132 
   1133 	.align	1
   1134 ALTENTRY(EMcvtps)
   1135 	return
   1136 
   1137 
   1138 	.align	1
   1139 ALTENTRY(EMcvtsp)
   1140 	return
   1141 
   1142 
   1143 	.align	1
   1144 ALTENTRY(EMaddp6)
   1145 	return
   1146 
   1147 
   1148 	.align	1
   1149 ALTENTRY(EMsubp4)
   1150 	return
   1151 
   1152 
   1153 	.align	1
   1154 ALTENTRY(EMsubp6)
   1155 	return
   1156 
   1157 
   1158 	.align	1
   1159 ALTENTRY(EMcvtpt)
   1160 	return
   1161 
   1162 
   1163 	.align	1
   1164 ALTENTRY(EMmulp)
   1165 	return
   1166 
   1167 
   1168 	.align	1
   1169 ALTENTRY(EMcvttp)
   1170 	return
   1171 
   1172 
   1173 	.align	1
   1174 ALTENTRY(EMdivp)
   1175 	return
   1176 
   1177 
   1178 	.align	1
   1179 ALTENTRY(EMcmpp3)
   1180 	return
   1181 
   1182 
   1183 	.align	1
   1184 ALTENTRY(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 
   1252 SCBVEC(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
   1267 noemulate:
   1268 	addl2	$48,%sp			# adjust stack for
   1269 	.word	0xffff			# "reserved instruction fault"
   1270 SCBVEC(emulateFPD):
   1271 	.word	0xffff			# "reserved instruction fault"
   1272 #endif
   1273