cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

get_op.S (20372B)


      1|
      2|	get_op.sa 3.6 5/19/92
      3|
      4|	get_op.sa 3.5 4/26/91
      5|
      6|  Description: This routine is called by the unsupported format/data
      7| type exception handler ('unsupp' - vector 55) and the unimplemented
      8| instruction exception handler ('unimp' - vector 11).  'get_op'
      9| determines the opclass (0, 2, or 3) and branches to the
     10| opclass handler routine.  See 68881/2 User's Manual table 4-11
     11| for a description of the opclasses.
     12|
     13| For UNSUPPORTED data/format (exception vector 55) and for
     14| UNIMPLEMENTED instructions (exception vector 11) the following
     15| applies:
     16|
     17| - For unnormalized numbers (opclass 0, 2, or 3) the
     18| number(s) is normalized and the operand type tag is updated.
     19|
     20| - For a packed number (opclass 2) the number is unpacked and the
     21| operand type tag is updated.
     22|
     23| - For denormalized numbers (opclass 0 or 2) the number(s) is not
     24| changed but passed to the next module.  The next module for
     25| unimp is do_func, the next module for unsupp is res_func.
     26|
     27| For UNSUPPORTED data/format (exception vector 55) only the
     28| following applies:
     29|
     30| - If there is a move out with a packed number (opclass 3) the
     31| number is packed and written to user memory.  For the other
     32| opclasses the number(s) are written back to the fsave stack
     33| and the instruction is then restored back into the '040.  The
     34| '040 is then able to complete the instruction.
     35|
     36| For example:
     37| fadd.x fpm,fpn where the fpm contains an unnormalized number.
     38| The '040 takes an unsupported data trap and gets to this
     39| routine.  The number is normalized, put back on the stack and
     40| then an frestore is done to restore the instruction back into
     41| the '040.  The '040 then re-executes the fadd.x fpm,fpn with
     42| a normalized number in the source and the instruction is
     43| successful.
     44|
     45| Next consider if in the process of normalizing the un-
     46| normalized number it becomes a denormalized number.  The
     47| routine which converts the unnorm to a norm (called mk_norm)
     48| detects this and tags the number as a denorm.  The routine
     49| res_func sees the denorm tag and converts the denorm to a
     50| norm.  The instruction is then restored back into the '040
     51| which re_executes the instruction.
     52|
     53|
     54|		Copyright (C) Motorola, Inc. 1990
     55|			All Rights Reserved
     56|
     57|       For details on the license for this file, please see the
     58|       file, README, in this same directory.
     59
     60GET_OP:    |idnt    2,1 | Motorola 040 Floating Point Software Package
     61
     62	|section	8
     63
     64#include "fpsp.h"
     65
     66	.global	PIRN,PIRZRM,PIRP
     67	.global	SMALRN,SMALRZRM,SMALRP
     68	.global	BIGRN,BIGRZRM,BIGRP
     69
     70PIRN:
     71	.long 0x40000000,0xc90fdaa2,0x2168c235    |pi
     72PIRZRM:
     73	.long 0x40000000,0xc90fdaa2,0x2168c234    |pi
     74PIRP:
     75	.long 0x40000000,0xc90fdaa2,0x2168c235    |pi
     76
     77|round to nearest
     78SMALRN:
     79	.long 0x3ffd0000,0x9a209a84,0xfbcff798    |log10(2)
     80	.long 0x40000000,0xadf85458,0xa2bb4a9a    |e
     81	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bc    |log2(e)
     82	.long 0x3ffd0000,0xde5bd8a9,0x37287195    |log10(e)
     83	.long 0x00000000,0x00000000,0x00000000    |0.0
     84| round to zero;round to negative infinity
     85SMALRZRM:
     86	.long 0x3ffd0000,0x9a209a84,0xfbcff798    |log10(2)
     87	.long 0x40000000,0xadf85458,0xa2bb4a9a    |e
     88	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bb    |log2(e)
     89	.long 0x3ffd0000,0xde5bd8a9,0x37287195    |log10(e)
     90	.long 0x00000000,0x00000000,0x00000000    |0.0
     91| round to positive infinity
     92SMALRP:
     93	.long 0x3ffd0000,0x9a209a84,0xfbcff799    |log10(2)
     94	.long 0x40000000,0xadf85458,0xa2bb4a9b    |e
     95	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bc    |log2(e)
     96	.long 0x3ffd0000,0xde5bd8a9,0x37287195    |log10(e)
     97	.long 0x00000000,0x00000000,0x00000000    |0.0
     98
     99|round to nearest
    100BIGRN:
    101	.long 0x3ffe0000,0xb17217f7,0xd1cf79ac    |ln(2)
    102	.long 0x40000000,0x935d8ddd,0xaaa8ac17    |ln(10)
    103	.long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
    104
    105	.global	PTENRN
    106PTENRN:
    107	.long 0x40020000,0xA0000000,0x00000000    |10 ^ 1
    108	.long 0x40050000,0xC8000000,0x00000000    |10 ^ 2
    109	.long 0x400C0000,0x9C400000,0x00000000    |10 ^ 4
    110	.long 0x40190000,0xBEBC2000,0x00000000    |10 ^ 8
    111	.long 0x40340000,0x8E1BC9BF,0x04000000    |10 ^ 16
    112	.long 0x40690000,0x9DC5ADA8,0x2B70B59E    |10 ^ 32
    113	.long 0x40D30000,0xC2781F49,0xFFCFA6D5    |10 ^ 64
    114	.long 0x41A80000,0x93BA47C9,0x80E98CE0    |10 ^ 128
    115	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8E    |10 ^ 256
    116	.long 0x46A30000,0xE319A0AE,0xA60E91C7    |10 ^ 512
    117	.long 0x4D480000,0xC9767586,0x81750C17    |10 ^ 1024
    118	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE5    |10 ^ 2048
    119	.long 0x75250000,0xC4605202,0x8A20979B    |10 ^ 4096
    120|round to minus infinity
    121BIGRZRM:
    122	.long 0x3ffe0000,0xb17217f7,0xd1cf79ab    |ln(2)
    123	.long 0x40000000,0x935d8ddd,0xaaa8ac16    |ln(10)
    124	.long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
    125
    126	.global	PTENRM
    127PTENRM:
    128	.long 0x40020000,0xA0000000,0x00000000    |10 ^ 1
    129	.long 0x40050000,0xC8000000,0x00000000    |10 ^ 2
    130	.long 0x400C0000,0x9C400000,0x00000000    |10 ^ 4
    131	.long 0x40190000,0xBEBC2000,0x00000000    |10 ^ 8
    132	.long 0x40340000,0x8E1BC9BF,0x04000000    |10 ^ 16
    133	.long 0x40690000,0x9DC5ADA8,0x2B70B59D    |10 ^ 32
    134	.long 0x40D30000,0xC2781F49,0xFFCFA6D5    |10 ^ 64
    135	.long 0x41A80000,0x93BA47C9,0x80E98CDF    |10 ^ 128
    136	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8D    |10 ^ 256
    137	.long 0x46A30000,0xE319A0AE,0xA60E91C6    |10 ^ 512
    138	.long 0x4D480000,0xC9767586,0x81750C17    |10 ^ 1024
    139	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE5    |10 ^ 2048
    140	.long 0x75250000,0xC4605202,0x8A20979A    |10 ^ 4096
    141|round to positive infinity
    142BIGRP:
    143	.long 0x3ffe0000,0xb17217f7,0xd1cf79ac    |ln(2)
    144	.long 0x40000000,0x935d8ddd,0xaaa8ac17    |ln(10)
    145	.long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
    146
    147	.global	PTENRP
    148PTENRP:
    149	.long 0x40020000,0xA0000000,0x00000000    |10 ^ 1
    150	.long 0x40050000,0xC8000000,0x00000000    |10 ^ 2
    151	.long 0x400C0000,0x9C400000,0x00000000    |10 ^ 4
    152	.long 0x40190000,0xBEBC2000,0x00000000    |10 ^ 8
    153	.long 0x40340000,0x8E1BC9BF,0x04000000    |10 ^ 16
    154	.long 0x40690000,0x9DC5ADA8,0x2B70B59E    |10 ^ 32
    155	.long 0x40D30000,0xC2781F49,0xFFCFA6D6    |10 ^ 64
    156	.long 0x41A80000,0x93BA47C9,0x80E98CE0    |10 ^ 128
    157	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8E    |10 ^ 256
    158	.long 0x46A30000,0xE319A0AE,0xA60E91C7    |10 ^ 512
    159	.long 0x4D480000,0xC9767586,0x81750C18    |10 ^ 1024
    160	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE6    |10 ^ 2048
    161	.long 0x75250000,0xC4605202,0x8A20979B    |10 ^ 4096
    162
    163	|xref	nrm_zero
    164	|xref	decbin
    165	|xref	round
    166
    167	.global    get_op
    168	.global    uns_getop
    169	.global    uni_getop
    170get_op:
    171	clrb	DY_MO_FLG(%a6)
    172	tstb	UFLG_TMP(%a6)	|test flag for unsupp/unimp state
    173	beq	uni_getop
    174
    175uns_getop:
    176	btstb	#direction_bit,CMDREG1B(%a6)
    177	bne	opclass3	|branch if a fmove out (any kind)
    178	btstb	#6,CMDREG1B(%a6)
    179	beqs	uns_notpacked
    180
    181	bfextu	CMDREG1B(%a6){#3:#3},%d0
    182	cmpb	#3,%d0
    183	beq	pack_source	|check for a packed src op, branch if so
    184uns_notpacked:
    185	bsr	chk_dy_mo	|set the dyadic/monadic flag
    186	tstb	DY_MO_FLG(%a6)
    187	beqs	src_op_ck	|if monadic, go check src op
    188|				;else, check dst op (fall through)
    189
    190	btstb	#7,DTAG(%a6)
    191	beqs	src_op_ck	|if dst op is norm, check src op
    192	bras	dst_ex_dnrm	|else, handle destination unnorm/dnrm
    193
    194uni_getop:
    195	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
    196	cmpil	#0x17,%d0		|if op class and size fields are $17,
    197|				;it is FMOVECR; if not, continue
    198|
    199| If the instruction is fmovecr, exit get_op.  It is handled
    200| in do_func and smovecr.sa.
    201|
    202	bne	not_fmovecr	|handle fmovecr as an unimplemented inst
    203	rts
    204
    205not_fmovecr:
    206	btstb	#E1,E_BYTE(%a6)	|if set, there is a packed operand
    207	bne	pack_source	|check for packed src op, branch if so
    208
    209| The following lines of are coded to optimize on normalized operands
    210	moveb	STAG(%a6),%d0
    211	orb	DTAG(%a6),%d0	|check if either of STAG/DTAG msb set
    212	bmis	dest_op_ck	|if so, some op needs to be fixed
    213	rts
    214
    215dest_op_ck:
    216	btstb	#7,DTAG(%a6)	|check for unsupported data types in
    217	beqs	src_op_ck	|the destination, if not, check src op
    218	bsr	chk_dy_mo	|set dyadic/monadic flag
    219	tstb	DY_MO_FLG(%a6)	|
    220	beqs	src_op_ck	|if monadic, check src op
    221|
    222| At this point, destination has an extended denorm or unnorm.
    223|
    224dst_ex_dnrm:
    225	movew	FPTEMP_EX(%a6),%d0 |get destination exponent
    226	andiw	#0x7fff,%d0	|mask sign, check if exp = 0000
    227	beqs	src_op_ck	|if denorm then check source op.
    228|				;denorms are taken care of in res_func
    229|				;(unsupp) or do_func (unimp)
    230|				;else unnorm fall through
    231	leal	FPTEMP(%a6),%a0	|point a0 to dop - used in mk_norm
    232	bsr	mk_norm		|go normalize - mk_norm returns:
    233|				;L_SCR1{7:5} = operand tag
    234|				;	(000 = norm, 100 = denorm)
    235|				;L_SCR1{4} = fpte15 or ete15
    236|				;	0 = exp >  $3fff
    237|				;	1 = exp <= $3fff
    238|				;and puts the normalized num back
    239|				;on the fsave stack
    240|
    241	moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15
    242|				;to the fsave stack and fall
    243|				;through to check source operand
    244|
    245src_op_ck:
    246	btstb	#7,STAG(%a6)
    247	beq	end_getop	|check for unsupported data types on the
    248|				;source operand
    249	btstb	#5,STAG(%a6)
    250	bnes	src_sd_dnrm	|if bit 5 set, handle sgl/dbl denorms
    251|
    252| At this point only unnorms or extended denorms are possible.
    253|
    254src_ex_dnrm:
    255	movew	ETEMP_EX(%a6),%d0 |get source exponent
    256	andiw	#0x7fff,%d0	|mask sign, check if exp = 0000
    257	beq	end_getop	|if denorm then exit, denorms are
    258|				;handled in do_func
    259	leal	ETEMP(%a6),%a0	|point a0 to sop - used in mk_norm
    260	bsr	mk_norm		|go normalize - mk_norm returns:
    261|				;L_SCR1{7:5} = operand tag
    262|				;	(000 = norm, 100 = denorm)
    263|				;L_SCR1{4} = fpte15 or ete15
    264|				;	0 = exp >  $3fff
    265|				;	1 = exp <= $3fff
    266|				;and puts the normalized num back
    267|				;on the fsave stack
    268|
    269	moveb	L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
    270	rts			|end_getop
    271
    272|
    273| At this point, only single or double denorms are possible.
    274| If the inst is not fmove, normalize the source.  If it is,
    275| do nothing to the input.
    276|
    277src_sd_dnrm:
    278	btstb	#4,CMDREG1B(%a6)	|differentiate between sgl/dbl denorm
    279	bnes	is_double
    280is_single:
    281	movew	#0x3f81,%d1	|write bias for sgl denorm
    282	bras	common		|goto the common code
    283is_double:
    284	movew	#0x3c01,%d1	|write the bias for a dbl denorm
    285common:
    286	btstb	#sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
    287	beqs	pos
    288	bset	#15,%d1		|set sign bit because it is negative
    289pos:
    290	movew	%d1,ETEMP_EX(%a6)
    291|				;put exponent on stack
    292
    293	movew	CMDREG1B(%a6),%d1
    294	andw	#0xe3ff,%d1	|clear out source specifier
    295	orw	#0x0800,%d1	|set source specifier to extended prec
    296	movew	%d1,CMDREG1B(%a6)	|write back to the command word in stack
    297|				;this is needed to fix unsupp data stack
    298	leal	ETEMP(%a6),%a0	|point a0 to sop
    299
    300	bsr	mk_norm		|convert sgl/dbl denorm to norm
    301	moveb	L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
    302	rts			|end_getop
    303|
    304| At this point, the source is definitely packed, whether
    305| instruction is dyadic or monadic is still unknown
    306|
    307pack_source:
    308	movel	FPTEMP_LO(%a6),ETEMP(%a6)	|write ms part of packed
    309|				;number to etemp slot
    310	bsr	chk_dy_mo	|set dyadic/monadic flag
    311	bsr	unpack
    312
    313	tstb	DY_MO_FLG(%a6)
    314	beqs	end_getop	|if monadic, exit
    315|				;else, fix FPTEMP
    316pack_dya:
    317	bfextu	CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
    318	movel	#7,%d1
    319	subl	%d0,%d1
    320	clrl	%d0
    321	bsetl	%d1,%d0		|set up d0 as a dynamic register mask
    322	fmovemx %d0,FPTEMP(%a6)	|write to FPTEMP
    323
    324	btstb	#7,DTAG(%a6)	|check dest tag for unnorm or denorm
    325	bne	dst_ex_dnrm	|else, handle the unnorm or ext denorm
    326|
    327| Dest is not denormalized.  Check for norm, and set fpte15
    328| accordingly.
    329|
    330	moveb	DTAG(%a6),%d0
    331	andib	#0xf0,%d0		|strip to only dtag:fpte15
    332	tstb	%d0		|check for normalized value
    333	bnes	end_getop	|if inf/nan/zero leave get_op
    334	movew	FPTEMP_EX(%a6),%d0
    335	andiw	#0x7fff,%d0
    336	cmpiw	#0x3fff,%d0	|check if fpte15 needs setting
    337	bges	end_getop	|if >= $3fff, leave fpte15=0
    338	orb	#0x10,DTAG(%a6)
    339	bras	end_getop
    340
    341|
    342| At this point, it is either an fmoveout packed, unnorm or denorm
    343|
    344opclass3:
    345	clrb	DY_MO_FLG(%a6)	|set dyadic/monadic flag to monadic
    346	bfextu	CMDREG1B(%a6){#4:#2},%d0
    347	cmpib	#3,%d0
    348	bne	src_ex_dnrm	|if not equal, must be unnorm or denorm
    349|				;else it is a packed move out
    350|				;exit
    351end_getop:
    352	rts
    353
    354|
    355| Sets the DY_MO_FLG correctly. This is used only on if it is an
    356| unsupported data type exception.  Set if dyadic.
    357|
    358chk_dy_mo:
    359	movew	CMDREG1B(%a6),%d0
    360	btstl	#5,%d0		|testing extension command word
    361	beqs	set_mon		|if bit 5 = 0 then monadic
    362	btstl	#4,%d0		|know that bit 5 = 1
    363	beqs	set_dya		|if bit 4 = 0 then dyadic
    364	andiw	#0x007f,%d0	|get rid of all but extension bits {6:0}
    365	cmpiw	#0x0038,%d0	|if extension = $38 then fcmp (dyadic)
    366	bnes	set_mon
    367set_dya:
    368	st	DY_MO_FLG(%a6)	|set the inst flag type to dyadic
    369	rts
    370set_mon:
    371	clrb	DY_MO_FLG(%a6)	|set the inst flag type to monadic
    372	rts
    373|
    374|	MK_NORM
    375|
    376| Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
    377| exception if denorm.
    378|
    379| CASE opclass 0x0 unsupp
    380|	mk_norm till msb set
    381|	set tag = norm
    382|
    383| CASE opclass 0x0 unimp
    384|	mk_norm till msb set or exp = 0
    385|	if integer bit = 0
    386|	   tag = denorm
    387|	else
    388|	   tag = norm
    389|
    390| CASE opclass 011 unsupp
    391|	mk_norm till msb set or exp = 0
    392|	if integer bit = 0
    393|	   tag = denorm
    394|	   set unfl_nmcexe = 1
    395|	else
    396|	   tag = norm
    397|
    398| if exp <= $3fff
    399|   set ete15 or fpte15 = 1
    400| else set ete15 or fpte15 = 0
    401
    402| input:
    403|	a0 = points to operand to be normalized
    404| output:
    405|	L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
    406|	L_SCR1{4}   = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
    407|	the normalized operand is placed back on the fsave stack
    408mk_norm:
    409	clrl	L_SCR1(%a6)
    410	bclrb	#sign_bit,LOCAL_EX(%a0)
    411	sne	LOCAL_SGN(%a0)	|transform into internal extended format
    412
    413	cmpib	#0x2c,1+EXC_VEC(%a6) |check if unimp
    414	bnes	uns_data	|branch if unsupp
    415	bsr	uni_inst	|call if unimp (opclass 0x0)
    416	bras	reload
    417uns_data:
    418	btstb	#direction_bit,CMDREG1B(%a6) |check transfer direction
    419	bnes	bit_set		|branch if set (opclass 011)
    420	bsr	uns_opx		|call if opclass 0x0
    421	bras	reload
    422bit_set:
    423	bsr	uns_op3		|opclass 011
    424reload:
    425	cmpw	#0x3fff,LOCAL_EX(%a0) |if exp > $3fff
    426	bgts	end_mk		|   fpte15/ete15 already set to 0
    427	bsetb	#4,L_SCR1(%a6)	|else set fpte15/ete15 to 1
    428|				;calling routine actually sets the
    429|				;value on the stack (along with the
    430|				;tag), since this routine doesn't
    431|				;know if it should set ete15 or fpte15
    432|				;ie, it doesn't know if this is the
    433|				;src op or dest op.
    434end_mk:
    435	bfclr	LOCAL_SGN(%a0){#0:#8}
    436	beqs	end_mk_pos
    437	bsetb	#sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
    438end_mk_pos:
    439	rts
    440|
    441|     CASE opclass 011 unsupp
    442|
    443uns_op3:
    444	bsr	nrm_zero	|normalize till msb = 1 or exp = zero
    445	btstb	#7,LOCAL_HI(%a0)	|if msb = 1
    446	bnes	no_unfl		|then branch
    447set_unfl:
    448	orw	#dnrm_tag,L_SCR1(%a6) |set denorm tag
    449	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
    450no_unfl:
    451	rts
    452|
    453|     CASE opclass 0x0 unsupp
    454|
    455uns_opx:
    456	bsr	nrm_zero	|normalize the number
    457	btstb	#7,LOCAL_HI(%a0)	|check if integer bit (j-bit) is set
    458	beqs	uns_den		|if clear then now have a denorm
    459uns_nrm:
    460	orb	#norm_tag,L_SCR1(%a6) |set tag to norm
    461	rts
    462uns_den:
    463	orb	#dnrm_tag,L_SCR1(%a6) |set tag to denorm
    464	rts
    465|
    466|     CASE opclass 0x0 unimp
    467|
    468uni_inst:
    469	bsr	nrm_zero
    470	btstb	#7,LOCAL_HI(%a0)	|check if integer bit (j-bit) is set
    471	beqs	uni_den		|if clear then now have a denorm
    472uni_nrm:
    473	orb	#norm_tag,L_SCR1(%a6) |set tag to norm
    474	rts
    475uni_den:
    476	orb	#dnrm_tag,L_SCR1(%a6) |set tag to denorm
    477	rts
    478
    479|
    480|	Decimal to binary conversion
    481|
    482| Special cases of inf and NaNs are completed outside of decbin.
    483| If the input is an snan, the snan bit is not set.
    484|
    485| input:
    486|	ETEMP(a6)	- points to packed decimal string in memory
    487| output:
    488|	fp0	- contains packed string converted to extended precision
    489|	ETEMP	- same as fp0
    490unpack:
    491	movew	CMDREG1B(%a6),%d0	|examine command word, looking for fmove's
    492	andw	#0x3b,%d0
    493	beq	move_unpack	|special handling for fmove: must set FPSR_CC
    494
    495	movew	ETEMP(%a6),%d0	|get word with inf information
    496	bfextu	%d0{#20:#12},%d1	|get exponent into d1
    497	cmpiw	#0x0fff,%d1	|test for inf or NaN
    498	bnes	try_zero	|if not equal, it is not special
    499	bfextu	%d0{#17:#3},%d1	|get SE and y bits into d1
    500	cmpiw	#7,%d1		|SE and y bits must be on for special
    501	bnes	try_zero	|if not on, it is not special
    502|input is of the special cases of inf and NaN
    503	tstl	ETEMP_HI(%a6)	|check ms mantissa
    504	bnes	fix_nan		|if non-zero, it is a NaN
    505	tstl	ETEMP_LO(%a6)	|check ls mantissa
    506	bnes	fix_nan		|if non-zero, it is a NaN
    507	bra	finish		|special already on stack
    508fix_nan:
    509	btstb	#signan_bit,ETEMP_HI(%a6) |test for snan
    510	bne	finish
    511	orl	#snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
    512	bra	finish
    513try_zero:
    514	movew	ETEMP_EX+2(%a6),%d0 |get word 4
    515	andiw	#0x000f,%d0	|clear all but last ni(y)bble
    516	tstw	%d0		|check for zero.
    517	bne	not_spec
    518	tstl	ETEMP_HI(%a6)	|check words 3 and 2
    519	bne	not_spec
    520	tstl	ETEMP_LO(%a6)	|check words 1 and 0
    521	bne	not_spec
    522	tstl	ETEMP(%a6)	|test sign of the zero
    523	bges	pos_zero
    524	movel	#0x80000000,ETEMP(%a6) |write neg zero to etemp
    525	clrl	ETEMP_HI(%a6)
    526	clrl	ETEMP_LO(%a6)
    527	bra	finish
    528pos_zero:
    529	clrl	ETEMP(%a6)
    530	clrl	ETEMP_HI(%a6)
    531	clrl	ETEMP_LO(%a6)
    532	bra	finish
    533
    534not_spec:
    535	fmovemx %fp0-%fp1,-(%a7)	|save fp0 - decbin returns in it
    536	bsr	decbin
    537	fmovex %fp0,ETEMP(%a6)	|put the unpacked sop in the fsave stack
    538	fmovemx (%a7)+,%fp0-%fp1
    539	fmovel	#0,%FPSR		|clr fpsr from decbin
    540	bra	finish
    541
    542|
    543| Special handling for packed move in:  Same results as all other
    544| packed cases, but we must set the FPSR condition codes properly.
    545|
    546move_unpack:
    547	movew	ETEMP(%a6),%d0	|get word with inf information
    548	bfextu	%d0{#20:#12},%d1	|get exponent into d1
    549	cmpiw	#0x0fff,%d1	|test for inf or NaN
    550	bnes	mtry_zero	|if not equal, it is not special
    551	bfextu	%d0{#17:#3},%d1	|get SE and y bits into d1
    552	cmpiw	#7,%d1		|SE and y bits must be on for special
    553	bnes	mtry_zero	|if not on, it is not special
    554|input is of the special cases of inf and NaN
    555	tstl	ETEMP_HI(%a6)	|check ms mantissa
    556	bnes	mfix_nan		|if non-zero, it is a NaN
    557	tstl	ETEMP_LO(%a6)	|check ls mantissa
    558	bnes	mfix_nan		|if non-zero, it is a NaN
    559|input is inf
    560	orl	#inf_mask,USER_FPSR(%a6) |set I bit
    561	tstl	ETEMP(%a6)	|check sign
    562	bge	finish
    563	orl	#neg_mask,USER_FPSR(%a6) |set N bit
    564	bra	finish		|special already on stack
    565mfix_nan:
    566	orl	#nan_mask,USER_FPSR(%a6) |set NaN bit
    567	moveb	#nan_tag,STAG(%a6)	|set stag to NaN
    568	btstb	#signan_bit,ETEMP_HI(%a6) |test for snan
    569	bnes	mn_snan
    570	orl	#snaniop_mask,USER_FPSR(%a6) |set snan bit
    571	btstb	#snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
    572	bnes	mn_snan
    573	bsetb	#signan_bit,ETEMP_HI(%a6) |force snans to qnans
    574mn_snan:
    575	tstl	ETEMP(%a6)	|check for sign
    576	bge	finish		|if clr, go on
    577	orl	#neg_mask,USER_FPSR(%a6) |set N bit
    578	bra	finish
    579
    580mtry_zero:
    581	movew	ETEMP_EX+2(%a6),%d0 |get word 4
    582	andiw	#0x000f,%d0	|clear all but last ni(y)bble
    583	tstw	%d0		|check for zero.
    584	bnes	mnot_spec
    585	tstl	ETEMP_HI(%a6)	|check words 3 and 2
    586	bnes	mnot_spec
    587	tstl	ETEMP_LO(%a6)	|check words 1 and 0
    588	bnes	mnot_spec
    589	tstl	ETEMP(%a6)	|test sign of the zero
    590	bges	mpos_zero
    591	orl	#neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
    592	movel	#0x80000000,ETEMP(%a6) |write neg zero to etemp
    593	clrl	ETEMP_HI(%a6)
    594	clrl	ETEMP_LO(%a6)
    595	bras	finish
    596mpos_zero:
    597	orl	#z_mask,USER_FPSR(%a6) |set Z
    598	clrl	ETEMP(%a6)
    599	clrl	ETEMP_HI(%a6)
    600	clrl	ETEMP_LO(%a6)
    601	bras	finish
    602
    603mnot_spec:
    604	fmovemx %fp0-%fp1,-(%a7)	|save fp0 ,fp1 - decbin returns in fp0
    605	bsr	decbin
    606	fmovex %fp0,ETEMP(%a6)
    607|				;put the unpacked sop in the fsave stack
    608	fmovemx (%a7)+,%fp0-%fp1
    609
    610finish:
    611	movew	CMDREG1B(%a6),%d0	|get the command word
    612	andw	#0xfbff,%d0	|change the source specifier field to
    613|				;extended (was packed).
    614	movew	%d0,CMDREG1B(%a6)	|write command word back to fsave stack
    615|				;we need to do this so the 040 will
    616|				;re-execute the inst. without taking
    617|				;another packed trap.
    618
    619fix_stag:
    620|Converted result is now in etemp on fsave stack, now set the source
    621|tag (stag)
    622|	if (ete =$7fff) then INF or NAN
    623|		if (etemp = $x.0----0) then
    624|			stag = INF
    625|		else
    626|			stag = NAN
    627|	else
    628|		if (ete = $0000) then
    629|			stag = ZERO
    630|		else
    631|			stag = NORM
    632|
    633| Note also that the etemp_15 bit (just right of the stag) must
    634| be set accordingly.
    635|
    636	movew		ETEMP_EX(%a6),%d1
    637	andiw		#0x7fff,%d1   |strip sign
    638	cmpw		#0x7fff,%d1
    639	bnes		z_or_nrm
    640	movel		ETEMP_HI(%a6),%d1
    641	bnes		is_nan
    642	movel		ETEMP_LO(%a6),%d1
    643	bnes		is_nan
    644is_inf:
    645	moveb		#0x40,STAG(%a6)
    646	movel		#0x40,%d0
    647	rts
    648is_nan:
    649	moveb		#0x60,STAG(%a6)
    650	movel		#0x60,%d0
    651	rts
    652z_or_nrm:
    653	tstw		%d1
    654	bnes		is_nrm
    655is_zro:
    656| For a zero, set etemp_15
    657	moveb		#0x30,STAG(%a6)
    658	movel		#0x20,%d0
    659	rts
    660is_nrm:
    661| For a norm, check if the exp <= $3fff; if so, set etemp_15
    662	cmpiw		#0x3fff,%d1
    663	bles		set_bit15
    664	moveb		#0,STAG(%a6)
    665	bras		end_is_nrm
    666set_bit15:
    667	moveb		#0x10,STAG(%a6)
    668end_is_nrm:
    669	movel		#0,%d0
    670end_fix:
    671	rts
    672
    673end_get:
    674	rts
    675	|end