11.5Sandvar*	$NetBSD: get_op.sa,v 1.5 2022/11/02 20:38:22 andvar Exp $
21.3Scgd
31.1Smycroft*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
41.1Smycroft*	M68000 Hi-Performance Microprocessor Division
51.1Smycroft*	M68040 Software Package 
61.1Smycroft*
71.1Smycroft*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
81.1Smycroft*	All rights reserved.
91.1Smycroft*
101.1Smycroft*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
111.1Smycroft*	To the maximum extent permitted by applicable law,
121.1Smycroft*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
131.1Smycroft*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
141.1Smycroft*	PARTICULAR PURPOSE and any warranty against infringement with
151.1Smycroft*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
161.1Smycroft*	and any accompanying written materials. 
171.1Smycroft*
181.1Smycroft*	To the maximum extent permitted by applicable law,
191.1Smycroft*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
201.1Smycroft*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
211.1Smycroft*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
221.1Smycroft*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
231.1Smycroft*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
241.1Smycroft*	and support of the SOFTWARE.  
251.1Smycroft*
261.1Smycroft*	You are hereby granted a copyright license to use, modify, and
271.1Smycroft*	distribute the SOFTWARE so long as this entire notice is retained
281.1Smycroft*	without alteration in any modified and/or redistributed versions,
291.1Smycroft*	and that such modified versions are clearly identified as such.
301.1Smycroft*	No licenses are granted by implication, estoppel or otherwise
311.1Smycroft*	under any patents or trademarks of Motorola, Inc.
321.1Smycroft
331.1Smycroft*
341.1Smycroft*	get_op.sa 3.6 5/19/92
351.1Smycroft*
361.1Smycroft*	get_op.sa 3.5 4/26/91
371.1Smycroft*
381.1Smycroft*  Description: This routine is called by the unsupported format/data
391.1Smycroft* type exception handler ('unsupp' - vector 55) and the unimplemented
401.1Smycroft* instruction exception handler ('unimp' - vector 11).  'get_op'
411.1Smycroft* determines the opclass (0, 2, or 3) and branches to the
421.1Smycroft* opclass handler routine.  See 68881/2 User's Manual table 4-11
431.1Smycroft* for a description of the opclasses.
441.1Smycroft*
451.1Smycroft* For UNSUPPORTED data/format (exception vector 55) and for
461.1Smycroft* UNIMPLEMENTED instructions (exception vector 11) the following
471.1Smycroft* applies:
481.1Smycroft*
491.1Smycroft* - For unnormormalized numbers (opclass 0, 2, or 3) the
501.1Smycroft* number(s) is normalized and the operand type tag is updated.
511.1Smycroft*		
521.1Smycroft* - For a packed number (opclass 2) the number is unpacked and the
531.1Smycroft* operand type tag is updated.
541.1Smycroft*
551.1Smycroft* - For denormalized numbers (opclass 0 or 2) the number(s) is not
561.1Smycroft* changed but passed to the next module.  The next module for
571.1Smycroft* unimp is do_func, the next module for unsupp is res_func.
581.1Smycroft*
591.1Smycroft* For UNSUPPORTED data/format (exception vector 55) only the
601.1Smycroft* following applies:
611.1Smycroft*
621.1Smycroft* - If there is a move out with a packed number (opclass 3) the
631.1Smycroft* number is packed and written to user memory.  For the other
641.1Smycroft* opclasses the number(s) are written back to the fsave stack
651.1Smycroft* and the instruction is then restored back into the '040.  The
661.1Smycroft* '040 is then able to complete the instruction.
671.1Smycroft*
681.1Smycroft* For example:
691.1Smycroft* fadd.x fpm,fpn where the fpm contains an unnormalized number.
701.1Smycroft* The '040 takes an unsupported data trap and gets to this
711.1Smycroft* routine.  The number is normalized, put back on the stack and
721.1Smycroft* then an frestore is done to restore the instruction back into
731.1Smycroft* the '040.  The '040 then re-executes the fadd.x fpm,fpn with
741.1Smycroft* a normalized number in the source and the instruction is
751.1Smycroft* successful.
761.1Smycroft*		
771.1Smycroft* Next consider if in the process of normalizing the un-
781.1Smycroft* normalized number it becomes a denormalized number.  The
791.1Smycroft* routine which converts the unnorm to a norm (called mk_norm)
801.1Smycroft* detects this and tags the number as a denorm.  The routine
811.1Smycroft* res_func sees the denorm tag and converts the denorm to a
821.1Smycroft* norm.  The instruction is then restored back into the '040
831.1Smycroft* which re_executess the instruction.
841.1Smycroft*
851.1Smycroft
861.1SmycroftGET_OP    IDNT    2,1 Motorola 040 Floating Point Software Package
871.1Smycroft
881.1Smycroft	section	8
891.1Smycroft
901.1Smycroft	include	fpsp.h
911.1Smycroft
921.1Smycroft	xdef	PIRN,PIRZRM,PIRP
931.1Smycroft	xdef	SMALRN,SMALRZRM,SMALRP
941.1Smycroft	xdef	BIGRN,BIGRZRM,BIGRP
951.1Smycroft
961.1SmycroftPIRN:
971.1Smycroft	dc.l $40000000,$c90fdaa2,$2168c235    ;pi
981.1SmycroftPIRZRM:
991.1Smycroft	dc.l $40000000,$c90fdaa2,$2168c234    ;pi
1001.1SmycroftPIRP:
1011.1Smycroft	dc.l $40000000,$c90fdaa2,$2168c235    ;pi
1021.1Smycroft
1031.1Smycroft*round to nearest
1041.1SmycroftSMALRN:
1051.1Smycroft	dc.l $3ffd0000,$9a209a84,$fbcff798    ;log10(2)
1061.1Smycroft	dc.l $40000000,$adf85458,$a2bb4a9a    ;e
1071.1Smycroft	dc.l $3fff0000,$b8aa3b29,$5c17f0bc    ;log2(e)
1081.1Smycroft	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
1091.1Smycroft	dc.l $00000000,$00000000,$00000000    ;0.0
1101.1Smycroft* round to zero;round to negative infinity
1111.1SmycroftSMALRZRM:
1121.1Smycroft	dc.l $3ffd0000,$9a209a84,$fbcff798    ;log10(2)
1131.1Smycroft	dc.l $40000000,$adf85458,$a2bb4a9a    ;e
1141.1Smycroft	dc.l $3fff0000,$b8aa3b29,$5c17f0bb    ;log2(e)
1151.1Smycroft	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
1161.1Smycroft	dc.l $00000000,$00000000,$00000000    ;0.0
1171.1Smycroft* round to positive infinity
1181.1SmycroftSMALRP:
1191.1Smycroft	dc.l $3ffd0000,$9a209a84,$fbcff799    ;log10(2)
1201.1Smycroft	dc.l $40000000,$adf85458,$a2bb4a9b    ;e
1211.1Smycroft	dc.l $3fff0000,$b8aa3b29,$5c17f0bc    ;log2(e)
1221.1Smycroft	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
1231.1Smycroft	dc.l $00000000,$00000000,$00000000    ;0.0
1241.1Smycroft
1251.1Smycroft*round to nearest
1261.1SmycroftBIGRN:
1271.1Smycroft	dc.l $3ffe0000,$b17217f7,$d1cf79ac    ;ln(2)
1281.1Smycroft	dc.l $40000000,$935d8ddd,$aaa8ac17    ;ln(10)
1291.1Smycroft	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
1301.1Smycroft
1311.1Smycroft	xdef	PTENRN
1321.1SmycroftPTENRN:
1331.1Smycroft	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
1341.1Smycroft	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
1351.1Smycroft	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
1361.1Smycroft	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
1371.1Smycroft	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
1381.1Smycroft	dc.l $40690000,$9DC5ADA8,$2B70B59E    ;10 ^ 32
1391.1Smycroft	dc.l $40D30000,$C2781F49,$FFCFA6D5    ;10 ^ 64
1401.1Smycroft	dc.l $41A80000,$93BA47C9,$80E98CE0    ;10 ^ 128
1411.1Smycroft	dc.l $43510000,$AA7EEBFB,$9DF9DE8E    ;10 ^ 256
1421.1Smycroft	dc.l $46A30000,$E319A0AE,$A60E91C7    ;10 ^ 512
1431.1Smycroft	dc.l $4D480000,$C9767586,$81750C17    ;10 ^ 1024
1441.1Smycroft	dc.l $5A920000,$9E8B3B5D,$C53D5DE5    ;10 ^ 2048
1451.1Smycroft	dc.l $75250000,$C4605202,$8A20979B    ;10 ^ 4096
1461.1Smycroft*round to minus infinity
1471.1SmycroftBIGRZRM:
1481.1Smycroft	dc.l $3ffe0000,$b17217f7,$d1cf79ab    ;ln(2)
1491.1Smycroft	dc.l $40000000,$935d8ddd,$aaa8ac16    ;ln(10)
1501.1Smycroft	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
1511.1Smycroft
1521.1Smycroft	xdef	PTENRM
1531.1SmycroftPTENRM:
1541.1Smycroft	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
1551.1Smycroft	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
1561.1Smycroft	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
1571.1Smycroft	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
1581.1Smycroft	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
1591.1Smycroft	dc.l $40690000,$9DC5ADA8,$2B70B59D    ;10 ^ 32
1601.1Smycroft	dc.l $40D30000,$C2781F49,$FFCFA6D5    ;10 ^ 64
1611.1Smycroft	dc.l $41A80000,$93BA47C9,$80E98CDF    ;10 ^ 128
1621.1Smycroft	dc.l $43510000,$AA7EEBFB,$9DF9DE8D    ;10 ^ 256
1631.1Smycroft	dc.l $46A30000,$E319A0AE,$A60E91C6    ;10 ^ 512
1641.1Smycroft	dc.l $4D480000,$C9767586,$81750C17    ;10 ^ 1024
1651.1Smycroft	dc.l $5A920000,$9E8B3B5D,$C53D5DE5    ;10 ^ 2048
1661.1Smycroft	dc.l $75250000,$C4605202,$8A20979A    ;10 ^ 4096
1671.1Smycroft*round to positive infinity
1681.1SmycroftBIGRP:
1691.1Smycroft	dc.l $3ffe0000,$b17217f7,$d1cf79ac    ;ln(2)
1701.1Smycroft	dc.l $40000000,$935d8ddd,$aaa8ac17    ;ln(10)
1711.1Smycroft	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
1721.1Smycroft
1731.1Smycroft	xdef	PTENRP
1741.1SmycroftPTENRP:
1751.1Smycroft	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
1761.1Smycroft	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
1771.1Smycroft	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
1781.1Smycroft	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
1791.1Smycroft	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
1801.1Smycroft	dc.l $40690000,$9DC5ADA8,$2B70B59E    ;10 ^ 32
1811.1Smycroft	dc.l $40D30000,$C2781F49,$FFCFA6D6    ;10 ^ 64
1821.1Smycroft	dc.l $41A80000,$93BA47C9,$80E98CE0    ;10 ^ 128
1831.1Smycroft	dc.l $43510000,$AA7EEBFB,$9DF9DE8E    ;10 ^ 256
1841.1Smycroft	dc.l $46A30000,$E319A0AE,$A60E91C7    ;10 ^ 512
1851.1Smycroft	dc.l $4D480000,$C9767586,$81750C18    ;10 ^ 1024
1861.1Smycroft	dc.l $5A920000,$9E8B3B5D,$C53D5DE6    ;10 ^ 2048
1871.1Smycroft	dc.l $75250000,$C4605202,$8A20979B    ;10 ^ 4096
1881.1Smycroft
1891.1Smycroft	xref	nrm_zero
1901.1Smycroft	xref	decbin
1911.1Smycroft	xref	round
1921.1Smycroft
1931.1Smycroft	xdef    get_op
1941.1Smycroft	xdef    uns_getop
1951.1Smycroft	xdef    uni_getop
1961.1Smycroftget_op:
1971.1Smycroft	clr.b	DY_MO_FLG(a6)
1981.1Smycroft	tst.b	UFLG_TMP(a6)	;test flag for unsupp/unimp state
1991.4Sbriggs	beq.b	short_uni_getop
2001.1Smycroft
2011.1Smycroftuns_getop:
2021.1Smycroft	btst.b	#direction_bit,CMDREG1B(a6)
2031.1Smycroft	bne.w	opclass3	;branch if a fmove out (any kind)
2041.1Smycroft	btst.b	#6,CMDREG1B(a6)
2051.1Smycroft	beq.b	uns_notpacked
2061.1Smycroft
2071.1Smycroft	bfextu	CMDREG1B(a6){3:3},d0
2081.1Smycroft	cmp.b	#3,d0
2091.1Smycroft	beq.w	pack_source	;check for a packed src op, branch if so
2101.1Smycroftuns_notpacked:
2111.1Smycroft	bsr	chk_dy_mo	;set the dyadic/monadic flag
2121.1Smycroft	tst.b	DY_MO_FLG(a6)
2131.1Smycroft	beq.b	src_op_ck	;if monadic, go check src op
2141.1Smycroft*				;else, check dst op (fall through)
2151.1Smycroft
2161.1Smycroft	btst.b	#7,DTAG(a6)
2171.1Smycroft	beq.b	src_op_ck	;if dst op is norm, check src op
2181.1Smycroft	bra.b	dst_ex_dnrm	;else, handle destination unnorm/dnrm
2191.1Smycroft
2201.1Smycroftuni_getop:
2211.4Sbriggsshort_uni_getop:
2221.1Smycroft	bfextu	CMDREG1B(a6){0:6},d0 ;get opclass and src fields
2231.1Smycroft	cmpi.l	#$17,d0		;if op class and size fields are $17, 
2241.1Smycroft*				;it is FMOVECR; if not, continue
2251.1Smycroft*
2261.1Smycroft* If the instruction is fmovecr, exit get_op.  It is handled
2271.1Smycroft* in do_func and smovecr.sa.
2281.1Smycroft*
2291.1Smycroft	bne.w	not_fmovecr	;handle fmovecr as an unimplemented inst
2301.1Smycroft	rts
2311.1Smycroft
2321.1Smycroftnot_fmovecr:
2331.1Smycroft	btst.b	#E1,E_BYTE(a6)	;if set, there is a packed operand
2341.1Smycroft	bne.w	pack_source	;check for packed src op, branch if so
2351.1Smycroft
2361.1Smycroft* The following lines of are coded to optimize on normalized operands
2371.1Smycroft	move.b	STAG(a6),d0
2381.1Smycroft	or.b	DTAG(a6),d0	;check if either of STAG/DTAG msb set
2391.1Smycroft	bmi.b	dest_op_ck	;if so, some op needs to be fixed
2401.1Smycroft	rts
2411.1Smycroft
2421.1Smycroftdest_op_ck:
2431.1Smycroft	btst.b	#7,DTAG(a6)	;check for unsupported data types in
2441.1Smycroft	beq.b	src_op_ck	;the destination, if not, check src op
2451.1Smycroft	bsr	chk_dy_mo	;set dyadic/monadic flag
2461.1Smycroft	tst.b	DY_MO_FLG(a6)	;
2471.1Smycroft	beq.b	src_op_ck	;if monadic, check src op
2481.1Smycroft*
2491.1Smycroft* At this point, destination has an extended denorm or unnorm.
2501.1Smycroft*
2511.1Smycroftdst_ex_dnrm:
2521.1Smycroft	move.w	FPTEMP_EX(a6),d0 ;get destination exponent
2531.1Smycroft	andi.w	#$7fff,d0	;mask sign, check if exp = 0000
2541.1Smycroft	beq.b	src_op_ck	;if denorm then check source op.
2551.1Smycroft*				;denorms are taken care of in res_func 
2561.1Smycroft*				;(unsupp) or do_func (unimp)
2571.1Smycroft*				;else unnorm fall through
2581.1Smycroft	lea.l	FPTEMP(a6),a0	;point a0 to dop - used in mk_norm
2591.1Smycroft	bsr	mk_norm		;go normalize - mk_norm returns:
2601.1Smycroft*				;L_SCR1{7:5} = operand tag 
2611.1Smycroft*				;	(000 = norm, 100 = denorm)
2621.1Smycroft*				;L_SCR1{4} = fpte15 or ete15 
2631.1Smycroft*				;	0 = exp >  $3fff
2641.1Smycroft*				;	1 = exp <= $3fff
2651.1Smycroft*				;and puts the normalized num back 
2661.1Smycroft*				;on the fsave stack
2671.1Smycroft*
2681.1Smycroft	move.b L_SCR1(a6),DTAG(a6) ;write the new tag & fpte15 
2691.1Smycroft*				;to the fsave stack and fall 
2701.1Smycroft*				;through to check source operand
2711.1Smycroft*
2721.1Smycroftsrc_op_ck:
2731.1Smycroft	btst.b	#7,STAG(a6)
2741.1Smycroft	beq.w	end_getop	;check for unsupported data types on the
2751.1Smycroft*				;source operand
2761.1Smycroft	btst.b	#5,STAG(a6)
2771.1Smycroft	bne.b	src_sd_dnrm	;if bit 5 set, handle sgl/dbl denorms
2781.1Smycroft*
2791.1Smycroft* At this point only unnorms or extended denorms are possible.
2801.1Smycroft*
2811.1Smycroftsrc_ex_dnrm:
2821.1Smycroft	move.w	ETEMP_EX(a6),d0 ;get source exponent
2831.1Smycroft	andi.w	#$7fff,d0	;mask sign, check if exp = 0000
2841.1Smycroft	beq.w	end_getop	;if denorm then exit, denorms are 
2851.1Smycroft*				;handled in do_func
2861.1Smycroft	lea.l	ETEMP(a6),a0	;point a0 to sop - used in mk_norm
2871.1Smycroft	bsr	mk_norm		;go normalize - mk_norm returns:
2881.1Smycroft*				;L_SCR1{7:5} = operand tag 
2891.1Smycroft*				;	(000 = norm, 100 = denorm)
2901.1Smycroft*				;L_SCR1{4} = fpte15 or ete15 
2911.1Smycroft*				;	0 = exp >  $3fff
2921.1Smycroft*				;	1 = exp <= $3fff
2931.1Smycroft*				;and puts the normalized num back 
2941.1Smycroft*				;on the fsave stack
2951.1Smycroft*
2961.1Smycroft	move.b	L_SCR1(a6),STAG(a6) ;write the new tag & ete15 
2971.1Smycroft	rts			;end_getop
2981.1Smycroft
2991.1Smycroft*
3001.1Smycroft* At this point, only single or double denorms are possible.
3011.1Smycroft* If the inst is not fmove, normalize the source.  If it is,
3021.1Smycroft* do nothing to the input.
3031.1Smycroft*
3041.1Smycroftsrc_sd_dnrm:
3051.1Smycroft	btst.b	#4,CMDREG1B(a6)	;differentiate between sgl/dbl denorm
3061.1Smycroft	bne.b	is_double
3071.1Smycroftis_single:
3081.1Smycroft	move.w	#$3f81,d1	;write bias for sgl denorm
3091.1Smycroft	bra.b	common		;goto the common code
3101.1Smycroftis_double:
3111.1Smycroft	move.w	#$3c01,d1	;write the bias for a dbl denorm
3121.1Smycroftcommon:
3131.1Smycroft	btst.b	#sign_bit,ETEMP_EX(a6) ;grab sign bit of mantissa
3141.1Smycroft	beq.b	pos	
3151.1Smycroft	bset	#15,d1		;set sign bit because it is negative
3161.1Smycroftpos:
3171.1Smycroft	move.w	d1,ETEMP_EX(a6)
3181.1Smycroft*				;put exponent on stack
3191.1Smycroft
3201.1Smycroft	move.w	CMDREG1B(a6),d1
3211.1Smycroft	and.w	#$e3ff,d1	;clear out source specifier
3221.1Smycroft	or.w	#$0800,d1	;set source specifier to extended prec
3231.1Smycroft	move.w	d1,CMDREG1B(a6)	;write back to the command word in stack
3241.1Smycroft*				;this is needed to fix unsupp data stack
3251.1Smycroft	lea.l	ETEMP(a6),a0	;point a0 to sop
3261.1Smycroft	
3271.1Smycroft	bsr	mk_norm		;convert sgl/dbl denorm to norm
3281.1Smycroft	move.b	L_SCR1(a6),STAG(a6) ;put tag into source tag reg - d0
3291.1Smycroft	rts			;end_getop
3301.1Smycroft*
3311.1Smycroft* At this point, the source is definitely packed, whether
3321.1Smycroft* instruction is dyadic or monadic is still unknown
3331.1Smycroft*
3341.1Smycroftpack_source:
3351.1Smycroft	move.l	FPTEMP_LO(a6),ETEMP(a6)	;write ms part of packed 
3361.1Smycroft*				;number to etemp slot
3371.1Smycroft	bsr	chk_dy_mo	;set dyadic/monadic flag
3381.1Smycroft	bsr	unpack
3391.1Smycroft
3401.1Smycroft	tst.b	DY_MO_FLG(a6)
3411.1Smycroft	beq.b	end_getop	;if monadic, exit
3421.1Smycroft*				;else, fix FPTEMP
3431.1Smycroftpack_dya:
3441.1Smycroft	bfextu	CMDREG1B(a6){6:3},d0 ;extract dest fp reg
3451.1Smycroft	move.l	#7,d1
3461.1Smycroft	sub.l	d0,d1
3471.1Smycroft	clr.l	d0
3481.1Smycroft	bset.l	d1,d0		;set up d0 as a dynamic register mask
3491.1Smycroft	fmovem.x d0,FPTEMP(a6)	;write to FPTEMP
3501.1Smycroft
3511.1Smycroft	btst.b	#7,DTAG(a6)	;check dest tag for unnorm or denorm
3521.1Smycroft	bne.w	dst_ex_dnrm	;else, handle the unnorm or ext denorm
3531.1Smycroft*
3541.1Smycroft* Dest is not denormalized.  Check for norm, and set fpte15 
3551.1Smycroft* accordingly.
3561.1Smycroft*
3571.1Smycroft	move.b	DTAG(a6),d0
3581.1Smycroft	andi.b	#$f0,d0		;strip to only dtag:fpte15
3591.1Smycroft	tst.b	d0		;check for normalized value
3601.1Smycroft	bne.b	end_getop	;if inf/nan/zero leave get_op
3611.1Smycroft	move.w	FPTEMP_EX(a6),d0
3621.1Smycroft	andi.w	#$7fff,d0
3631.1Smycroft	cmpi.w	#$3fff,d0	;check if fpte15 needs setting
3641.1Smycroft	bge.b	end_getop	;if >= $3fff, leave fpte15=0
3651.1Smycroft	or.b	#$10,DTAG(a6)
3661.1Smycroft	bra.b	end_getop
3671.1Smycroft
3681.1Smycroft*
3691.1Smycroft* At this point, it is either an fmoveout packed, unnorm or denorm
3701.1Smycroft*
3711.1Smycroftopclass3:
3721.1Smycroft	clr.b	DY_MO_FLG(a6)	;set dyadic/monadic flag to monadic
3731.1Smycroft	bfextu	CMDREG1B(a6){4:2},d0
3741.1Smycroft	cmpi.b	#3,d0
3751.1Smycroft	bne.w	src_ex_dnrm	;if not equal, must be unnorm or denorm
3761.1Smycroft*				;else it is a packed move out
3771.1Smycroft*				;exit
3781.1Smycroftend_getop:
3791.1Smycroft	rts
3801.1Smycroft
3811.1Smycroft*
3821.1Smycroft* Sets the DY_MO_FLG correctly. This is used only on if it is an
3831.5Sandvar* unsupported data type exception.  Set if dyadic.
3841.1Smycroft*
3851.1Smycroftchk_dy_mo:
3861.1Smycroft	move.w	CMDREG1B(a6),d0	
3871.1Smycroft	btst.l	#5,d0		;testing extension command word
3881.1Smycroft	beq.b	set_mon		;if bit 5 = 0 then monadic
3891.1Smycroft	btst.l	#4,d0		;know that bit 5 = 1
3901.1Smycroft	beq.b	set_dya		;if bit 4 = 0 then dyadic
3911.1Smycroft	andi.w	#$007f,d0	;get rid of all but extension bits {6:0}
3921.1Smycroft	cmpi.w 	#$0038,d0	;if extension = $38 then fcmp (dyadic)
3931.1Smycroft	bne.b	set_mon
3941.1Smycroftset_dya:
3951.1Smycroft	st.b	DY_MO_FLG(a6)	;set the inst flag type to dyadic
3961.1Smycroft	rts
3971.1Smycroftset_mon:
3981.1Smycroft	clr.b	DY_MO_FLG(a6)	;set the inst flag type to monadic
3991.1Smycroft	rts
4001.1Smycroft*
4011.1Smycroft*	MK_NORM
4021.1Smycroft*
4031.1Smycroft* Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
4041.1Smycroft* exception if denorm.
4051.1Smycroft*
4061.1Smycroft* CASE opclass 0x0 unsupp
4071.1Smycroft*	mk_norm till msb set
4081.1Smycroft*	set tag = norm
4091.1Smycroft*
4101.1Smycroft* CASE opclass 0x0 unimp
4111.1Smycroft*	mk_norm till msb set or exp = 0
4121.1Smycroft*	if integer bit = 0
4131.1Smycroft*	   tag = denorm
4141.1Smycroft*	else
4151.1Smycroft*	   tag = norm
4161.1Smycroft*
4171.1Smycroft* CASE opclass 011 unsupp
4181.1Smycroft*	mk_norm till msb set or exp = 0
4191.1Smycroft*	if integer bit = 0
4201.1Smycroft*	   tag = denorm
4211.1Smycroft*	   set unfl_nmcexe = 1
4221.1Smycroft*	else
4231.1Smycroft*	   tag = norm
4241.1Smycroft*
4251.1Smycroft* if exp <= $3fff
4261.1Smycroft*   set ete15 or fpte15 = 1
4271.1Smycroft* else set ete15 or fpte15 = 0
4281.1Smycroft
4291.1Smycroft* input:
4301.1Smycroft*	a0 = points to operand to be normalized
4311.1Smycroft* output:
4321.1Smycroft*	L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
4331.1Smycroft*	L_SCR1{4}   = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
4341.1Smycroft*	the normalized operand is placed back on the fsave stack
4351.1Smycroftmk_norm:	
4361.1Smycroft	clr.l	L_SCR1(a6)
4371.1Smycroft	bclr.b	#sign_bit,LOCAL_EX(a0)
4381.1Smycroft	sne	LOCAL_SGN(a0)	;transform into internal extended format
4391.1Smycroft
4401.1Smycroft	cmpi.b	#$2c,1+EXC_VEC(a6) ;check if unimp
4411.1Smycroft	bne.b	uns_data	;branch if unsupp
4421.1Smycroft	bsr	uni_inst	;call if unimp (opclass 0x0)
4431.1Smycroft	bra.b	reload
4441.1Smycroftuns_data:
4451.1Smycroft	btst.b	#direction_bit,CMDREG1B(a6) ;check transfer direction
4461.1Smycroft	bne.b	bit_set		;branch if set (opclass 011)
4471.1Smycroft	bsr	uns_opx		;call if opclass 0x0
4481.1Smycroft	bra.b	reload
4491.1Smycroftbit_set:
4501.1Smycroft	bsr	uns_op3		;opclass 011
4511.1Smycroftreload:
4521.1Smycroft	cmp.w	#$3fff,LOCAL_EX(a0) ;if exp > $3fff
4531.1Smycroft	bgt.b	end_mk		;   fpte15/ete15 already set to 0
4541.1Smycroft	bset.b	#4,L_SCR1(a6)	;else set fpte15/ete15 to 1
4551.1Smycroft*				;calling routine actually sets the 
4561.1Smycroft*				;value on the stack (along with the 
4571.1Smycroft*				;tag), since this routine doesn't 
4581.1Smycroft*				;know if it should set ete15 or fpte15
4591.1Smycroft*				;ie, it doesn't know if this is the 
4601.1Smycroft*				;src op or dest op.
4611.1Smycroftend_mk:
4621.1Smycroft	bfclr	LOCAL_SGN(a0){0:8}
4631.1Smycroft	beq.b	end_mk_pos
4641.1Smycroft	bset.b	#sign_bit,LOCAL_EX(a0) ;convert back to IEEE format
4651.1Smycroftend_mk_pos:
4661.1Smycroft	rts
4671.1Smycroft*
4681.1Smycroft*     CASE opclass 011 unsupp
4691.1Smycroft*
4701.1Smycroftuns_op3:
4711.1Smycroft	bsr	nrm_zero	;normalize till msb = 1 or exp = zero
4721.1Smycroft	btst.b	#7,LOCAL_HI(a0)	;if msb = 1
4731.1Smycroft	bne.b	no_unfl		;then branch
4741.1Smycroftset_unfl:
4751.2Smycroft	or.b	#dnrm_tag,L_SCR1(a6) ;set denorm tag
4761.1Smycroft	bset.b	#unfl_bit,FPSR_EXCEPT(a6) ;set unfl exception bit
4771.1Smycroftno_unfl:
4781.1Smycroft	rts
4791.1Smycroft*
4801.1Smycroft*     CASE opclass 0x0 unsupp
4811.1Smycroft*
4821.1Smycroftuns_opx:
4831.1Smycroft	bsr	nrm_zero	;normalize the number
4841.1Smycroft	btst.b	#7,LOCAL_HI(a0)	;check if integer bit (j-bit) is set 
4851.1Smycroft	beq.b	uns_den		;if clear then now have a denorm
4861.1Smycroftuns_nrm:
4871.1Smycroft	or.b	#norm_tag,L_SCR1(a6) ;set tag to norm
4881.1Smycroft	rts
4891.1Smycroftuns_den:
4901.1Smycroft	or.b	#dnrm_tag,L_SCR1(a6) ;set tag to denorm
4911.1Smycroft	rts
4921.1Smycroft*
4931.1Smycroft*     CASE opclass 0x0 unimp
4941.1Smycroft*
4951.1Smycroftuni_inst:
4961.1Smycroft	bsr	nrm_zero
4971.1Smycroft	btst.b	#7,LOCAL_HI(a0)	;check if integer bit (j-bit) is set 
4981.1Smycroft	beq.b	uni_den		;if clear then now have a denorm
4991.1Smycroftuni_nrm:
5001.1Smycroft	or.b	#norm_tag,L_SCR1(a6) ;set tag to norm
5011.1Smycroft	rts
5021.1Smycroftuni_den:
5031.1Smycroft	or.b	#dnrm_tag,L_SCR1(a6) ;set tag to denorm
5041.1Smycroft	rts
5051.1Smycroft
5061.1Smycroft*
5071.1Smycroft*	Decimal to binary conversion
5081.1Smycroft*
5091.1Smycroft* Special cases of inf and NaNs are completed outside of decbin.  
5101.1Smycroft* If the input is an snan, the snan bit is not set.
5111.1Smycroft* 
5121.1Smycroft* input:
5131.1Smycroft*	ETEMP(a6)	- points to packed decimal string in memory
5141.1Smycroft* output:
5151.1Smycroft*	fp0	- contains packed string converted to extended precision
5161.1Smycroft*	ETEMP	- same as fp0
5171.1Smycroftunpack:
5181.1Smycroft	move.w	CMDREG1B(a6),d0	;examine command word, looking for fmove's
5191.1Smycroft	and.w	#$3b,d0
5201.1Smycroft	beq	move_unpack	;special handling for fmove: must set FPSR_CC
5211.1Smycroft
5221.1Smycroft	move.w	ETEMP(a6),d0	;get word with inf information
5231.1Smycroft	bfextu	d0{20:12},d1	;get exponent into d1
5241.1Smycroft	cmpi.w	#$0fff,d1	;test for inf or NaN
5251.1Smycroft	bne.b	try_zero	;if not equal, it is not special
5261.1Smycroft	bfextu	d0{17:3},d1	;get SE and y bits into d1
5271.1Smycroft	cmpi.w	#7,d1		;SE and y bits must be on for special
5281.1Smycroft	bne.b	try_zero	;if not on, it is not special
5291.1Smycroft*input is of the special cases of inf and NaN
5301.1Smycroft	tst.l	ETEMP_HI(a6)	;check ms mantissa
5311.1Smycroft	bne.b	fix_nan		;if non-zero, it is a NaN
5321.1Smycroft	tst.l	ETEMP_LO(a6)	;check ls mantissa
5331.1Smycroft	bne.b	fix_nan		;if non-zero, it is a NaN
5341.1Smycroft	bra.w	finish		;special already on stack
5351.1Smycroftfix_nan:
5361.1Smycroft	btst.b	#signan_bit,ETEMP_HI(a6) ;test for snan
5371.1Smycroft	bne.w	finish
5381.1Smycroft	or.l	#snaniop_mask,USER_FPSR(a6) ;always set snan if it is so
5391.1Smycroft	bra.w	finish
5401.1Smycrofttry_zero:
5411.1Smycroft	move.w	ETEMP_EX+2(a6),d0 ;get word 4
5421.1Smycroft	andi.w	#$000f,d0	;clear all but last ni(y)bble
5431.1Smycroft	tst.w	d0		;check for zero.
5441.1Smycroft	bne.w	not_spec
5451.1Smycroft	tst.l	ETEMP_HI(a6)	;check words 3 and 2
5461.1Smycroft	bne.w	not_spec
5471.1Smycroft	tst.l	ETEMP_LO(a6)	;check words 1 and 0
5481.1Smycroft	bne.w	not_spec
5491.1Smycroft	tst.l	ETEMP(a6)	;test sign of the zero
5501.1Smycroft	bge.b	pos_zero
5511.1Smycroft	move.l	#$80000000,ETEMP(a6) ;write neg zero to etemp
5521.1Smycroft	clr.l	ETEMP_HI(a6)
5531.1Smycroft	clr.l	ETEMP_LO(a6)
5541.1Smycroft	bra.w	finish
5551.1Smycroftpos_zero:
5561.1Smycroft	clr.l	ETEMP(a6)
5571.1Smycroft	clr.l	ETEMP_HI(a6)
5581.1Smycroft	clr.l	ETEMP_LO(a6)
5591.1Smycroft	bra.w	finish
5601.1Smycroft
5611.1Smycroftnot_spec:
5621.1Smycroft	fmovem.x fp0-fp1,-(a7)	;save fp0 - decbin returns in it
5631.1Smycroft	bsr	decbin
5641.1Smycroft	fmove.x fp0,ETEMP(a6)	;put the unpacked sop in the fsave stack
5651.1Smycroft	fmovem.x (a7)+,fp0-fp1
5661.1Smycroft	fmove.l	#0,FPSR		;clr fpsr from decbin
5671.1Smycroft	bra	finish
5681.1Smycroft
5691.1Smycroft*
5701.1Smycroft* Special handling for packed move in:  Same results as all other
5711.1Smycroft* packed cases, but we must set the FPSR condition codes properly.
5721.1Smycroft*
5731.1Smycroftmove_unpack:
5741.1Smycroft	move.w	ETEMP(a6),d0	;get word with inf information
5751.1Smycroft	bfextu	d0{20:12},d1	;get exponent into d1
5761.1Smycroft	cmpi.w	#$0fff,d1	;test for inf or NaN
5771.1Smycroft	bne.b	mtry_zero	;if not equal, it is not special
5781.1Smycroft	bfextu	d0{17:3},d1	;get SE and y bits into d1
5791.1Smycroft	cmpi.w	#7,d1		;SE and y bits must be on for special
5801.1Smycroft	bne.b	mtry_zero	;if not on, it is not special
5811.1Smycroft*input is of the special cases of inf and NaN
5821.1Smycroft	tst.l	ETEMP_HI(a6)	;check ms mantissa
5831.1Smycroft	bne.b	mfix_nan		;if non-zero, it is a NaN
5841.1Smycroft	tst.l	ETEMP_LO(a6)	;check ls mantissa
5851.1Smycroft	bne.b	mfix_nan		;if non-zero, it is a NaN
5861.1Smycroft*input is inf
5871.1Smycroft	or.l	#inf_mask,USER_FPSR(a6) ;set I bit
5881.1Smycroft	tst.l	ETEMP(a6)	;check sign
5891.1Smycroft	bge.w	finish
5901.1Smycroft	or.l	#neg_mask,USER_FPSR(a6) ;set N bit
5911.1Smycroft	bra.w	finish		;special already on stack
5921.1Smycroftmfix_nan:
5931.1Smycroft	or.l	#nan_mask,USER_FPSR(a6) ;set NaN bit
5941.1Smycroft	move.b	#nan_tag,STAG(a6)	;set stag to NaN
5951.1Smycroft	btst.b	#signan_bit,ETEMP_HI(a6) ;test for snan
5961.1Smycroft	bne.b	mn_snan
5971.1Smycroft	or.l	#snaniop_mask,USER_FPSR(a6) ;set snan bit
5981.1Smycroft	btst.b	#snan_bit,FPCR_ENABLE(a6) ;test for snan enabled
5991.1Smycroft	bne.b	mn_snan
6001.1Smycroft	bset.b	#signan_bit,ETEMP_HI(a6) ;force snans to qnans
6011.1Smycroftmn_snan:
6021.1Smycroft	tst.l	ETEMP(a6)	;check for sign
6031.1Smycroft	bge.w	finish		;if clr, go on
6041.1Smycroft	or.l	#neg_mask,USER_FPSR(a6) ;set N bit
6051.1Smycroft	bra.w	finish
6061.1Smycroft
6071.1Smycroftmtry_zero:
6081.1Smycroft	move.w	ETEMP_EX+2(a6),d0 ;get word 4
6091.1Smycroft	andi.w	#$000f,d0	;clear all but last ni(y)bble
6101.1Smycroft	tst.w	d0		;check for zero.
6111.1Smycroft	bne.b	mnot_spec
6121.1Smycroft	tst.l	ETEMP_HI(a6)	;check words 3 and 2
6131.1Smycroft	bne.b	mnot_spec
6141.1Smycroft	tst.l	ETEMP_LO(a6)	;check words 1 and 0
6151.1Smycroft	bne.b	mnot_spec
6161.1Smycroft	tst.l	ETEMP(a6)	;test sign of the zero
6171.1Smycroft	bge.b	mpos_zero
6181.1Smycroft	or.l	#neg_mask+z_mask,USER_FPSR(a6) ;set N and Z
6191.1Smycroft	move.l	#$80000000,ETEMP(a6) ;write neg zero to etemp
6201.1Smycroft	clr.l	ETEMP_HI(a6)
6211.1Smycroft	clr.l	ETEMP_LO(a6)
6221.1Smycroft	bra.b	finish
6231.1Smycroftmpos_zero:
6241.1Smycroft	or.l	#z_mask,USER_FPSR(a6) ;set Z
6251.1Smycroft	clr.l	ETEMP(a6)
6261.1Smycroft	clr.l	ETEMP_HI(a6)
6271.1Smycroft	clr.l	ETEMP_LO(a6)
6281.1Smycroft	bra.b	finish
6291.1Smycroft
6301.1Smycroftmnot_spec:
6311.1Smycroft	fmovem.x fp0-fp1,-(a7)	;save fp0 ,fp1 - decbin returns in fp0
6321.1Smycroft	bsr	decbin
6331.1Smycroft	fmove.x fp0,ETEMP(a6)
6341.1Smycroft*				;put the unpacked sop in the fsave stack
6351.1Smycroft	fmovem.x (a7)+,fp0-fp1
6361.1Smycroft
6371.1Smycroftfinish:
6381.1Smycroft	move.w	CMDREG1B(a6),d0	;get the command word
6391.1Smycroft	and.w	#$fbff,d0	;change the source specifier field to 
6401.1Smycroft*				;extended (was packed).
6411.1Smycroft	move.w	d0,CMDREG1B(a6)	;write command word back to fsave stack
6421.1Smycroft*				;we need to do this so the 040 will 
6431.1Smycroft*				;re-execute the inst. without taking 
6441.1Smycroft*				;another packed trap.
6451.1Smycroft
6461.1Smycroftfix_stag:
6471.1Smycroft*Converted result is now in etemp on fsave stack, now set the source 
6481.1Smycroft*tag (stag) 
6491.1Smycroft*	if (ete =$7fff) then INF or NAN
6501.1Smycroft*		if (etemp = $x.0----0) then
6511.1Smycroft*			stag = INF
6521.1Smycroft*		else
6531.1Smycroft*			stag = NAN
6541.1Smycroft*	else
6551.1Smycroft*		if (ete = $0000) then
6561.1Smycroft*			stag = ZERO
6571.1Smycroft*		else
6581.1Smycroft*			stag = NORM
6591.1Smycroft*
6601.1Smycroft* Note also that the etemp_15 bit (just right of the stag) must
6611.1Smycroft* be set accordingly.  
6621.1Smycroft*
6631.1Smycroft	move.w		ETEMP_EX(a6),d1
6641.1Smycroft	andi.w		#$7fff,d1   ;strip sign
6651.1Smycroft	cmp.w  		#$7fff,d1
6661.1Smycroft	bne.b  		z_or_nrm
6671.1Smycroft	move.l		ETEMP_HI(a6),d1
6681.1Smycroft	bne.b		is_nan
6691.1Smycroft	move.l		ETEMP_LO(a6),d1
6701.1Smycroft	bne.b		is_nan
6711.1Smycroftis_inf:
6721.1Smycroft	move.b		#$40,STAG(a6)
6731.1Smycroft	move.l		#$40,d0
6741.1Smycroft	rts
6751.1Smycroftis_nan:
6761.1Smycroft	move.b		#$60,STAG(a6)
6771.1Smycroft	move.l		#$60,d0
6781.1Smycroft	rts
6791.1Smycroftz_or_nrm:
6801.1Smycroft	tst.w		d1  
6811.1Smycroft	bne.b		is_nrm
6821.1Smycroftis_zro:
6831.1Smycroft* For a zero, set etemp_15
6841.1Smycroft	move.b		#$30,STAG(a6)
6851.1Smycroft	move.l		#$20,d0
6861.1Smycroft	rts
6871.1Smycroftis_nrm:
6881.1Smycroft* For a norm, check if the exp <= $3fff; if so, set etemp_15
6891.1Smycroft	cmpi.w		#$3fff,d1
6901.1Smycroft	ble.b		set_bit15
6911.2Smycroft	clr.b		STAG(a6)
6921.1Smycroft	bra.b		end_is_nrm
6931.1Smycroftset_bit15:
6941.1Smycroft	move.b		#$10,STAG(a6)
6951.1Smycroftend_is_nrm:
6961.2Smycroft	clr.l		d0
6971.1Smycroftend_fix:
6981.1Smycroft	rts
6991.1Smycroft 
7001.1Smycroftend_get:
7011.1Smycroft	rts
7021.1Smycroft	end
703