| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | | 
|  | 2 | |	res_func.sa 3.9 7/29/91 | 
|  | 3 | | | 
|  | 4 | | Normalizes denormalized numbers if necessary and updates the | 
|  | 5 | | stack frame.  The function is then restored back into the | 
|  | 6 | | machine and the 040 completes the operation.  This routine | 
|  | 7 | | is only used by the unsupported data type/format handler. | 
|  | 8 | | (Exception vector 55). | 
|  | 9 | | | 
|  | 10 | | For packed move out (fmove.p fpm,<ea>) the operation is | 
|  | 11 | | completed here; data is packed and moved to user memory. | 
|  | 12 | | The stack is restored to the 040 only in the case of a | 
|  | 13 | | reportable exception in the conversion. | 
|  | 14 | | | 
|  | 15 | | | 
|  | 16 | |		Copyright (C) Motorola, Inc. 1990 | 
|  | 17 | |			All Rights Reserved | 
|  | 18 | | | 
| Matt Waddel | e00d82d | 2006-02-11 17:55:48 -0800 | [diff] [blame] | 19 | |       For details on the license for this file, please see the | 
|  | 20 | |       file, README, in this same directory. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
|  | 22 | RES_FUNC:    |idnt    2,1 | Motorola 040 Floating Point Software Package | 
|  | 23 |  | 
|  | 24 | |section	8 | 
|  | 25 |  | 
|  | 26 | #include "fpsp.h" | 
|  | 27 |  | 
|  | 28 | sp_bnds:	.short	0x3f81,0x407e | 
|  | 29 | .short	0x3f6a,0x0000 | 
|  | 30 | dp_bnds:	.short	0x3c01,0x43fe | 
|  | 31 | .short	0x3bcd,0x0000 | 
|  | 32 |  | 
|  | 33 | |xref	mem_write | 
|  | 34 | |xref	bindec | 
|  | 35 | |xref	get_fline | 
|  | 36 | |xref	round | 
|  | 37 | |xref	denorm | 
|  | 38 | |xref	dest_ext | 
|  | 39 | |xref	dest_dbl | 
|  | 40 | |xref	dest_sgl | 
|  | 41 | |xref	unf_sub | 
|  | 42 | |xref	nrm_set | 
|  | 43 | |xref	dnrm_lp | 
|  | 44 | |xref	ovf_res | 
|  | 45 | |xref	reg_dest | 
|  | 46 | |xref	t_ovfl | 
|  | 47 | |xref	t_unfl | 
|  | 48 |  | 
|  | 49 | .global	res_func | 
|  | 50 | .global	p_move | 
|  | 51 |  | 
|  | 52 | res_func: | 
|  | 53 | clrb	DNRM_FLG(%a6) | 
|  | 54 | clrb	RES_FLG(%a6) | 
|  | 55 | clrb	CU_ONLY(%a6) | 
|  | 56 | tstb	DY_MO_FLG(%a6) | 
|  | 57 | beqs	monadic | 
|  | 58 | dyadic: | 
|  | 59 | btstb	#7,DTAG(%a6)	|if dop = norm=000, zero=001, | 
|  | 60 | |				;inf=010 or nan=011 | 
|  | 61 | beqs	monadic		|then branch | 
|  | 62 | |				;else denorm | 
|  | 63 | | HANDLE DESTINATION DENORM HERE | 
|  | 64 | |				;set dtag to norm | 
|  | 65 | |				;write the tag & fpte15 to the fstack | 
|  | 66 | leal	FPTEMP(%a6),%a0 | 
|  | 67 |  | 
|  | 68 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 69 | sne	LOCAL_SGN(%a0) | 
|  | 70 |  | 
|  | 71 | bsr	nrm_set		|normalize number (exp will go negative) | 
|  | 72 | bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign | 
|  | 73 | bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
|  | 74 | beqs	dpos | 
|  | 75 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 76 | dpos: | 
|  | 77 | bfclr	DTAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0 | 
|  | 78 | bsetb	#4,DTAG(%a6)	|set FPTE15 | 
|  | 79 | orb	#0x0f,DNRM_FLG(%a6) | 
|  | 80 | monadic: | 
|  | 81 | leal	ETEMP(%a6),%a0 | 
|  | 82 | btstb	#direction_bit,CMDREG1B(%a6)	|check direction | 
|  | 83 | bne	opclass3			|it is a mv out | 
|  | 84 | | | 
|  | 85 | | At this point, only opclass 0 and 2 possible | 
|  | 86 | | | 
|  | 87 | btstb	#7,STAG(%a6)	|if sop = norm=000, zero=001, | 
|  | 88 | |				;inf=010 or nan=011 | 
|  | 89 | bne	mon_dnrm	|else denorm | 
|  | 90 | tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would | 
|  | 91 | bne	normal		|require normalization of denorm | 
|  | 92 |  | 
|  | 93 | | At this point: | 
|  | 94 | |	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a | 
|  | 95 | |				fmove = $00  fsmove = $40  fdmove = $44 | 
|  | 96 | |				fsqrt = $05* fssqrt = $41  fdsqrt = $45 | 
|  | 97 | |				(*fsqrt reencoded to $05) | 
|  | 98 | | | 
|  | 99 | movew	CMDREG1B(%a6),%d0	|get command register | 
|  | 100 | andil	#0x7f,%d0			|strip to only command word | 
|  | 101 | | | 
|  | 102 | | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | 
|  | 103 | | fdsqrt are possible. | 
|  | 104 | | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) | 
|  | 105 | | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) | 
|  | 106 | | | 
|  | 107 | btstl	#0,%d0 | 
|  | 108 | bne	normal			|weed out fsqrt instructions | 
|  | 109 | | | 
|  | 110 | | cu_norm handles fmove in instructions with normalized inputs. | 
|  | 111 | | The routine round is used to correctly round the input for the | 
|  | 112 | | destination precision and mode. | 
|  | 113 | | | 
|  | 114 | cu_norm: | 
|  | 115 | st	CU_ONLY(%a6)		|set cu-only inst flag | 
|  | 116 | movew	CMDREG1B(%a6),%d0 | 
|  | 117 | andib	#0x3b,%d0		|isolate bits to select inst | 
|  | 118 | tstb	%d0 | 
|  | 119 | beql	cu_nmove	|if zero, it is an fmove | 
|  | 120 | cmpib	#0x18,%d0 | 
|  | 121 | beql	cu_nabs		|if $18, it is fabs | 
|  | 122 | cmpib	#0x1a,%d0 | 
|  | 123 | beql	cu_nneg		|if $1a, it is fneg | 
|  | 124 | | | 
|  | 125 | | Inst is ftst.  Check the source operand and set the cc's accordingly. | 
|  | 126 | | No write is done, so simply rts. | 
|  | 127 | | | 
|  | 128 | cu_ntst: | 
|  | 129 | movew	LOCAL_EX(%a0),%d0 | 
|  | 130 | bclrl	#15,%d0 | 
|  | 131 | sne	LOCAL_SGN(%a0) | 
|  | 132 | beqs	cu_ntpo | 
|  | 133 | orl	#neg_mask,USER_FPSR(%a6) |set N | 
|  | 134 | cu_ntpo: | 
|  | 135 | cmpiw	#0x7fff,%d0	|test for inf/nan | 
|  | 136 | bnes	cu_ntcz | 
|  | 137 | tstl	LOCAL_HI(%a0) | 
|  | 138 | bnes	cu_ntn | 
|  | 139 | tstl	LOCAL_LO(%a0) | 
|  | 140 | bnes	cu_ntn | 
|  | 141 | orl	#inf_mask,USER_FPSR(%a6) | 
|  | 142 | rts | 
|  | 143 | cu_ntn: | 
|  | 144 | orl	#nan_mask,USER_FPSR(%a6) | 
|  | 145 | movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
|  | 146 | |						;snan handler | 
|  | 147 |  | 
|  | 148 | rts | 
|  | 149 | cu_ntcz: | 
|  | 150 | tstl	LOCAL_HI(%a0) | 
|  | 151 | bnel	cu_ntsx | 
|  | 152 | tstl	LOCAL_LO(%a0) | 
|  | 153 | bnel	cu_ntsx | 
|  | 154 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 155 | cu_ntsx: | 
|  | 156 | rts | 
|  | 157 | | | 
|  | 158 | | Inst is fabs.  Execute the absolute value function on the input. | 
|  | 159 | | Branch to the fmove code.  If the operand is NaN, do nothing. | 
|  | 160 | | | 
|  | 161 | cu_nabs: | 
|  | 162 | moveb	STAG(%a6),%d0 | 
|  | 163 | btstl	#5,%d0			|test for NaN or zero | 
|  | 164 | bne	wr_etemp		|if either, simply write it | 
|  | 165 | bclrb	#7,LOCAL_EX(%a0)		|do abs | 
|  | 166 | bras	cu_nmove		|fmove code will finish | 
|  | 167 | | | 
|  | 168 | | Inst is fneg.  Execute the negate value function on the input. | 
|  | 169 | | Fall though to the fmove code.  If the operand is NaN, do nothing. | 
|  | 170 | | | 
|  | 171 | cu_nneg: | 
|  | 172 | moveb	STAG(%a6),%d0 | 
|  | 173 | btstl	#5,%d0			|test for NaN or zero | 
|  | 174 | bne	wr_etemp		|if either, simply write it | 
|  | 175 | bchgb	#7,LOCAL_EX(%a0)		|do neg | 
|  | 176 | | | 
|  | 177 | | Inst is fmove.  This code also handles all result writes. | 
|  | 178 | | If bit 2 is set, round is forced to double.  If it is clear, | 
|  | 179 | | and bit 6 is set, round is forced to single.  If both are clear, | 
|  | 180 | | the round precision is found in the fpcr.  If the rounding precision | 
|  | 181 | | is double or single, round the result before the write. | 
|  | 182 | | | 
|  | 183 | cu_nmove: | 
|  | 184 | moveb	STAG(%a6),%d0 | 
|  | 185 | andib	#0xe0,%d0			|isolate stag bits | 
|  | 186 | bne	wr_etemp		|if not norm, simply write it | 
|  | 187 | btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
|  | 188 | bne	cu_nmrd | 
|  | 189 | btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
|  | 190 | bne	cu_nmrs | 
|  | 191 | | | 
|  | 192 | | The move or operation is not with forced precision.  Test for | 
|  | 193 | | nan or inf as the input; if so, simply write it to FPn.  Use the | 
|  | 194 | | FPCR_MODE byte to get rounding on norms and zeros. | 
|  | 195 | | | 
|  | 196 | cu_nmnr: | 
|  | 197 | bfextu	FPCR_MODE(%a6){#0:#2},%d0 | 
|  | 198 | tstb	%d0			|check for extended | 
|  | 199 | beq	cu_wrexn		|if so, just write result | 
|  | 200 | cmpib	#1,%d0			|check for single | 
|  | 201 | beq	cu_nmrs			|fall through to double | 
|  | 202 | | | 
|  | 203 | | The move is fdmove or round precision is double. | 
|  | 204 | | | 
|  | 205 | cu_nmrd: | 
|  | 206 | movel	#2,%d0			|set up the size for denorm | 
|  | 207 | movew	LOCAL_EX(%a0),%d1		|compare exponent to double threshold | 
|  | 208 | andw	#0x7fff,%d1 | 
|  | 209 | cmpw	#0x3c01,%d1 | 
|  | 210 | bls	cu_nunfl | 
|  | 211 | bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
|  | 212 | orl	#0x00020000,%d1		|or in rprec (double) | 
|  | 213 | clrl	%d0			|clear g,r,s for round | 
|  | 214 | bclrb	#sign_bit,LOCAL_EX(%a0)	|convert to internal format | 
|  | 215 | sne	LOCAL_SGN(%a0) | 
|  | 216 | bsrl	round | 
|  | 217 | bfclr	LOCAL_SGN(%a0){#0:#8} | 
|  | 218 | beqs	cu_nmrdc | 
|  | 219 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 220 | cu_nmrdc: | 
|  | 221 | movew	LOCAL_EX(%a0),%d1		|check for overflow | 
|  | 222 | andw	#0x7fff,%d1 | 
|  | 223 | cmpw	#0x43ff,%d1 | 
|  | 224 | bge	cu_novfl		|take care of overflow case | 
|  | 225 | bra	cu_wrexn | 
|  | 226 | | | 
|  | 227 | | The move is fsmove or round precision is single. | 
|  | 228 | | | 
|  | 229 | cu_nmrs: | 
|  | 230 | movel	#1,%d0 | 
|  | 231 | movew	LOCAL_EX(%a0),%d1 | 
|  | 232 | andw	#0x7fff,%d1 | 
|  | 233 | cmpw	#0x3f81,%d1 | 
|  | 234 | bls	cu_nunfl | 
|  | 235 | bfextu	FPCR_MODE(%a6){#2:#2},%d1 | 
|  | 236 | orl	#0x00010000,%d1 | 
|  | 237 | clrl	%d0 | 
|  | 238 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 239 | sne	LOCAL_SGN(%a0) | 
|  | 240 | bsrl	round | 
|  | 241 | bfclr	LOCAL_SGN(%a0){#0:#8} | 
|  | 242 | beqs	cu_nmrsc | 
|  | 243 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 244 | cu_nmrsc: | 
|  | 245 | movew	LOCAL_EX(%a0),%d1 | 
|  | 246 | andw	#0x7FFF,%d1 | 
|  | 247 | cmpw	#0x407f,%d1 | 
|  | 248 | blt	cu_wrexn | 
|  | 249 | | | 
|  | 250 | | The operand is above precision boundaries.  Use t_ovfl to | 
|  | 251 | | generate the correct value. | 
|  | 252 | | | 
|  | 253 | cu_novfl: | 
|  | 254 | bsr	t_ovfl | 
|  | 255 | bra	cu_wrexn | 
|  | 256 | | | 
|  | 257 | | The operand is below precision boundaries.  Use denorm to | 
|  | 258 | | generate the correct value. | 
|  | 259 | | | 
|  | 260 | cu_nunfl: | 
|  | 261 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 262 | sne	LOCAL_SGN(%a0) | 
|  | 263 | bsr	denorm | 
|  | 264 | bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
|  | 265 | beqs	cu_nucont | 
|  | 266 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 267 | cu_nucont: | 
|  | 268 | bfextu	FPCR_MODE(%a6){#2:#2},%d1 | 
|  | 269 | btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
|  | 270 | bne	inst_d | 
|  | 271 | btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
|  | 272 | bne	inst_s | 
|  | 273 | swap	%d1 | 
|  | 274 | moveb	FPCR_MODE(%a6),%d1 | 
|  | 275 | lsrb	#6,%d1 | 
|  | 276 | swap	%d1 | 
|  | 277 | bra	inst_sd | 
|  | 278 | inst_d: | 
|  | 279 | orl	#0x00020000,%d1 | 
|  | 280 | bra	inst_sd | 
|  | 281 | inst_s: | 
|  | 282 | orl	#0x00010000,%d1 | 
|  | 283 | inst_sd: | 
|  | 284 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 285 | sne	LOCAL_SGN(%a0) | 
|  | 286 | bsrl	round | 
|  | 287 | bfclr	LOCAL_SGN(%a0){#0:#8} | 
|  | 288 | beqs	cu_nuflp | 
|  | 289 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 290 | cu_nuflp: | 
|  | 291 | btstb	#inex2_bit,FPSR_EXCEPT(%a6) | 
|  | 292 | beqs	cu_nuninx | 
|  | 293 | orl	#aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFL | 
|  | 294 | cu_nuninx: | 
|  | 295 | tstl	LOCAL_HI(%a0)		|test for zero | 
|  | 296 | bnes	cu_nunzro | 
|  | 297 | tstl	LOCAL_LO(%a0) | 
|  | 298 | bnes	cu_nunzro | 
|  | 299 | | | 
|  | 300 | | The mantissa is zero from the denorm loop.  Check sign and rmode | 
|  | 301 | | to see if rounding should have occurred which would leave the lsb. | 
|  | 302 | | | 
|  | 303 | movel	USER_FPCR(%a6),%d0 | 
|  | 304 | andil	#0x30,%d0		|isolate rmode | 
|  | 305 | cmpil	#0x20,%d0 | 
|  | 306 | blts	cu_nzro | 
|  | 307 | bnes	cu_nrp | 
|  | 308 | cu_nrm: | 
|  | 309 | tstw	LOCAL_EX(%a0)	|if positive, set lsb | 
|  | 310 | bges	cu_nzro | 
|  | 311 | btstb	#7,FPCR_MODE(%a6) |check for double | 
|  | 312 | beqs	cu_nincs | 
|  | 313 | bras	cu_nincd | 
|  | 314 | cu_nrp: | 
|  | 315 | tstw	LOCAL_EX(%a0)	|if positive, set lsb | 
|  | 316 | blts	cu_nzro | 
|  | 317 | btstb	#7,FPCR_MODE(%a6) |check for double | 
|  | 318 | beqs	cu_nincs | 
|  | 319 | cu_nincd: | 
|  | 320 | orl	#0x800,LOCAL_LO(%a0) |inc for double | 
|  | 321 | bra	cu_nunzro | 
|  | 322 | cu_nincs: | 
|  | 323 | orl	#0x100,LOCAL_HI(%a0) |inc for single | 
|  | 324 | bra	cu_nunzro | 
|  | 325 | cu_nzro: | 
|  | 326 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 327 | moveb	STAG(%a6),%d0 | 
|  | 328 | andib	#0xe0,%d0 | 
|  | 329 | cmpib	#0x40,%d0		|check if input was tagged zero | 
|  | 330 | beqs	cu_numv | 
|  | 331 | cu_nunzro: | 
|  | 332 | orl	#unfl_mask,USER_FPSR(%a6) |set unfl | 
|  | 333 | cu_numv: | 
|  | 334 | movel	(%a0),ETEMP(%a6) | 
|  | 335 | movel	4(%a0),ETEMP_HI(%a6) | 
|  | 336 | movel	8(%a0),ETEMP_LO(%a6) | 
|  | 337 | | | 
|  | 338 | | Write the result to memory, setting the fpsr cc bits.  NaN and Inf | 
|  | 339 | | bypass cu_wrexn. | 
|  | 340 | | | 
|  | 341 | cu_wrexn: | 
|  | 342 | tstw	LOCAL_EX(%a0)		|test for zero | 
|  | 343 | beqs	cu_wrzero | 
|  | 344 | cmpw	#0x8000,LOCAL_EX(%a0)	|test for zero | 
|  | 345 | bnes	cu_wreon | 
|  | 346 | cu_wrzero: | 
|  | 347 | orl	#z_mask,USER_FPSR(%a6)	|set Z bit | 
|  | 348 | cu_wreon: | 
|  | 349 | tstw	LOCAL_EX(%a0) | 
|  | 350 | bpl	wr_etemp | 
|  | 351 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 352 | bra	wr_etemp | 
|  | 353 |  | 
|  | 354 | | | 
|  | 355 | | HANDLE SOURCE DENORM HERE | 
|  | 356 | | | 
|  | 357 | |				;clear denorm stag to norm | 
|  | 358 | |				;write the new tag & ete15 to the fstack | 
|  | 359 | mon_dnrm: | 
|  | 360 | | | 
|  | 361 | | At this point, check for the cases in which normalizing the | 
|  | 362 | | denorm produces incorrect results. | 
|  | 363 | | | 
|  | 364 | tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would | 
|  | 365 | bnes	nrm_src		|require normalization of denorm | 
|  | 366 |  | 
|  | 367 | | At this point: | 
|  | 368 | |	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a | 
|  | 369 | |				fmove = $00  fsmove = $40  fdmove = $44 | 
|  | 370 | |				fsqrt = $05* fssqrt = $41  fdsqrt = $45 | 
|  | 371 | |				(*fsqrt reencoded to $05) | 
|  | 372 | | | 
|  | 373 | movew	CMDREG1B(%a6),%d0	|get command register | 
|  | 374 | andil	#0x7f,%d0			|strip to only command word | 
|  | 375 | | | 
|  | 376 | | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | 
|  | 377 | | fdsqrt are possible. | 
|  | 378 | | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) | 
|  | 379 | | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) | 
|  | 380 | | | 
|  | 381 | btstl	#0,%d0 | 
|  | 382 | bnes	nrm_src		|weed out fsqrt instructions | 
|  | 383 | st	CU_ONLY(%a6)	|set cu-only inst flag | 
|  | 384 | bra	cu_dnrm		|fmove, fabs, fneg, ftst | 
|  | 385 | |				;cases go to cu_dnrm | 
|  | 386 | nrm_src: | 
|  | 387 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 388 | sne	LOCAL_SGN(%a0) | 
|  | 389 | bsr	nrm_set		|normalize number (exponent will go | 
|  | 390 | |				; negative) | 
|  | 391 | bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign | 
|  | 392 |  | 
|  | 393 | bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format | 
|  | 394 | beqs	spos | 
|  | 395 | bsetb	#sign_bit,LOCAL_EX(%a0) | 
|  | 396 | spos: | 
|  | 397 | bfclr	STAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0 | 
|  | 398 | bsetb	#4,STAG(%a6)	|set ETE15 | 
|  | 399 | orb	#0xf0,DNRM_FLG(%a6) | 
|  | 400 | normal: | 
|  | 401 | tstb	DNRM_FLG(%a6)	|check if any of the ops were denorms | 
|  | 402 | bne	ck_wrap		|if so, check if it is a potential | 
|  | 403 | |				;wrap-around case | 
|  | 404 | fix_stk: | 
|  | 405 | moveb	#0xfe,CU_SAVEPC(%a6) | 
|  | 406 | bclrb	#E1,E_BYTE(%a6) | 
|  | 407 |  | 
|  | 408 | clrw	NMNEXC(%a6) | 
|  | 409 |  | 
|  | 410 | st	RES_FLG(%a6)	|indicate that a restore is needed | 
|  | 411 | rts | 
|  | 412 |  | 
|  | 413 | | | 
|  | 414 | | cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and | 
|  | 415 | | ftst) completely in software without an frestore to the 040. | 
|  | 416 | | | 
|  | 417 | cu_dnrm: | 
|  | 418 | st	CU_ONLY(%a6) | 
|  | 419 | movew	CMDREG1B(%a6),%d0 | 
|  | 420 | andib	#0x3b,%d0		|isolate bits to select inst | 
|  | 421 | tstb	%d0 | 
|  | 422 | beql	cu_dmove	|if zero, it is an fmove | 
|  | 423 | cmpib	#0x18,%d0 | 
|  | 424 | beql	cu_dabs		|if $18, it is fabs | 
|  | 425 | cmpib	#0x1a,%d0 | 
|  | 426 | beql	cu_dneg		|if $1a, it is fneg | 
|  | 427 | | | 
|  | 428 | | Inst is ftst.  Check the source operand and set the cc's accordingly. | 
|  | 429 | | No write is done, so simply rts. | 
|  | 430 | | | 
|  | 431 | cu_dtst: | 
|  | 432 | movew	LOCAL_EX(%a0),%d0 | 
|  | 433 | bclrl	#15,%d0 | 
|  | 434 | sne	LOCAL_SGN(%a0) | 
|  | 435 | beqs	cu_dtpo | 
|  | 436 | orl	#neg_mask,USER_FPSR(%a6) |set N | 
|  | 437 | cu_dtpo: | 
|  | 438 | cmpiw	#0x7fff,%d0	|test for inf/nan | 
|  | 439 | bnes	cu_dtcz | 
|  | 440 | tstl	LOCAL_HI(%a0) | 
|  | 441 | bnes	cu_dtn | 
|  | 442 | tstl	LOCAL_LO(%a0) | 
|  | 443 | bnes	cu_dtn | 
|  | 444 | orl	#inf_mask,USER_FPSR(%a6) | 
|  | 445 | rts | 
|  | 446 | cu_dtn: | 
|  | 447 | orl	#nan_mask,USER_FPSR(%a6) | 
|  | 448 | movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
|  | 449 | |						;snan handler | 
|  | 450 | rts | 
|  | 451 | cu_dtcz: | 
|  | 452 | tstl	LOCAL_HI(%a0) | 
|  | 453 | bnel	cu_dtsx | 
|  | 454 | tstl	LOCAL_LO(%a0) | 
|  | 455 | bnel	cu_dtsx | 
|  | 456 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 457 | cu_dtsx: | 
|  | 458 | rts | 
|  | 459 | | | 
|  | 460 | | Inst is fabs.  Execute the absolute value function on the input. | 
|  | 461 | | Branch to the fmove code. | 
|  | 462 | | | 
|  | 463 | cu_dabs: | 
|  | 464 | bclrb	#7,LOCAL_EX(%a0)		|do abs | 
|  | 465 | bras	cu_dmove		|fmove code will finish | 
|  | 466 | | | 
|  | 467 | | Inst is fneg.  Execute the negate value function on the input. | 
|  | 468 | | Fall though to the fmove code. | 
|  | 469 | | | 
|  | 470 | cu_dneg: | 
|  | 471 | bchgb	#7,LOCAL_EX(%a0)		|do neg | 
|  | 472 | | | 
|  | 473 | | Inst is fmove.  This code also handles all result writes. | 
|  | 474 | | If bit 2 is set, round is forced to double.  If it is clear, | 
|  | 475 | | and bit 6 is set, round is forced to single.  If both are clear, | 
|  | 476 | | the round precision is found in the fpcr.  If the rounding precision | 
|  | 477 | | is double or single, the result is zero, and the mode is checked | 
|  | 478 | | to determine if the lsb of the result should be set. | 
|  | 479 | | | 
|  | 480 | cu_dmove: | 
|  | 481 | btstb	#2,CMDREG1B+1(%a6)	|check for rd | 
|  | 482 | bne	cu_dmrd | 
|  | 483 | btstb	#6,CMDREG1B+1(%a6)	|check for rs | 
|  | 484 | bne	cu_dmrs | 
|  | 485 | | | 
|  | 486 | | The move or operation is not with forced precision.  Use the | 
|  | 487 | | FPCR_MODE byte to get rounding. | 
|  | 488 | | | 
|  | 489 | cu_dmnr: | 
|  | 490 | bfextu	FPCR_MODE(%a6){#0:#2},%d0 | 
|  | 491 | tstb	%d0			|check for extended | 
|  | 492 | beq	cu_wrexd		|if so, just write result | 
|  | 493 | cmpib	#1,%d0			|check for single | 
|  | 494 | beq	cu_dmrs			|fall through to double | 
|  | 495 | | | 
|  | 496 | | The move is fdmove or round precision is double.  Result is zero. | 
|  | 497 | | Check rmode for rp or rm and set lsb accordingly. | 
|  | 498 | | | 
|  | 499 | cu_dmrd: | 
|  | 500 | bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
|  | 501 | tstw	LOCAL_EX(%a0)		|check sign | 
|  | 502 | blts	cu_dmdn | 
|  | 503 | cmpib	#3,%d1			|check for rp | 
|  | 504 | bne	cu_dpd			|load double pos zero | 
|  | 505 | bra	cu_dpdr			|load double pos zero w/lsb | 
|  | 506 | cu_dmdn: | 
|  | 507 | cmpib	#2,%d1			|check for rm | 
|  | 508 | bne	cu_dnd			|load double neg zero | 
|  | 509 | bra	cu_dndr			|load double neg zero w/lsb | 
|  | 510 | | | 
|  | 511 | | The move is fsmove or round precision is single.  Result is zero. | 
|  | 512 | | Check for rp or rm and set lsb accordingly. | 
|  | 513 | | | 
|  | 514 | cu_dmrs: | 
|  | 515 | bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode | 
|  | 516 | tstw	LOCAL_EX(%a0)		|check sign | 
|  | 517 | blts	cu_dmsn | 
|  | 518 | cmpib	#3,%d1			|check for rp | 
|  | 519 | bne	cu_spd			|load single pos zero | 
|  | 520 | bra	cu_spdr			|load single pos zero w/lsb | 
|  | 521 | cu_dmsn: | 
|  | 522 | cmpib	#2,%d1			|check for rm | 
|  | 523 | bne	cu_snd			|load single neg zero | 
|  | 524 | bra	cu_sndr			|load single neg zero w/lsb | 
|  | 525 | | | 
|  | 526 | | The precision is extended, so the result in etemp is correct. | 
|  | 527 | | Simply set unfl (not inex2 or aunfl) and write the result to | 
|  | 528 | | the correct fp register. | 
|  | 529 | cu_wrexd: | 
|  | 530 | orl	#unfl_mask,USER_FPSR(%a6) | 
|  | 531 | tstw	LOCAL_EX(%a0) | 
|  | 532 | beq	wr_etemp | 
|  | 533 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 534 | bra	wr_etemp | 
|  | 535 | | | 
|  | 536 | | These routines write +/- zero in double format.  The routines | 
|  | 537 | | cu_dpdr and cu_dndr set the double lsb. | 
|  | 538 | | | 
|  | 539 | cu_dpd: | 
|  | 540 | movel	#0x3c010000,LOCAL_EX(%a0)	|force pos double zero | 
|  | 541 | clrl	LOCAL_HI(%a0) | 
|  | 542 | clrl	LOCAL_LO(%a0) | 
|  | 543 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 544 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 545 | bra	wr_etemp | 
|  | 546 | cu_dpdr: | 
|  | 547 | movel	#0x3c010000,LOCAL_EX(%a0)	|force pos double zero | 
|  | 548 | clrl	LOCAL_HI(%a0) | 
|  | 549 | movel	#0x800,LOCAL_LO(%a0)	|with lsb set | 
|  | 550 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 551 | bra	wr_etemp | 
|  | 552 | cu_dnd: | 
|  | 553 | movel	#0xbc010000,LOCAL_EX(%a0)	|force pos double zero | 
|  | 554 | clrl	LOCAL_HI(%a0) | 
|  | 555 | clrl	LOCAL_LO(%a0) | 
|  | 556 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 557 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 558 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 559 | bra	wr_etemp | 
|  | 560 | cu_dndr: | 
|  | 561 | movel	#0xbc010000,LOCAL_EX(%a0)	|force pos double zero | 
|  | 562 | clrl	LOCAL_HI(%a0) | 
|  | 563 | movel	#0x800,LOCAL_LO(%a0)	|with lsb set | 
|  | 564 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 565 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 566 | bra	wr_etemp | 
|  | 567 | | | 
|  | 568 | | These routines write +/- zero in single format.  The routines | 
|  | 569 | | cu_dpdr and cu_dndr set the single lsb. | 
|  | 570 | | | 
|  | 571 | cu_spd: | 
|  | 572 | movel	#0x3f810000,LOCAL_EX(%a0)	|force pos single zero | 
|  | 573 | clrl	LOCAL_HI(%a0) | 
|  | 574 | clrl	LOCAL_LO(%a0) | 
|  | 575 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 576 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 577 | bra	wr_etemp | 
|  | 578 | cu_spdr: | 
|  | 579 | movel	#0x3f810000,LOCAL_EX(%a0)	|force pos single zero | 
|  | 580 | movel	#0x100,LOCAL_HI(%a0)	|with lsb set | 
|  | 581 | clrl	LOCAL_LO(%a0) | 
|  | 582 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 583 | bra	wr_etemp | 
|  | 584 | cu_snd: | 
|  | 585 | movel	#0xbf810000,LOCAL_EX(%a0)	|force pos single zero | 
|  | 586 | clrl	LOCAL_HI(%a0) | 
|  | 587 | clrl	LOCAL_LO(%a0) | 
|  | 588 | orl	#z_mask,USER_FPSR(%a6) | 
|  | 589 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 590 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 591 | bra	wr_etemp | 
|  | 592 | cu_sndr: | 
|  | 593 | movel	#0xbf810000,LOCAL_EX(%a0)	|force pos single zero | 
|  | 594 | movel	#0x100,LOCAL_HI(%a0)	|with lsb set | 
|  | 595 | clrl	LOCAL_LO(%a0) | 
|  | 596 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 597 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 598 | bra	wr_etemp | 
|  | 599 |  | 
|  | 600 | | | 
|  | 601 | | This code checks for 16-bit overflow conditions on dyadic | 
|  | 602 | | operations which are not restorable into the floating-point | 
|  | 603 | | unit and must be completed in software.  Basically, this | 
|  | 604 | | condition exists with a very large norm and a denorm.  One | 
|  | 605 | | of the operands must be denormalized to enter this code. | 
|  | 606 | | | 
|  | 607 | | Flags used: | 
|  | 608 | |	DY_MO_FLG contains 0 for monadic op, $ff for dyadic | 
|  | 609 | |	DNRM_FLG contains $00 for neither op denormalized | 
|  | 610 | |	                  $0f for the destination op denormalized | 
|  | 611 | |	                  $f0 for the source op denormalized | 
|  | 612 | |	                  $ff for both ops denormalized | 
|  | 613 | | | 
|  | 614 | | The wrap-around condition occurs for add, sub, div, and cmp | 
|  | 615 | | when | 
|  | 616 | | | 
|  | 617 | |	abs(dest_exp - src_exp) >= $8000 | 
|  | 618 | | | 
|  | 619 | | and for mul when | 
|  | 620 | | | 
|  | 621 | |	(dest_exp + src_exp) < $0 | 
|  | 622 | | | 
|  | 623 | | we must process the operation here if this case is true. | 
|  | 624 | | | 
|  | 625 | | The rts following the frcfpn routine is the exit from res_func | 
|  | 626 | | for this condition.  The restore flag (RES_FLG) is left clear. | 
|  | 627 | | No frestore is done unless an exception is to be reported. | 
|  | 628 | | | 
|  | 629 | | For fadd: | 
|  | 630 | |	if(sign_of(dest) != sign_of(src)) | 
|  | 631 | |		replace exponent of src with $3fff (keep sign) | 
|  | 632 | |		use fpu to perform dest+new_src (user's rmode and X) | 
|  | 633 | |		clr sticky | 
|  | 634 | |	else | 
|  | 635 | |		set sticky | 
|  | 636 | |	call round with user's precision and mode | 
|  | 637 | |	move result to fpn and wbtemp | 
|  | 638 | | | 
|  | 639 | | For fsub: | 
|  | 640 | |	if(sign_of(dest) == sign_of(src)) | 
|  | 641 | |		replace exponent of src with $3fff (keep sign) | 
|  | 642 | |		use fpu to perform dest+new_src (user's rmode and X) | 
|  | 643 | |		clr sticky | 
|  | 644 | |	else | 
|  | 645 | |		set sticky | 
|  | 646 | |	call round with user's precision and mode | 
|  | 647 | |	move result to fpn and wbtemp | 
|  | 648 | | | 
|  | 649 | | For fdiv/fsgldiv: | 
|  | 650 | |	if(both operands are denorm) | 
|  | 651 | |		restore_to_fpu; | 
|  | 652 | |	if(dest is norm) | 
|  | 653 | |		force_ovf; | 
|  | 654 | |	else(dest is denorm) | 
|  | 655 | |		force_unf: | 
|  | 656 | | | 
|  | 657 | | For fcmp: | 
|  | 658 | |	if(dest is norm) | 
|  | 659 | |		N = sign_of(dest); | 
|  | 660 | |	else(dest is denorm) | 
|  | 661 | |		N = sign_of(src); | 
|  | 662 | | | 
|  | 663 | | For fmul: | 
|  | 664 | |	if(both operands are denorm) | 
|  | 665 | |		force_unf; | 
|  | 666 | |	if((dest_exp + src_exp) < 0) | 
|  | 667 | |		force_unf: | 
|  | 668 | |	else | 
|  | 669 | |		restore_to_fpu; | 
|  | 670 | | | 
|  | 671 | | local equates: | 
|  | 672 | .set	addcode,0x22 | 
|  | 673 | .set	subcode,0x28 | 
|  | 674 | .set	mulcode,0x23 | 
|  | 675 | .set	divcode,0x20 | 
|  | 676 | .set	cmpcode,0x38 | 
|  | 677 | ck_wrap: | 
|  | 678 | | tstb	DY_MO_FLG(%a6)	;check for fsqrt | 
|  | 679 | beq	fix_stk		|if zero, it is fsqrt | 
|  | 680 | movew	CMDREG1B(%a6),%d0 | 
|  | 681 | andiw	#0x3b,%d0		|strip to command bits | 
|  | 682 | cmpiw	#addcode,%d0 | 
|  | 683 | beq	wrap_add | 
|  | 684 | cmpiw	#subcode,%d0 | 
|  | 685 | beq	wrap_sub | 
|  | 686 | cmpiw	#mulcode,%d0 | 
|  | 687 | beq	wrap_mul | 
|  | 688 | cmpiw	#cmpcode,%d0 | 
|  | 689 | beq	wrap_cmp | 
|  | 690 | | | 
|  | 691 | | Inst is fdiv. | 
|  | 692 | | | 
|  | 693 | wrap_div: | 
|  | 694 | cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
|  | 695 | beq	fix_stk		 |restore to fpu | 
|  | 696 | | | 
|  | 697 | | One of the ops is denormalized.  Test for wrap condition | 
|  | 698 | | and force the result. | 
|  | 699 | | | 
|  | 700 | cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
|  | 701 | bnes	div_srcd | 
|  | 702 | div_destd: | 
|  | 703 | bsrl	ckinf_ns | 
|  | 704 | bne	fix_stk | 
|  | 705 | bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
|  | 706 | bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
|  | 707 | subl	%d1,%d0			|subtract dest from src | 
|  | 708 | cmpl	#0x7fff,%d0 | 
|  | 709 | blt	fix_stk			|if less, not wrap case | 
|  | 710 | clrb	WBTEMP_SGN(%a6) | 
|  | 711 | movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
|  | 712 | movew	FPTEMP_EX(%a6),%d1 | 
|  | 713 | eorw	%d1,%d0 | 
|  | 714 | andiw	#0x8000,%d0 | 
|  | 715 | beq	force_unf | 
|  | 716 | st	WBTEMP_SGN(%a6) | 
|  | 717 | bra	force_unf | 
|  | 718 |  | 
|  | 719 | ckinf_ns: | 
|  | 720 | moveb	STAG(%a6),%d0		|check source tag for inf or nan | 
|  | 721 | bra	ck_in_com | 
|  | 722 | ckinf_nd: | 
|  | 723 | moveb	DTAG(%a6),%d0		|check destination tag for inf or nan | 
|  | 724 | ck_in_com: | 
|  | 725 | andib	#0x60,%d0			|isolate tag bits | 
|  | 726 | cmpb	#0x40,%d0			|is it inf? | 
|  | 727 | beq	nan_or_inf		|not wrap case | 
|  | 728 | cmpb	#0x60,%d0			|is it nan? | 
|  | 729 | beq	nan_or_inf		|yes, not wrap case? | 
|  | 730 | cmpb	#0x20,%d0			|is it a zero? | 
|  | 731 | beq	nan_or_inf		|yes | 
|  | 732 | clrl	%d0 | 
|  | 733 | rts				|then ; it is either a zero of norm, | 
|  | 734 | |					;check wrap case | 
|  | 735 | nan_or_inf: | 
|  | 736 | moveql	#-1,%d0 | 
|  | 737 | rts | 
|  | 738 |  | 
|  | 739 |  | 
|  | 740 |  | 
|  | 741 | div_srcd: | 
|  | 742 | bsrl	ckinf_nd | 
|  | 743 | bne	fix_stk | 
|  | 744 | bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
|  | 745 | bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
|  | 746 | subl	%d1,%d0			|subtract src from dest | 
|  | 747 | cmpl	#0x8000,%d0 | 
|  | 748 | blt	fix_stk			|if less, not wrap case | 
|  | 749 | clrb	WBTEMP_SGN(%a6) | 
|  | 750 | movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
|  | 751 | movew	FPTEMP_EX(%a6),%d1 | 
|  | 752 | eorw	%d1,%d0 | 
|  | 753 | andiw	#0x8000,%d0 | 
|  | 754 | beqs	force_ovf | 
|  | 755 | st	WBTEMP_SGN(%a6) | 
|  | 756 | | | 
|  | 757 | | This code handles the case of the instruction resulting in | 
|  | 758 | | an overflow condition. | 
|  | 759 | | | 
|  | 760 | force_ovf: | 
|  | 761 | bclrb	#E1,E_BYTE(%a6) | 
|  | 762 | orl	#ovfl_inx_mask,USER_FPSR(%a6) | 
|  | 763 | clrw	NMNEXC(%a6) | 
|  | 764 | leal	WBTEMP(%a6),%a0		|point a0 to memory location | 
|  | 765 | movew	CMDREG1B(%a6),%d0 | 
|  | 766 | btstl	#6,%d0			|test for forced precision | 
|  | 767 | beqs	frcovf_fpcr | 
|  | 768 | btstl	#2,%d0			|check for double | 
|  | 769 | bnes	frcovf_dbl | 
|  | 770 | movel	#0x1,%d0			|inst is forced single | 
|  | 771 | bras	frcovf_rnd | 
|  | 772 | frcovf_dbl: | 
|  | 773 | movel	#0x2,%d0			|inst is forced double | 
|  | 774 | bras	frcovf_rnd | 
|  | 775 | frcovf_fpcr: | 
|  | 776 | bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
|  | 777 | frcovf_rnd: | 
|  | 778 |  | 
|  | 779 | | The 881/882 does not set inex2 for the following case, so the | 
|  | 780 | | line is commented out to be compatible with 881/882 | 
|  | 781 | |	tst.b	%d0 | 
|  | 782 | |	beq.b	frcovf_x | 
|  | 783 | |	or.l	#inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2 | 
|  | 784 |  | 
|  | 785 | |frcovf_x: | 
|  | 786 | bsrl	ovf_res			|get correct result based on | 
|  | 787 | |					;round precision/mode.  This | 
|  | 788 | |					;sets FPSR_CC correctly | 
|  | 789 | |					;returns in external format | 
|  | 790 | bfclr	WBTEMP_SGN(%a6){#0:#8} | 
|  | 791 | beq	frcfpn | 
|  | 792 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 793 | bra	frcfpn | 
|  | 794 | | | 
|  | 795 | | Inst is fadd. | 
|  | 796 | | | 
|  | 797 | wrap_add: | 
|  | 798 | cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
|  | 799 | beq	fix_stk		 |restore to fpu | 
|  | 800 | | | 
|  | 801 | | One of the ops is denormalized.  Test for wrap condition | 
|  | 802 | | and complete the instruction. | 
|  | 803 | | | 
|  | 804 | cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
|  | 805 | bnes	add_srcd | 
|  | 806 | add_destd: | 
|  | 807 | bsrl	ckinf_ns | 
|  | 808 | bne	fix_stk | 
|  | 809 | bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
|  | 810 | bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
|  | 811 | subl	%d1,%d0			|subtract dest from src | 
|  | 812 | cmpl	#0x8000,%d0 | 
|  | 813 | blt	fix_stk			|if less, not wrap case | 
|  | 814 | bra	add_wrap | 
|  | 815 | add_srcd: | 
|  | 816 | bsrl	ckinf_nd | 
|  | 817 | bne	fix_stk | 
|  | 818 | bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
|  | 819 | bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
|  | 820 | subl	%d1,%d0			|subtract src from dest | 
|  | 821 | cmpl	#0x8000,%d0 | 
|  | 822 | blt	fix_stk			|if less, not wrap case | 
|  | 823 | | | 
|  | 824 | | Check the signs of the operands.  If they are unlike, the fpu | 
|  | 825 | | can be used to add the norm and 1.0 with the sign of the | 
|  | 826 | | denorm and it will correctly generate the result in extended | 
|  | 827 | | precision.  We can then call round with no sticky and the result | 
|  | 828 | | will be correct for the user's rounding mode and precision.  If | 
|  | 829 | | the signs are the same, we call round with the sticky bit set | 
|  | 830 | | and the result will be correct for the user's rounding mode and | 
|  | 831 | | precision. | 
|  | 832 | | | 
|  | 833 | add_wrap: | 
|  | 834 | movew	ETEMP_EX(%a6),%d0 | 
|  | 835 | movew	FPTEMP_EX(%a6),%d1 | 
|  | 836 | eorw	%d1,%d0 | 
|  | 837 | andiw	#0x8000,%d0 | 
|  | 838 | beq	add_same | 
|  | 839 | | | 
|  | 840 | | The signs are unlike. | 
|  | 841 | | | 
|  | 842 | cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
|  | 843 | bnes	add_u_srcd | 
|  | 844 | movew	FPTEMP_EX(%a6),%d0 | 
|  | 845 | andiw	#0x8000,%d0 | 
|  | 846 | orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
|  | 847 | movew	%d0,FPTEMP_EX(%a6) |in the denorm | 
|  | 848 | movel	USER_FPCR(%a6),%d0 | 
|  | 849 | andil	#0x30,%d0 | 
|  | 850 | fmovel	%d0,%fpcr		|set up users rmode and X | 
|  | 851 | fmovex	ETEMP(%a6),%fp0 | 
|  | 852 | faddx	FPTEMP(%a6),%fp0 | 
|  | 853 | leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
|  | 854 | fmovel	%fpsr,%d1 | 
|  | 855 | orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
|  | 856 | fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
|  | 857 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 858 | movel	USER_FPCR(%a6),%d1 | 
|  | 859 | andil	#0xc0,%d1 | 
|  | 860 | lsrl	#6,%d1		|put precision in upper word | 
|  | 861 | swap	%d1 | 
|  | 862 | orl	%d0,%d1		|set up for round call | 
|  | 863 | clrl	%d0		|force sticky to zero | 
|  | 864 | bclrb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 865 | sne	WBTEMP_SGN(%a6) | 
|  | 866 | bsrl	round		|round result to users rmode & prec | 
|  | 867 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 868 | beq	frcfpnr | 
|  | 869 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 870 | bra	frcfpnr | 
|  | 871 | add_u_srcd: | 
|  | 872 | movew	ETEMP_EX(%a6),%d0 | 
|  | 873 | andiw	#0x8000,%d0 | 
|  | 874 | orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
|  | 875 | movew	%d0,ETEMP_EX(%a6) |in the denorm | 
|  | 876 | movel	USER_FPCR(%a6),%d0 | 
|  | 877 | andil	#0x30,%d0 | 
|  | 878 | fmovel	%d0,%fpcr		|set up users rmode and X | 
|  | 879 | fmovex	ETEMP(%a6),%fp0 | 
|  | 880 | faddx	FPTEMP(%a6),%fp0 | 
|  | 881 | fmovel	%fpsr,%d1 | 
|  | 882 | orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
|  | 883 | leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
|  | 884 | fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
|  | 885 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 886 | movel	USER_FPCR(%a6),%d1 | 
|  | 887 | andil	#0xc0,%d1 | 
|  | 888 | lsrl	#6,%d1		|put precision in upper word | 
|  | 889 | swap	%d1 | 
|  | 890 | orl	%d0,%d1		|set up for round call | 
|  | 891 | clrl	%d0		|force sticky to zero | 
|  | 892 | bclrb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 893 | sne	WBTEMP_SGN(%a6)	|use internal format for round | 
|  | 894 | bsrl	round		|round result to users rmode & prec | 
|  | 895 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 896 | beq	frcfpnr | 
|  | 897 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 898 | bra	frcfpnr | 
|  | 899 | | | 
|  | 900 | | Signs are alike: | 
|  | 901 | | | 
|  | 902 | add_same: | 
|  | 903 | cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
|  | 904 | bnes	add_s_srcd | 
|  | 905 | add_s_destd: | 
|  | 906 | leal	ETEMP(%a6),%a0 | 
|  | 907 | movel	USER_FPCR(%a6),%d0 | 
|  | 908 | andil	#0x30,%d0 | 
|  | 909 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 910 | movel	USER_FPCR(%a6),%d1 | 
|  | 911 | andil	#0xc0,%d1 | 
|  | 912 | lsrl	#6,%d1		|put precision in upper word | 
|  | 913 | swap	%d1 | 
|  | 914 | orl	%d0,%d1		|set up for round call | 
|  | 915 | movel	#0x20000000,%d0	|set sticky for round | 
|  | 916 | bclrb	#sign_bit,ETEMP_EX(%a6) | 
|  | 917 | sne	ETEMP_SGN(%a6) | 
|  | 918 | bsrl	round		|round result to users rmode & prec | 
|  | 919 | bfclr	ETEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 920 | beqs	add_s_dclr | 
|  | 921 | bsetb	#sign_bit,ETEMP_EX(%a6) | 
|  | 922 | add_s_dclr: | 
|  | 923 | leal	WBTEMP(%a6),%a0 | 
|  | 924 | movel	ETEMP(%a6),(%a0)	|write result to wbtemp | 
|  | 925 | movel	ETEMP_HI(%a6),4(%a0) | 
|  | 926 | movel	ETEMP_LO(%a6),8(%a0) | 
|  | 927 | tstw	ETEMP_EX(%a6) | 
|  | 928 | bgt	add_ckovf | 
|  | 929 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 930 | bra	add_ckovf | 
|  | 931 | add_s_srcd: | 
|  | 932 | leal	FPTEMP(%a6),%a0 | 
|  | 933 | movel	USER_FPCR(%a6),%d0 | 
|  | 934 | andil	#0x30,%d0 | 
|  | 935 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 936 | movel	USER_FPCR(%a6),%d1 | 
|  | 937 | andil	#0xc0,%d1 | 
|  | 938 | lsrl	#6,%d1		|put precision in upper word | 
|  | 939 | swap	%d1 | 
|  | 940 | orl	%d0,%d1		|set up for round call | 
|  | 941 | movel	#0x20000000,%d0	|set sticky for round | 
|  | 942 | bclrb	#sign_bit,FPTEMP_EX(%a6) | 
|  | 943 | sne	FPTEMP_SGN(%a6) | 
|  | 944 | bsrl	round		|round result to users rmode & prec | 
|  | 945 | bfclr	FPTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 946 | beqs	add_s_sclr | 
|  | 947 | bsetb	#sign_bit,FPTEMP_EX(%a6) | 
|  | 948 | add_s_sclr: | 
|  | 949 | leal	WBTEMP(%a6),%a0 | 
|  | 950 | movel	FPTEMP(%a6),(%a0)	|write result to wbtemp | 
|  | 951 | movel	FPTEMP_HI(%a6),4(%a0) | 
|  | 952 | movel	FPTEMP_LO(%a6),8(%a0) | 
|  | 953 | tstw	FPTEMP_EX(%a6) | 
|  | 954 | bgt	add_ckovf | 
|  | 955 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 956 | add_ckovf: | 
|  | 957 | movew	WBTEMP_EX(%a6),%d0 | 
|  | 958 | andiw	#0x7fff,%d0 | 
|  | 959 | cmpiw	#0x7fff,%d0 | 
|  | 960 | bne	frcfpnr | 
|  | 961 | | | 
|  | 962 | | The result has overflowed to $7fff exponent.  Set I, ovfl, | 
|  | 963 | | and aovfl, and clr the mantissa (incorrectly set by the | 
|  | 964 | | round routine.) | 
|  | 965 | | | 
|  | 966 | orl	#inf_mask+ovfl_inx_mask,USER_FPSR(%a6) | 
|  | 967 | clrl	4(%a0) | 
|  | 968 | bra	frcfpnr | 
|  | 969 | | | 
|  | 970 | | Inst is fsub. | 
|  | 971 | | | 
|  | 972 | wrap_sub: | 
|  | 973 | cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
|  | 974 | beq	fix_stk		 |restore to fpu | 
|  | 975 | | | 
|  | 976 | | One of the ops is denormalized.  Test for wrap condition | 
|  | 977 | | and complete the instruction. | 
|  | 978 | | | 
|  | 979 | cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
|  | 980 | bnes	sub_srcd | 
|  | 981 | sub_destd: | 
|  | 982 | bsrl	ckinf_ns | 
|  | 983 | bne	fix_stk | 
|  | 984 | bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
|  | 985 | bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
|  | 986 | subl	%d1,%d0			|subtract src from dest | 
|  | 987 | cmpl	#0x8000,%d0 | 
|  | 988 | blt	fix_stk			|if less, not wrap case | 
|  | 989 | bra	sub_wrap | 
|  | 990 | sub_srcd: | 
|  | 991 | bsrl	ckinf_nd | 
|  | 992 | bne	fix_stk | 
|  | 993 | bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
|  | 994 | bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
|  | 995 | subl	%d1,%d0			|subtract dest from src | 
|  | 996 | cmpl	#0x8000,%d0 | 
|  | 997 | blt	fix_stk			|if less, not wrap case | 
|  | 998 | | | 
|  | 999 | | Check the signs of the operands.  If they are alike, the fpu | 
|  | 1000 | | can be used to subtract from the norm 1.0 with the sign of the | 
|  | 1001 | | denorm and it will correctly generate the result in extended | 
|  | 1002 | | precision.  We can then call round with no sticky and the result | 
|  | 1003 | | will be correct for the user's rounding mode and precision.  If | 
|  | 1004 | | the signs are unlike, we call round with the sticky bit set | 
|  | 1005 | | and the result will be correct for the user's rounding mode and | 
|  | 1006 | | precision. | 
|  | 1007 | | | 
|  | 1008 | sub_wrap: | 
|  | 1009 | movew	ETEMP_EX(%a6),%d0 | 
|  | 1010 | movew	FPTEMP_EX(%a6),%d1 | 
|  | 1011 | eorw	%d1,%d0 | 
|  | 1012 | andiw	#0x8000,%d0 | 
|  | 1013 | bne	sub_diff | 
|  | 1014 | | | 
|  | 1015 | | The signs are alike. | 
|  | 1016 | | | 
|  | 1017 | cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
|  | 1018 | bnes	sub_u_srcd | 
|  | 1019 | movew	FPTEMP_EX(%a6),%d0 | 
|  | 1020 | andiw	#0x8000,%d0 | 
|  | 1021 | orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
|  | 1022 | movew	%d0,FPTEMP_EX(%a6) |in the denorm | 
|  | 1023 | movel	USER_FPCR(%a6),%d0 | 
|  | 1024 | andil	#0x30,%d0 | 
|  | 1025 | fmovel	%d0,%fpcr		|set up users rmode and X | 
|  | 1026 | fmovex	FPTEMP(%a6),%fp0 | 
|  | 1027 | fsubx	ETEMP(%a6),%fp0 | 
|  | 1028 | fmovel	%fpsr,%d1 | 
|  | 1029 | orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
|  | 1030 | leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
|  | 1031 | fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
|  | 1032 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 1033 | movel	USER_FPCR(%a6),%d1 | 
|  | 1034 | andil	#0xc0,%d1 | 
|  | 1035 | lsrl	#6,%d1		|put precision in upper word | 
|  | 1036 | swap	%d1 | 
|  | 1037 | orl	%d0,%d1		|set up for round call | 
|  | 1038 | clrl	%d0		|force sticky to zero | 
|  | 1039 | bclrb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1040 | sne	WBTEMP_SGN(%a6) | 
|  | 1041 | bsrl	round		|round result to users rmode & prec | 
|  | 1042 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1043 | beq	frcfpnr | 
|  | 1044 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1045 | bra	frcfpnr | 
|  | 1046 | sub_u_srcd: | 
|  | 1047 | movew	ETEMP_EX(%a6),%d0 | 
|  | 1048 | andiw	#0x8000,%d0 | 
|  | 1049 | orw	#0x3fff,%d0	|force the exponent to +/- 1 | 
|  | 1050 | movew	%d0,ETEMP_EX(%a6) |in the denorm | 
|  | 1051 | movel	USER_FPCR(%a6),%d0 | 
|  | 1052 | andil	#0x30,%d0 | 
|  | 1053 | fmovel	%d0,%fpcr		|set up users rmode and X | 
|  | 1054 | fmovex	FPTEMP(%a6),%fp0 | 
|  | 1055 | fsubx	ETEMP(%a6),%fp0 | 
|  | 1056 | fmovel	%fpsr,%d1 | 
|  | 1057 | orl	%d1,USER_FPSR(%a6) |capture cc's and inex from fadd | 
|  | 1058 | leal	WBTEMP(%a6),%a0	|point a0 to wbtemp in frame | 
|  | 1059 | fmovex	%fp0,WBTEMP(%a6)	|write result to memory | 
|  | 1060 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 1061 | movel	USER_FPCR(%a6),%d1 | 
|  | 1062 | andil	#0xc0,%d1 | 
|  | 1063 | lsrl	#6,%d1		|put precision in upper word | 
|  | 1064 | swap	%d1 | 
|  | 1065 | orl	%d0,%d1		|set up for round call | 
|  | 1066 | clrl	%d0		|force sticky to zero | 
|  | 1067 | bclrb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1068 | sne	WBTEMP_SGN(%a6) | 
|  | 1069 | bsrl	round		|round result to users rmode & prec | 
|  | 1070 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1071 | beq	frcfpnr | 
|  | 1072 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1073 | bra	frcfpnr | 
|  | 1074 | | | 
|  | 1075 | | Signs are unlike: | 
|  | 1076 | | | 
|  | 1077 | sub_diff: | 
|  | 1078 | cmpb	#0x0f,DNRM_FLG(%a6) |is dest the denorm? | 
|  | 1079 | bnes	sub_s_srcd | 
|  | 1080 | sub_s_destd: | 
|  | 1081 | leal	ETEMP(%a6),%a0 | 
|  | 1082 | movel	USER_FPCR(%a6),%d0 | 
|  | 1083 | andil	#0x30,%d0 | 
|  | 1084 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 1085 | movel	USER_FPCR(%a6),%d1 | 
|  | 1086 | andil	#0xc0,%d1 | 
|  | 1087 | lsrl	#6,%d1		|put precision in upper word | 
|  | 1088 | swap	%d1 | 
|  | 1089 | orl	%d0,%d1		|set up for round call | 
|  | 1090 | movel	#0x20000000,%d0	|set sticky for round | 
|  | 1091 | | | 
|  | 1092 | | Since the dest is the denorm, the sign is the opposite of the | 
|  | 1093 | | norm sign. | 
|  | 1094 | | | 
|  | 1095 | eoriw	#0x8000,ETEMP_EX(%a6)	|flip sign on result | 
|  | 1096 | tstw	ETEMP_EX(%a6) | 
|  | 1097 | bgts	sub_s_dwr | 
|  | 1098 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1099 | sub_s_dwr: | 
|  | 1100 | bclrb	#sign_bit,ETEMP_EX(%a6) | 
|  | 1101 | sne	ETEMP_SGN(%a6) | 
|  | 1102 | bsrl	round		|round result to users rmode & prec | 
|  | 1103 | bfclr	ETEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1104 | beqs	sub_s_dclr | 
|  | 1105 | bsetb	#sign_bit,ETEMP_EX(%a6) | 
|  | 1106 | sub_s_dclr: | 
|  | 1107 | leal	WBTEMP(%a6),%a0 | 
|  | 1108 | movel	ETEMP(%a6),(%a0)	|write result to wbtemp | 
|  | 1109 | movel	ETEMP_HI(%a6),4(%a0) | 
|  | 1110 | movel	ETEMP_LO(%a6),8(%a0) | 
|  | 1111 | bra	sub_ckovf | 
|  | 1112 | sub_s_srcd: | 
|  | 1113 | leal	FPTEMP(%a6),%a0 | 
|  | 1114 | movel	USER_FPCR(%a6),%d0 | 
|  | 1115 | andil	#0x30,%d0 | 
|  | 1116 | lsrl	#4,%d0		|put rmode in lower 2 bits | 
|  | 1117 | movel	USER_FPCR(%a6),%d1 | 
|  | 1118 | andil	#0xc0,%d1 | 
|  | 1119 | lsrl	#6,%d1		|put precision in upper word | 
|  | 1120 | swap	%d1 | 
|  | 1121 | orl	%d0,%d1		|set up for round call | 
|  | 1122 | movel	#0x20000000,%d0	|set sticky for round | 
|  | 1123 | bclrb	#sign_bit,FPTEMP_EX(%a6) | 
|  | 1124 | sne	FPTEMP_SGN(%a6) | 
|  | 1125 | bsrl	round		|round result to users rmode & prec | 
|  | 1126 | bfclr	FPTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1127 | beqs	sub_s_sclr | 
|  | 1128 | bsetb	#sign_bit,FPTEMP_EX(%a6) | 
|  | 1129 | sub_s_sclr: | 
|  | 1130 | leal	WBTEMP(%a6),%a0 | 
|  | 1131 | movel	FPTEMP(%a6),(%a0)	|write result to wbtemp | 
|  | 1132 | movel	FPTEMP_HI(%a6),4(%a0) | 
|  | 1133 | movel	FPTEMP_LO(%a6),8(%a0) | 
|  | 1134 | tstw	FPTEMP_EX(%a6) | 
|  | 1135 | bgt	sub_ckovf | 
|  | 1136 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1137 | sub_ckovf: | 
|  | 1138 | movew	WBTEMP_EX(%a6),%d0 | 
|  | 1139 | andiw	#0x7fff,%d0 | 
|  | 1140 | cmpiw	#0x7fff,%d0 | 
|  | 1141 | bne	frcfpnr | 
|  | 1142 | | | 
|  | 1143 | | The result has overflowed to $7fff exponent.  Set I, ovfl, | 
|  | 1144 | | and aovfl, and clr the mantissa (incorrectly set by the | 
|  | 1145 | | round routine.) | 
|  | 1146 | | | 
|  | 1147 | orl	#inf_mask+ovfl_inx_mask,USER_FPSR(%a6) | 
|  | 1148 | clrl	4(%a0) | 
|  | 1149 | bra	frcfpnr | 
|  | 1150 | | | 
|  | 1151 | | Inst is fcmp. | 
|  | 1152 | | | 
|  | 1153 | wrap_cmp: | 
|  | 1154 | cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
|  | 1155 | beq	fix_stk		 |restore to fpu | 
|  | 1156 | | | 
|  | 1157 | | One of the ops is denormalized.  Test for wrap condition | 
|  | 1158 | | and complete the instruction. | 
|  | 1159 | | | 
|  | 1160 | cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
|  | 1161 | bnes	cmp_srcd | 
|  | 1162 | cmp_destd: | 
|  | 1163 | bsrl	ckinf_ns | 
|  | 1164 | bne	fix_stk | 
|  | 1165 | bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
|  | 1166 | bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
|  | 1167 | subl	%d1,%d0			|subtract dest from src | 
|  | 1168 | cmpl	#0x8000,%d0 | 
|  | 1169 | blt	fix_stk			|if less, not wrap case | 
|  | 1170 | tstw	ETEMP_EX(%a6)		|set N to ~sign_of(src) | 
|  | 1171 | bge	cmp_setn | 
|  | 1172 | rts | 
|  | 1173 | cmp_srcd: | 
|  | 1174 | bsrl	ckinf_nd | 
|  | 1175 | bne	fix_stk | 
|  | 1176 | bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
|  | 1177 | bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
|  | 1178 | subl	%d1,%d0			|subtract src from dest | 
|  | 1179 | cmpl	#0x8000,%d0 | 
|  | 1180 | blt	fix_stk			|if less, not wrap case | 
|  | 1181 | tstw	FPTEMP_EX(%a6)		|set N to sign_of(dest) | 
|  | 1182 | blt	cmp_setn | 
|  | 1183 | rts | 
|  | 1184 | cmp_setn: | 
|  | 1185 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1186 | rts | 
|  | 1187 |  | 
|  | 1188 | | | 
|  | 1189 | | Inst is fmul. | 
|  | 1190 | | | 
|  | 1191 | wrap_mul: | 
|  | 1192 | cmpb	#0xff,DNRM_FLG(%a6) |if both ops denorm, | 
|  | 1193 | beq	force_unf	|force an underflow (really!) | 
|  | 1194 | | | 
|  | 1195 | | One of the ops is denormalized.  Test for wrap condition | 
|  | 1196 | | and complete the instruction. | 
|  | 1197 | | | 
|  | 1198 | cmpb	#0x0f,DNRM_FLG(%a6) |check for dest denorm | 
|  | 1199 | bnes	mul_srcd | 
|  | 1200 | mul_destd: | 
|  | 1201 | bsrl	ckinf_ns | 
|  | 1202 | bne	fix_stk | 
|  | 1203 | bfextu	ETEMP_EX(%a6){#1:#15},%d0	|get src exp (always pos) | 
|  | 1204 | bfexts	FPTEMP_EX(%a6){#1:#15},%d1	|get dest exp (always neg) | 
|  | 1205 | addl	%d1,%d0			|subtract dest from src | 
|  | 1206 | bgt	fix_stk | 
|  | 1207 | bra	force_unf | 
|  | 1208 | mul_srcd: | 
|  | 1209 | bsrl	ckinf_nd | 
|  | 1210 | bne	fix_stk | 
|  | 1211 | bfextu	FPTEMP_EX(%a6){#1:#15},%d0	|get dest exp (always pos) | 
|  | 1212 | bfexts	ETEMP_EX(%a6){#1:#15},%d1	|get src exp (always neg) | 
|  | 1213 | addl	%d1,%d0			|subtract src from dest | 
|  | 1214 | bgt	fix_stk | 
|  | 1215 |  | 
|  | 1216 | | | 
|  | 1217 | | This code handles the case of the instruction resulting in | 
|  | 1218 | | an underflow condition. | 
|  | 1219 | | | 
|  | 1220 | force_unf: | 
|  | 1221 | bclrb	#E1,E_BYTE(%a6) | 
|  | 1222 | orl	#unfinx_mask,USER_FPSR(%a6) | 
|  | 1223 | clrw	NMNEXC(%a6) | 
|  | 1224 | clrb	WBTEMP_SGN(%a6) | 
|  | 1225 | movew	ETEMP_EX(%a6),%d0		|find the sign of the result | 
|  | 1226 | movew	FPTEMP_EX(%a6),%d1 | 
|  | 1227 | eorw	%d1,%d0 | 
|  | 1228 | andiw	#0x8000,%d0 | 
|  | 1229 | beqs	frcunfcont | 
|  | 1230 | st	WBTEMP_SGN(%a6) | 
|  | 1231 | frcunfcont: | 
|  | 1232 | lea	WBTEMP(%a6),%a0		|point a0 to memory location | 
|  | 1233 | movew	CMDREG1B(%a6),%d0 | 
|  | 1234 | btstl	#6,%d0			|test for forced precision | 
|  | 1235 | beqs	frcunf_fpcr | 
|  | 1236 | btstl	#2,%d0			|check for double | 
|  | 1237 | bnes	frcunf_dbl | 
|  | 1238 | movel	#0x1,%d0			|inst is forced single | 
|  | 1239 | bras	frcunf_rnd | 
|  | 1240 | frcunf_dbl: | 
|  | 1241 | movel	#0x2,%d0			|inst is forced double | 
|  | 1242 | bras	frcunf_rnd | 
|  | 1243 | frcunf_fpcr: | 
|  | 1244 | bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
|  | 1245 | frcunf_rnd: | 
|  | 1246 | bsrl	unf_sub			|get correct result based on | 
|  | 1247 | |					;round precision/mode.  This | 
|  | 1248 | |					;sets FPSR_CC correctly | 
|  | 1249 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1250 | beqs	frcfpn | 
|  | 1251 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1252 | bra	frcfpn | 
|  | 1253 |  | 
|  | 1254 | | | 
|  | 1255 | | Write the result to the user's fpn.  All results must be HUGE to be | 
|  | 1256 | | written; otherwise the results would have overflowed or underflowed. | 
|  | 1257 | | If the rounding precision is single or double, the ovf_res routine | 
|  | 1258 | | is needed to correctly supply the max value. | 
|  | 1259 | | | 
|  | 1260 | frcfpnr: | 
|  | 1261 | movew	CMDREG1B(%a6),%d0 | 
|  | 1262 | btstl	#6,%d0			|test for forced precision | 
|  | 1263 | beqs	frcfpn_fpcr | 
|  | 1264 | btstl	#2,%d0			|check for double | 
|  | 1265 | bnes	frcfpn_dbl | 
|  | 1266 | movel	#0x1,%d0			|inst is forced single | 
|  | 1267 | bras	frcfpn_rnd | 
|  | 1268 | frcfpn_dbl: | 
|  | 1269 | movel	#0x2,%d0			|inst is forced double | 
|  | 1270 | bras	frcfpn_rnd | 
|  | 1271 | frcfpn_fpcr: | 
|  | 1272 | bfextu	FPCR_MODE(%a6){#0:#2},%d0	|inst not forced - use fpcr prec | 
|  | 1273 | tstb	%d0 | 
|  | 1274 | beqs	frcfpn			|if extended, write what you got | 
|  | 1275 | frcfpn_rnd: | 
|  | 1276 | bclrb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1277 | sne	WBTEMP_SGN(%a6) | 
|  | 1278 | bsrl	ovf_res			|get correct result based on | 
|  | 1279 | |					;round precision/mode.  This | 
|  | 1280 | |					;sets FPSR_CC correctly | 
|  | 1281 | bfclr	WBTEMP_SGN(%a6){#0:#8}	|convert back to IEEE ext format | 
|  | 1282 | beqs	frcfpn_clr | 
|  | 1283 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1284 | frcfpn_clr: | 
|  | 1285 | orl	#ovfinx_mask,USER_FPSR(%a6) | 
|  | 1286 | | | 
|  | 1287 | | Perform the write. | 
|  | 1288 | | | 
|  | 1289 | frcfpn: | 
|  | 1290 | bfextu	CMDREG1B(%a6){#6:#3},%d0	|extract fp destination register | 
|  | 1291 | cmpib	#3,%d0 | 
|  | 1292 | bles	frc0123			|check if dest is fp0-fp3 | 
|  | 1293 | movel	#7,%d1 | 
|  | 1294 | subl	%d0,%d1 | 
|  | 1295 | clrl	%d0 | 
|  | 1296 | bsetl	%d1,%d0 | 
|  | 1297 | fmovemx WBTEMP(%a6),%d0 | 
|  | 1298 | rts | 
|  | 1299 | frc0123: | 
|  | 1300 | cmpib	#0,%d0 | 
|  | 1301 | beqs	frc0_dst | 
|  | 1302 | cmpib	#1,%d0 | 
|  | 1303 | beqs	frc1_dst | 
|  | 1304 | cmpib	#2,%d0 | 
|  | 1305 | beqs	frc2_dst | 
|  | 1306 | frc3_dst: | 
|  | 1307 | movel	WBTEMP_EX(%a6),USER_FP3(%a6) | 
|  | 1308 | movel	WBTEMP_HI(%a6),USER_FP3+4(%a6) | 
|  | 1309 | movel	WBTEMP_LO(%a6),USER_FP3+8(%a6) | 
|  | 1310 | rts | 
|  | 1311 | frc2_dst: | 
|  | 1312 | movel	WBTEMP_EX(%a6),USER_FP2(%a6) | 
|  | 1313 | movel	WBTEMP_HI(%a6),USER_FP2+4(%a6) | 
|  | 1314 | movel	WBTEMP_LO(%a6),USER_FP2+8(%a6) | 
|  | 1315 | rts | 
|  | 1316 | frc1_dst: | 
|  | 1317 | movel	WBTEMP_EX(%a6),USER_FP1(%a6) | 
|  | 1318 | movel	WBTEMP_HI(%a6),USER_FP1+4(%a6) | 
|  | 1319 | movel	WBTEMP_LO(%a6),USER_FP1+8(%a6) | 
|  | 1320 | rts | 
|  | 1321 | frc0_dst: | 
|  | 1322 | movel	WBTEMP_EX(%a6),USER_FP0(%a6) | 
|  | 1323 | movel	WBTEMP_HI(%a6),USER_FP0+4(%a6) | 
|  | 1324 | movel	WBTEMP_LO(%a6),USER_FP0+8(%a6) | 
|  | 1325 | rts | 
|  | 1326 |  | 
|  | 1327 | | | 
|  | 1328 | | Write etemp to fpn. | 
|  | 1329 | | A check is made on enabled and signalled snan exceptions, | 
|  | 1330 | | and the destination is not overwritten if this condition exists. | 
|  | 1331 | | This code is designed to make fmoveins of unsupported data types | 
|  | 1332 | | faster. | 
|  | 1333 | | | 
|  | 1334 | wr_etemp: | 
|  | 1335 | btstb	#snan_bit,FPSR_EXCEPT(%a6)	|if snan is set, and | 
|  | 1336 | beqs	fmoveinc		|enabled, force restore | 
|  | 1337 | btstb	#snan_bit,FPCR_ENABLE(%a6) |and don't overwrite | 
|  | 1338 | beqs	fmoveinc		|the dest | 
|  | 1339 | movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
|  | 1340 | |						;snan handler | 
|  | 1341 | tstb	ETEMP(%a6)		|check for negative | 
|  | 1342 | blts	snan_neg | 
|  | 1343 | rts | 
|  | 1344 | snan_neg: | 
|  | 1345 | orl	#neg_bit,USER_FPSR(%a6)	|snan is negative; set N | 
|  | 1346 | rts | 
|  | 1347 | fmoveinc: | 
|  | 1348 | clrw	NMNEXC(%a6) | 
|  | 1349 | bclrb	#E1,E_BYTE(%a6) | 
|  | 1350 | moveb	STAG(%a6),%d0		|check if stag is inf | 
|  | 1351 | andib	#0xe0,%d0 | 
|  | 1352 | cmpib	#0x40,%d0 | 
|  | 1353 | bnes	fminc_cnan | 
|  | 1354 | orl	#inf_mask,USER_FPSR(%a6) |if inf, nothing yet has set I | 
|  | 1355 | tstw	LOCAL_EX(%a0)		|check sign | 
|  | 1356 | bges	fminc_con | 
|  | 1357 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1358 | bra	fminc_con | 
|  | 1359 | fminc_cnan: | 
|  | 1360 | cmpib	#0x60,%d0			|check if stag is NaN | 
|  | 1361 | bnes	fminc_czero | 
|  | 1362 | orl	#nan_mask,USER_FPSR(%a6) |if nan, nothing yet has set NaN | 
|  | 1363 | movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for | 
|  | 1364 | |						;snan handler | 
|  | 1365 | tstw	LOCAL_EX(%a0)		|check sign | 
|  | 1366 | bges	fminc_con | 
|  | 1367 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1368 | bra	fminc_con | 
|  | 1369 | fminc_czero: | 
|  | 1370 | cmpib	#0x20,%d0			|check if zero | 
|  | 1371 | bnes	fminc_con | 
|  | 1372 | orl	#z_mask,USER_FPSR(%a6)	|if zero, set Z | 
|  | 1373 | tstw	LOCAL_EX(%a0)		|check sign | 
|  | 1374 | bges	fminc_con | 
|  | 1375 | orl	#neg_mask,USER_FPSR(%a6) | 
|  | 1376 | fminc_con: | 
|  | 1377 | bfextu	CMDREG1B(%a6){#6:#3},%d0	|extract fp destination register | 
|  | 1378 | cmpib	#3,%d0 | 
|  | 1379 | bles	fp0123			|check if dest is fp0-fp3 | 
|  | 1380 | movel	#7,%d1 | 
|  | 1381 | subl	%d0,%d1 | 
|  | 1382 | clrl	%d0 | 
|  | 1383 | bsetl	%d1,%d0 | 
|  | 1384 | fmovemx ETEMP(%a6),%d0 | 
|  | 1385 | rts | 
|  | 1386 |  | 
|  | 1387 | fp0123: | 
|  | 1388 | cmpib	#0,%d0 | 
|  | 1389 | beqs	fp0_dst | 
|  | 1390 | cmpib	#1,%d0 | 
|  | 1391 | beqs	fp1_dst | 
|  | 1392 | cmpib	#2,%d0 | 
|  | 1393 | beqs	fp2_dst | 
|  | 1394 | fp3_dst: | 
|  | 1395 | movel	ETEMP_EX(%a6),USER_FP3(%a6) | 
|  | 1396 | movel	ETEMP_HI(%a6),USER_FP3+4(%a6) | 
|  | 1397 | movel	ETEMP_LO(%a6),USER_FP3+8(%a6) | 
|  | 1398 | rts | 
|  | 1399 | fp2_dst: | 
|  | 1400 | movel	ETEMP_EX(%a6),USER_FP2(%a6) | 
|  | 1401 | movel	ETEMP_HI(%a6),USER_FP2+4(%a6) | 
|  | 1402 | movel	ETEMP_LO(%a6),USER_FP2+8(%a6) | 
|  | 1403 | rts | 
|  | 1404 | fp1_dst: | 
|  | 1405 | movel	ETEMP_EX(%a6),USER_FP1(%a6) | 
|  | 1406 | movel	ETEMP_HI(%a6),USER_FP1+4(%a6) | 
|  | 1407 | movel	ETEMP_LO(%a6),USER_FP1+8(%a6) | 
|  | 1408 | rts | 
|  | 1409 | fp0_dst: | 
|  | 1410 | movel	ETEMP_EX(%a6),USER_FP0(%a6) | 
|  | 1411 | movel	ETEMP_HI(%a6),USER_FP0+4(%a6) | 
|  | 1412 | movel	ETEMP_LO(%a6),USER_FP0+8(%a6) | 
|  | 1413 | rts | 
|  | 1414 |  | 
|  | 1415 | opclass3: | 
|  | 1416 | st	CU_ONLY(%a6) | 
|  | 1417 | movew	CMDREG1B(%a6),%d0	|check if packed moveout | 
|  | 1418 | andiw	#0x0c00,%d0	|isolate last 2 bits of size field | 
|  | 1419 | cmpiw	#0x0c00,%d0	|if size is 011 or 111, it is packed | 
|  | 1420 | beq	pack_out	|else it is norm or denorm | 
|  | 1421 | bra	mv_out | 
|  | 1422 |  | 
|  | 1423 |  | 
|  | 1424 | | | 
|  | 1425 | |	MOVE OUT | 
|  | 1426 | | | 
|  | 1427 |  | 
|  | 1428 | mv_tbl: | 
|  | 1429 | .long	li | 
|  | 1430 | .long	sgp | 
|  | 1431 | .long	xp | 
|  | 1432 | .long	mvout_end	|should never be taken | 
|  | 1433 | .long	wi | 
|  | 1434 | .long	dp | 
|  | 1435 | .long	bi | 
|  | 1436 | .long	mvout_end	|should never be taken | 
|  | 1437 | mv_out: | 
|  | 1438 | bfextu	CMDREG1B(%a6){#3:#3},%d1	|put source specifier in d1 | 
|  | 1439 | leal	mv_tbl,%a0 | 
|  | 1440 | movel	%a0@(%d1:l:4),%a0 | 
|  | 1441 | jmp	(%a0) | 
|  | 1442 |  | 
|  | 1443 | | | 
|  | 1444 | | This exit is for move-out to memory.  The aunfl bit is | 
|  | 1445 | | set if the result is inex and unfl is signalled. | 
|  | 1446 | | | 
|  | 1447 | mvout_end: | 
|  | 1448 | btstb	#inex2_bit,FPSR_EXCEPT(%a6) | 
|  | 1449 | beqs	no_aufl | 
|  | 1450 | btstb	#unfl_bit,FPSR_EXCEPT(%a6) | 
|  | 1451 | beqs	no_aufl | 
|  | 1452 | bsetb	#aunfl_bit,FPSR_AEXCEPT(%a6) | 
|  | 1453 | no_aufl: | 
|  | 1454 | clrw	NMNEXC(%a6) | 
|  | 1455 | bclrb	#E1,E_BYTE(%a6) | 
|  | 1456 | fmovel	#0,%FPSR			|clear any cc bits from res_func | 
|  | 1457 | | | 
|  | 1458 | | Return ETEMP to extended format from internal extended format so | 
|  | 1459 | | that gen_except will have a correctly signed value for ovfl/unfl | 
|  | 1460 | | handlers. | 
|  | 1461 | | | 
|  | 1462 | bfclr	ETEMP_SGN(%a6){#0:#8} | 
|  | 1463 | beqs	mvout_con | 
|  | 1464 | bsetb	#sign_bit,ETEMP_EX(%a6) | 
|  | 1465 | mvout_con: | 
|  | 1466 | rts | 
|  | 1467 | | | 
|  | 1468 | | This exit is for move-out to int register.  The aunfl bit is | 
|  | 1469 | | not set in any case for this move. | 
|  | 1470 | | | 
|  | 1471 | mvouti_end: | 
|  | 1472 | clrw	NMNEXC(%a6) | 
|  | 1473 | bclrb	#E1,E_BYTE(%a6) | 
|  | 1474 | fmovel	#0,%FPSR			|clear any cc bits from res_func | 
|  | 1475 | | | 
|  | 1476 | | Return ETEMP to extended format from internal extended format so | 
|  | 1477 | | that gen_except will have a correctly signed value for ovfl/unfl | 
|  | 1478 | | handlers. | 
|  | 1479 | | | 
|  | 1480 | bfclr	ETEMP_SGN(%a6){#0:#8} | 
|  | 1481 | beqs	mvouti_con | 
|  | 1482 | bsetb	#sign_bit,ETEMP_EX(%a6) | 
|  | 1483 | mvouti_con: | 
|  | 1484 | rts | 
|  | 1485 | | | 
|  | 1486 | | li is used to handle a long integer source specifier | 
|  | 1487 | | | 
|  | 1488 |  | 
|  | 1489 | li: | 
|  | 1490 | moveql	#4,%d0		|set byte count | 
|  | 1491 |  | 
|  | 1492 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1493 | bne	int_dnrm	|if so, branch | 
|  | 1494 |  | 
|  | 1495 | fmovemx ETEMP(%a6),%fp0-%fp0 | 
|  | 1496 | fcmpd	#0x41dfffffffc00000,%fp0 | 
|  | 1497 | | 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec | 
|  | 1498 | fbge	lo_plrg | 
|  | 1499 | fcmpd	#0xc1e0000000000000,%fp0 | 
|  | 1500 | | c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec | 
|  | 1501 | fble	lo_nlrg | 
|  | 1502 | | | 
|  | 1503 | | at this point, the answer is between the largest pos and neg values | 
|  | 1504 | | | 
|  | 1505 | movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
|  | 1506 | andil	#0x30,%d1 | 
|  | 1507 | fmovel	%d1,%fpcr | 
|  | 1508 | fmovel	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
|  | 1509 | fmovel %fpsr,%d1 | 
|  | 1510 | orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
|  | 1511 | bra	int_wrt | 
|  | 1512 |  | 
|  | 1513 |  | 
|  | 1514 | lo_plrg: | 
|  | 1515 | movel	#0x7fffffff,L_SCR1(%a6)	|answer is largest positive int | 
|  | 1516 | fbeq	int_wrt			|exact answer | 
|  | 1517 | fcmpd	#0x41dfffffffe00000,%fp0 | 
|  | 1518 | | 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec | 
|  | 1519 | fbge	int_operr		|set operr | 
|  | 1520 | bra	int_inx			|set inexact | 
|  | 1521 |  | 
|  | 1522 | lo_nlrg: | 
|  | 1523 | movel	#0x80000000,L_SCR1(%a6) | 
|  | 1524 | fbeq	int_wrt			|exact answer | 
|  | 1525 | fcmpd	#0xc1e0000000100000,%fp0 | 
|  | 1526 | | c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec | 
|  | 1527 | fblt	int_operr		|set operr | 
|  | 1528 | bra	int_inx			|set inexact | 
|  | 1529 |  | 
|  | 1530 | | | 
|  | 1531 | | wi is used to handle a word integer source specifier | 
|  | 1532 | | | 
|  | 1533 |  | 
|  | 1534 | wi: | 
|  | 1535 | moveql	#2,%d0		|set byte count | 
|  | 1536 |  | 
|  | 1537 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1538 | bne	int_dnrm	|branch if so | 
|  | 1539 |  | 
|  | 1540 | fmovemx ETEMP(%a6),%fp0-%fp0 | 
|  | 1541 | fcmps	#0x46fffe00,%fp0 | 
|  | 1542 | | 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec | 
|  | 1543 | fbge	wo_plrg | 
|  | 1544 | fcmps	#0xc7000000,%fp0 | 
|  | 1545 | | c7000000 in sgl prec = c00e00008000000000000000 in ext prec | 
|  | 1546 | fble	wo_nlrg | 
|  | 1547 |  | 
|  | 1548 | | | 
|  | 1549 | | at this point, the answer is between the largest pos and neg values | 
|  | 1550 | | | 
|  | 1551 | movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
|  | 1552 | andil	#0x30,%d1 | 
|  | 1553 | fmovel	%d1,%fpcr | 
|  | 1554 | fmovew	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
|  | 1555 | fmovel %fpsr,%d1 | 
|  | 1556 | orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
|  | 1557 | bra	int_wrt | 
|  | 1558 |  | 
|  | 1559 | wo_plrg: | 
|  | 1560 | movew	#0x7fff,L_SCR1(%a6)	|answer is largest positive int | 
|  | 1561 | fbeq	int_wrt			|exact answer | 
|  | 1562 | fcmps	#0x46ffff00,%fp0 | 
|  | 1563 | | 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec | 
|  | 1564 | fbge	int_operr		|set operr | 
|  | 1565 | bra	int_inx			|set inexact | 
|  | 1566 |  | 
|  | 1567 | wo_nlrg: | 
|  | 1568 | movew	#0x8000,L_SCR1(%a6) | 
|  | 1569 | fbeq	int_wrt			|exact answer | 
|  | 1570 | fcmps	#0xc7000080,%fp0 | 
|  | 1571 | | c7000080 in sgl prec = c00e00008000800000000000 in ext prec | 
|  | 1572 | fblt	int_operr		|set operr | 
|  | 1573 | bra	int_inx			|set inexact | 
|  | 1574 |  | 
|  | 1575 | | | 
|  | 1576 | | bi is used to handle a byte integer source specifier | 
|  | 1577 | | | 
|  | 1578 |  | 
|  | 1579 | bi: | 
|  | 1580 | moveql	#1,%d0		|set byte count | 
|  | 1581 |  | 
|  | 1582 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1583 | bne	int_dnrm	|branch if so | 
|  | 1584 |  | 
|  | 1585 | fmovemx ETEMP(%a6),%fp0-%fp0 | 
|  | 1586 | fcmps	#0x42fe0000,%fp0 | 
|  | 1587 | | 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec | 
|  | 1588 | fbge	by_plrg | 
|  | 1589 | fcmps	#0xc3000000,%fp0 | 
|  | 1590 | | c3000000 in sgl prec = c00600008000000000000000 in ext prec | 
|  | 1591 | fble	by_nlrg | 
|  | 1592 |  | 
|  | 1593 | | | 
|  | 1594 | | at this point, the answer is between the largest pos and neg values | 
|  | 1595 | | | 
|  | 1596 | movel	USER_FPCR(%a6),%d1	|use user's rounding mode | 
|  | 1597 | andil	#0x30,%d1 | 
|  | 1598 | fmovel	%d1,%fpcr | 
|  | 1599 | fmoveb	%fp0,L_SCR1(%a6)	|let the 040 perform conversion | 
|  | 1600 | fmovel %fpsr,%d1 | 
|  | 1601 | orl	%d1,USER_FPSR(%a6)	|capture inex2/ainex if set | 
|  | 1602 | bra	int_wrt | 
|  | 1603 |  | 
|  | 1604 | by_plrg: | 
|  | 1605 | moveb	#0x7f,L_SCR1(%a6)		|answer is largest positive int | 
|  | 1606 | fbeq	int_wrt			|exact answer | 
|  | 1607 | fcmps	#0x42ff0000,%fp0 | 
|  | 1608 | | 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec | 
|  | 1609 | fbge	int_operr		|set operr | 
|  | 1610 | bra	int_inx			|set inexact | 
|  | 1611 |  | 
|  | 1612 | by_nlrg: | 
|  | 1613 | moveb	#0x80,L_SCR1(%a6) | 
|  | 1614 | fbeq	int_wrt			|exact answer | 
|  | 1615 | fcmps	#0xc3008000,%fp0 | 
|  | 1616 | | c3008000 in sgl prec = c00600008080000000000000 in ext prec | 
|  | 1617 | fblt	int_operr		|set operr | 
|  | 1618 | bra	int_inx			|set inexact | 
|  | 1619 |  | 
|  | 1620 | | | 
|  | 1621 | | Common integer routines | 
|  | 1622 | | | 
|  | 1623 | | int_drnrm---account for possible nonzero result for round up with positive | 
|  | 1624 | | operand and round down for negative answer.  In the first case (result = 1) | 
|  | 1625 | | byte-width (store in d0) of result must be honored.  In the second case, | 
|  | 1626 | | -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out). | 
|  | 1627 |  | 
|  | 1628 | int_dnrm: | 
|  | 1629 | movel	#0,L_SCR1(%a6)	| initialize result to 0 | 
|  | 1630 | bfextu	FPCR_MODE(%a6){#2:#2},%d1	| d1 is the rounding mode | 
|  | 1631 | cmpb	#2,%d1 | 
|  | 1632 | bmis	int_inx		| if RN or RZ, done | 
|  | 1633 | bnes	int_rp		| if RP, continue below | 
|  | 1634 | tstw	ETEMP(%a6)	| RM: store -1 in L_SCR1 if src is negative | 
|  | 1635 | bpls	int_inx		| otherwise result is 0 | 
|  | 1636 | movel	#-1,L_SCR1(%a6) | 
|  | 1637 | bras	int_inx | 
|  | 1638 | int_rp: | 
|  | 1639 | tstw	ETEMP(%a6)	| RP: store +1 of proper width in L_SCR1 if | 
|  | 1640 | |				; source is greater than 0 | 
|  | 1641 | bmis	int_inx		| otherwise, result is 0 | 
|  | 1642 | lea	L_SCR1(%a6),%a1	| a1 is address of L_SCR1 | 
|  | 1643 | addal	%d0,%a1		| offset by destination width -1 | 
|  | 1644 | subal	#1,%a1 | 
|  | 1645 | bsetb	#0,(%a1)		| set low bit at a1 address | 
|  | 1646 | int_inx: | 
|  | 1647 | oril	#inx2a_mask,USER_FPSR(%a6) | 
|  | 1648 | bras	int_wrt | 
|  | 1649 | int_operr: | 
|  | 1650 | fmovemx %fp0-%fp0,FPTEMP(%a6)	|FPTEMP must contain the extended | 
|  | 1651 | |				;precision source that needs to be | 
|  | 1652 | |				;converted to integer this is required | 
|  | 1653 | |				;if the operr exception is enabled. | 
|  | 1654 | |				;set operr/aiop (no inex2 on int ovfl) | 
|  | 1655 |  | 
|  | 1656 | oril	#opaop_mask,USER_FPSR(%a6) | 
|  | 1657 | |				;fall through to perform int_wrt | 
|  | 1658 | int_wrt: | 
|  | 1659 | movel	EXC_EA(%a6),%a1	|load destination address | 
|  | 1660 | tstl	%a1		|check to see if it is a dest register | 
|  | 1661 | beqs	wrt_dn		|write data register | 
|  | 1662 | lea	L_SCR1(%a6),%a0	|point to supervisor source address | 
|  | 1663 | bsrl	mem_write | 
|  | 1664 | bra	mvouti_end | 
|  | 1665 |  | 
|  | 1666 | wrt_dn: | 
|  | 1667 | movel	%d0,-(%sp)	|d0 currently contains the size to write | 
|  | 1668 | bsrl	get_fline	|get_fline returns Dn in d0 | 
|  | 1669 | andiw	#0x7,%d0		|isolate register | 
|  | 1670 | movel	(%sp)+,%d1	|get size | 
|  | 1671 | cmpil	#4,%d1		|most frequent case | 
|  | 1672 | beqs	sz_long | 
|  | 1673 | cmpil	#2,%d1 | 
|  | 1674 | bnes	sz_con | 
|  | 1675 | orl	#8,%d0		|add 'word' size to register# | 
|  | 1676 | bras	sz_con | 
|  | 1677 | sz_long: | 
|  | 1678 | orl	#0x10,%d0		|add 'long' size to register# | 
|  | 1679 | sz_con: | 
|  | 1680 | movel	%d0,%d1		|reg_dest expects size:reg in d1 | 
|  | 1681 | bsrl	reg_dest	|load proper data register | 
|  | 1682 | bra	mvouti_end | 
|  | 1683 | xp: | 
|  | 1684 | lea	ETEMP(%a6),%a0 | 
|  | 1685 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 1686 | sne	LOCAL_SGN(%a0) | 
|  | 1687 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1688 | bne	xdnrm | 
|  | 1689 | clrl	%d0 | 
|  | 1690 | bras	do_fp		|do normal case | 
|  | 1691 | sgp: | 
|  | 1692 | lea	ETEMP(%a6),%a0 | 
|  | 1693 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 1694 | sne	LOCAL_SGN(%a0) | 
|  | 1695 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1696 | bne	sp_catas	|branch if so | 
|  | 1697 | movew	LOCAL_EX(%a0),%d0 | 
|  | 1698 | lea	sp_bnds,%a1 | 
|  | 1699 | cmpw	(%a1),%d0 | 
|  | 1700 | blt	sp_under | 
|  | 1701 | cmpw	2(%a1),%d0 | 
|  | 1702 | bgt	sp_over | 
|  | 1703 | movel	#1,%d0		|set destination format to single | 
|  | 1704 | bras	do_fp		|do normal case | 
|  | 1705 | dp: | 
|  | 1706 | lea	ETEMP(%a6),%a0 | 
|  | 1707 | bclrb	#sign_bit,LOCAL_EX(%a0) | 
|  | 1708 | sne	LOCAL_SGN(%a0) | 
|  | 1709 |  | 
|  | 1710 | btstb	#7,STAG(%a6)	|check for extended denorm | 
|  | 1711 | bne	dp_catas	|branch if so | 
|  | 1712 |  | 
|  | 1713 | movew	LOCAL_EX(%a0),%d0 | 
|  | 1714 | lea	dp_bnds,%a1 | 
|  | 1715 |  | 
|  | 1716 | cmpw	(%a1),%d0 | 
|  | 1717 | blt	dp_under | 
|  | 1718 | cmpw	2(%a1),%d0 | 
|  | 1719 | bgt	dp_over | 
|  | 1720 |  | 
|  | 1721 | movel	#2,%d0		|set destination format to double | 
|  | 1722 | |				;fall through to do_fp | 
|  | 1723 | | | 
|  | 1724 | do_fp: | 
|  | 1725 | bfextu	FPCR_MODE(%a6){#2:#2},%d1	|rnd mode in d1 | 
|  | 1726 | swap	%d0			|rnd prec in upper word | 
|  | 1727 | addl	%d0,%d1			|d1 has PREC/MODE info | 
|  | 1728 |  | 
|  | 1729 | clrl	%d0			|clear g,r,s | 
|  | 1730 |  | 
|  | 1731 | bsrl	round			|round | 
|  | 1732 |  | 
|  | 1733 | movel	%a0,%a1 | 
|  | 1734 | movel	EXC_EA(%a6),%a0 | 
|  | 1735 |  | 
|  | 1736 | bfextu	CMDREG1B(%a6){#3:#3},%d1	|extract destination format | 
|  | 1737 | |					;at this point only the dest | 
|  | 1738 | |					;formats sgl, dbl, ext are | 
|  | 1739 | |					;possible | 
|  | 1740 | cmpb	#2,%d1 | 
|  | 1741 | bgts	ddbl			|double=5, extended=2, single=1 | 
|  | 1742 | bnes	dsgl | 
|  | 1743 | |					;fall through to dext | 
|  | 1744 | dext: | 
|  | 1745 | bsrl	dest_ext | 
|  | 1746 | bra	mvout_end | 
|  | 1747 | dsgl: | 
|  | 1748 | bsrl	dest_sgl | 
|  | 1749 | bra	mvout_end | 
|  | 1750 | ddbl: | 
|  | 1751 | bsrl	dest_dbl | 
|  | 1752 | bra	mvout_end | 
|  | 1753 |  | 
|  | 1754 | | | 
|  | 1755 | | Handle possible denorm or catastrophic underflow cases here | 
|  | 1756 | | | 
|  | 1757 | xdnrm: | 
|  | 1758 | bsr	set_xop		|initialize WBTEMP | 
|  | 1759 | bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 | 
|  | 1760 |  | 
|  | 1761 | movel	%a0,%a1 | 
|  | 1762 | movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
|  | 1763 | bsrl	dest_ext	|store to memory | 
|  | 1764 | bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
|  | 1765 | bra	mvout_end | 
|  | 1766 |  | 
|  | 1767 | sp_under: | 
|  | 1768 | bsetb	#etemp15_bit,STAG(%a6) | 
|  | 1769 |  | 
|  | 1770 | cmpw	4(%a1),%d0 | 
|  | 1771 | blts	sp_catas	|catastrophic underflow case | 
|  | 1772 |  | 
|  | 1773 | movel	#1,%d0		|load in round precision | 
|  | 1774 | movel	#sgl_thresh,%d1	|load in single denorm threshold | 
|  | 1775 | bsrl	dpspdnrm	|expects d1 to have the proper | 
|  | 1776 | |				;denorm threshold | 
|  | 1777 | bsrl	dest_sgl	|stores value to destination | 
|  | 1778 | bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
|  | 1779 | bra	mvout_end	|exit | 
|  | 1780 |  | 
|  | 1781 | dp_under: | 
|  | 1782 | bsetb	#etemp15_bit,STAG(%a6) | 
|  | 1783 |  | 
|  | 1784 | cmpw	4(%a1),%d0 | 
|  | 1785 | blts	dp_catas	|catastrophic underflow case | 
|  | 1786 |  | 
|  | 1787 | movel	#dbl_thresh,%d1	|load in double precision threshold | 
|  | 1788 | movel	#2,%d0 | 
|  | 1789 | bsrl	dpspdnrm	|expects d1 to have proper | 
|  | 1790 | |				;denorm threshold | 
|  | 1791 | |				;expects d0 to have round precision | 
|  | 1792 | bsrl	dest_dbl	|store value to destination | 
|  | 1793 | bsetb	#unfl_bit,FPSR_EXCEPT(%a6) | 
|  | 1794 | bra	mvout_end	|exit | 
|  | 1795 |  | 
|  | 1796 | | | 
|  | 1797 | | Handle catastrophic underflow cases here | 
|  | 1798 | | | 
|  | 1799 | sp_catas: | 
|  | 1800 | | Temp fix for z bit set in unf_sub | 
|  | 1801 | movel	USER_FPSR(%a6),-(%a7) | 
|  | 1802 |  | 
|  | 1803 | movel	#1,%d0		|set round precision to sgl | 
|  | 1804 |  | 
|  | 1805 | bsrl	unf_sub		|a0 points to result | 
|  | 1806 |  | 
|  | 1807 | movel	(%a7)+,USER_FPSR(%a6) | 
|  | 1808 |  | 
|  | 1809 | movel	#1,%d0 | 
|  | 1810 | subw	%d0,LOCAL_EX(%a0) |account for difference between | 
|  | 1811 | |				;denorm/norm bias | 
|  | 1812 |  | 
|  | 1813 | movel	%a0,%a1		|a1 has the operand input | 
|  | 1814 | movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
|  | 1815 |  | 
|  | 1816 | bsrl	dest_sgl	|store the result | 
|  | 1817 | oril	#unfinx_mask,USER_FPSR(%a6) | 
|  | 1818 | bra	mvout_end | 
|  | 1819 |  | 
|  | 1820 | dp_catas: | 
|  | 1821 | | Temp fix for z bit set in unf_sub | 
|  | 1822 | movel	USER_FPSR(%a6),-(%a7) | 
|  | 1823 |  | 
|  | 1824 | movel	#2,%d0		|set round precision to dbl | 
|  | 1825 | bsrl	unf_sub		|a0 points to result | 
|  | 1826 |  | 
|  | 1827 | movel	(%a7)+,USER_FPSR(%a6) | 
|  | 1828 |  | 
|  | 1829 | movel	#1,%d0 | 
|  | 1830 | subw	%d0,LOCAL_EX(%a0) |account for difference between | 
|  | 1831 | |				;denorm/norm bias | 
|  | 1832 |  | 
|  | 1833 | movel	%a0,%a1		|a1 has the operand input | 
|  | 1834 | movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
|  | 1835 |  | 
|  | 1836 | bsrl	dest_dbl	|store the result | 
|  | 1837 | oril	#unfinx_mask,USER_FPSR(%a6) | 
|  | 1838 | bra	mvout_end | 
|  | 1839 |  | 
|  | 1840 | | | 
|  | 1841 | | Handle catastrophic overflow cases here | 
|  | 1842 | | | 
|  | 1843 | sp_over: | 
|  | 1844 | | Temp fix for z bit set in unf_sub | 
|  | 1845 | movel	USER_FPSR(%a6),-(%a7) | 
|  | 1846 |  | 
|  | 1847 | movel	#1,%d0 | 
|  | 1848 | leal	FP_SCR1(%a6),%a0	|use FP_SCR1 for creating result | 
|  | 1849 | movel	ETEMP_EX(%a6),(%a0) | 
|  | 1850 | movel	ETEMP_HI(%a6),4(%a0) | 
|  | 1851 | movel	ETEMP_LO(%a6),8(%a0) | 
|  | 1852 | bsrl	ovf_res | 
|  | 1853 |  | 
|  | 1854 | movel	(%a7)+,USER_FPSR(%a6) | 
|  | 1855 |  | 
|  | 1856 | movel	%a0,%a1 | 
|  | 1857 | movel	EXC_EA(%a6),%a0 | 
|  | 1858 | bsrl	dest_sgl | 
|  | 1859 | orl	#ovfinx_mask,USER_FPSR(%a6) | 
|  | 1860 | bra	mvout_end | 
|  | 1861 |  | 
|  | 1862 | dp_over: | 
|  | 1863 | | Temp fix for z bit set in ovf_res | 
|  | 1864 | movel	USER_FPSR(%a6),-(%a7) | 
|  | 1865 |  | 
|  | 1866 | movel	#2,%d0 | 
|  | 1867 | leal	FP_SCR1(%a6),%a0	|use FP_SCR1 for creating result | 
|  | 1868 | movel	ETEMP_EX(%a6),(%a0) | 
|  | 1869 | movel	ETEMP_HI(%a6),4(%a0) | 
|  | 1870 | movel	ETEMP_LO(%a6),8(%a0) | 
|  | 1871 | bsrl	ovf_res | 
|  | 1872 |  | 
|  | 1873 | movel	(%a7)+,USER_FPSR(%a6) | 
|  | 1874 |  | 
|  | 1875 | movel	%a0,%a1 | 
|  | 1876 | movel	EXC_EA(%a6),%a0 | 
|  | 1877 | bsrl	dest_dbl | 
|  | 1878 | orl	#ovfinx_mask,USER_FPSR(%a6) | 
|  | 1879 | bra	mvout_end | 
|  | 1880 |  | 
|  | 1881 | | | 
|  | 1882 | |	DPSPDNRM | 
|  | 1883 | | | 
|  | 1884 | | This subroutine takes an extended normalized number and denormalizes | 
|  | 1885 | | it to the given round precision. This subroutine also decrements | 
|  | 1886 | | the input operand's exponent by 1 to account for the fact that | 
|  | 1887 | | dest_sgl or dest_dbl expects a normalized number's bias. | 
|  | 1888 | | | 
|  | 1889 | | Input: a0  points to a normalized number in internal extended format | 
|  | 1890 | |	 d0  is the round precision (=1 for sgl; =2 for dbl) | 
|  | 1891 | |	 d1  is the single precision or double precision | 
|  | 1892 | |	     denorm threshold | 
|  | 1893 | | | 
|  | 1894 | | Output: (In the format for dest_sgl or dest_dbl) | 
|  | 1895 | |	 a0   points to the destination | 
|  | 1896 | |	 a1   points to the operand | 
|  | 1897 | | | 
|  | 1898 | | Exceptions: Reports inexact 2 exception by setting USER_FPSR bits | 
|  | 1899 | | | 
|  | 1900 | dpspdnrm: | 
|  | 1901 | movel	%d0,-(%a7)	|save round precision | 
|  | 1902 | clrl	%d0		|clear initial g,r,s | 
|  | 1903 | bsrl	dnrm_lp		|careful with d0, it's needed by round | 
|  | 1904 |  | 
|  | 1905 | bfextu	FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode | 
|  | 1906 | swap	%d1 | 
|  | 1907 | movew	2(%a7),%d1	|set rounding precision | 
|  | 1908 | swap	%d1		|at this point d1 has PREC/MODE info | 
|  | 1909 | bsrl	round		|round result, sets the inex bit in | 
|  | 1910 | |				;USER_FPSR if needed | 
|  | 1911 |  | 
|  | 1912 | movew	#1,%d0 | 
|  | 1913 | subw	%d0,LOCAL_EX(%a0) |account for difference in denorm | 
|  | 1914 | |				;vs norm bias | 
|  | 1915 |  | 
|  | 1916 | movel	%a0,%a1		|a1 has the operand input | 
|  | 1917 | movel	EXC_EA(%a6),%a0	|a0 has the destination pointer | 
|  | 1918 | addw	#4,%a7		|pop stack | 
|  | 1919 | rts | 
|  | 1920 | | | 
|  | 1921 | | SET_XOP initialized WBTEMP with the value pointed to by a0 | 
|  | 1922 | | input: a0 points to input operand in the internal extended format | 
|  | 1923 | | | 
|  | 1924 | set_xop: | 
|  | 1925 | movel	LOCAL_EX(%a0),WBTEMP_EX(%a6) | 
|  | 1926 | movel	LOCAL_HI(%a0),WBTEMP_HI(%a6) | 
|  | 1927 | movel	LOCAL_LO(%a0),WBTEMP_LO(%a6) | 
|  | 1928 | bfclr	WBTEMP_SGN(%a6){#0:#8} | 
|  | 1929 | beqs	sxop | 
|  | 1930 | bsetb	#sign_bit,WBTEMP_EX(%a6) | 
|  | 1931 | sxop: | 
|  | 1932 | bfclr	STAG(%a6){#5:#4}	|clear wbtm66,wbtm1,wbtm0,sbit | 
|  | 1933 | rts | 
|  | 1934 | | | 
|  | 1935 | |	P_MOVE | 
|  | 1936 | | | 
|  | 1937 | p_movet: | 
|  | 1938 | .long	p_move | 
|  | 1939 | .long	p_movez | 
|  | 1940 | .long	p_movei | 
|  | 1941 | .long	p_moven | 
|  | 1942 | .long	p_move | 
|  | 1943 | p_regd: | 
|  | 1944 | .long	p_dyd0 | 
|  | 1945 | .long	p_dyd1 | 
|  | 1946 | .long	p_dyd2 | 
|  | 1947 | .long	p_dyd3 | 
|  | 1948 | .long	p_dyd4 | 
|  | 1949 | .long	p_dyd5 | 
|  | 1950 | .long	p_dyd6 | 
|  | 1951 | .long	p_dyd7 | 
|  | 1952 |  | 
|  | 1953 | pack_out: | 
|  | 1954 | leal	p_movet,%a0	|load jmp table address | 
|  | 1955 | movew	STAG(%a6),%d0	|get source tag | 
|  | 1956 | bfextu	%d0{#16:#3},%d0	|isolate source bits | 
|  | 1957 | movel	(%a0,%d0.w*4),%a0	|load a0 with routine label for tag | 
|  | 1958 | jmp	(%a0)		|go to the routine | 
|  | 1959 |  | 
|  | 1960 | p_write: | 
|  | 1961 | movel	#0x0c,%d0	|get byte count | 
|  | 1962 | movel	EXC_EA(%a6),%a1	|get the destination address | 
|  | 1963 | bsr	mem_write	|write the user's destination | 
|  | 1964 | moveb	#0,CU_SAVEPC(%a6) |set the cu save pc to all 0's | 
|  | 1965 |  | 
|  | 1966 | | | 
|  | 1967 | | Also note that the dtag must be set to norm here - this is because | 
|  | 1968 | | the 040 uses the dtag to execute the correct microcode. | 
|  | 1969 | | | 
|  | 1970 | bfclr    DTAG(%a6){#0:#3}  |set dtag to norm | 
|  | 1971 |  | 
|  | 1972 | rts | 
|  | 1973 |  | 
|  | 1974 | | Notes on handling of special case (zero, inf, and nan) inputs: | 
|  | 1975 | |	1. Operr is not signalled if the k-factor is greater than 18. | 
|  | 1976 | |	2. Per the manual, status bits are not set. | 
|  | 1977 | | | 
|  | 1978 |  | 
|  | 1979 | p_move: | 
|  | 1980 | movew	CMDREG1B(%a6),%d0 | 
|  | 1981 | btstl	#kfact_bit,%d0	|test for dynamic k-factor | 
|  | 1982 | beqs	statick		|if clear, k-factor is static | 
|  | 1983 | dynamick: | 
|  | 1984 | bfextu	%d0{#25:#3},%d0	|isolate register for dynamic k-factor | 
|  | 1985 | lea	p_regd,%a0 | 
|  | 1986 | movel	%a0@(%d0:l:4),%a0 | 
|  | 1987 | jmp	(%a0) | 
|  | 1988 | statick: | 
|  | 1989 | andiw	#0x007f,%d0	|get k-factor | 
|  | 1990 | bfexts	%d0{#25:#7},%d0	|sign extend d0 for bindec | 
|  | 1991 | leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
|  | 1992 | bsrl	bindec		|perform the convert; data at a6 | 
|  | 1993 | leal	FP_SCR1(%a6),%a0	|load a0 with result address | 
|  | 1994 | bral	p_write | 
|  | 1995 | p_movez: | 
|  | 1996 | leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
|  | 1997 | clrw	2(%a0)		|clear lower word of exp | 
|  | 1998 | clrl	4(%a0)		|load second lword of ZERO | 
|  | 1999 | clrl	8(%a0)		|load third lword of ZERO | 
|  | 2000 | bra	p_write		|go write results | 
|  | 2001 | p_movei: | 
|  | 2002 | fmovel	#0,%FPSR		|clear aiop | 
|  | 2003 | leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
|  | 2004 | clrw	2(%a0)		|clear lower word of exp | 
|  | 2005 | bra	p_write		|go write the result | 
|  | 2006 | p_moven: | 
|  | 2007 | leal	ETEMP(%a6),%a0	|a0 will point to the packed decimal | 
|  | 2008 | clrw	2(%a0)		|clear lower word of exp | 
|  | 2009 | bra	p_write		|go write the result | 
|  | 2010 |  | 
|  | 2011 | | | 
|  | 2012 | | Routines to read the dynamic k-factor from Dn. | 
|  | 2013 | | | 
|  | 2014 | p_dyd0: | 
|  | 2015 | movel	USER_D0(%a6),%d0 | 
|  | 2016 | bras	statick | 
|  | 2017 | p_dyd1: | 
|  | 2018 | movel	USER_D1(%a6),%d0 | 
|  | 2019 | bras	statick | 
|  | 2020 | p_dyd2: | 
|  | 2021 | movel	%d2,%d0 | 
|  | 2022 | bras	statick | 
|  | 2023 | p_dyd3: | 
|  | 2024 | movel	%d3,%d0 | 
|  | 2025 | bras	statick | 
|  | 2026 | p_dyd4: | 
|  | 2027 | movel	%d4,%d0 | 
|  | 2028 | bras	statick | 
|  | 2029 | p_dyd5: | 
|  | 2030 | movel	%d5,%d0 | 
|  | 2031 | bras	statick | 
|  | 2032 | p_dyd6: | 
|  | 2033 | movel	%d6,%d0 | 
|  | 2034 | bra	statick | 
|  | 2035 | p_dyd7: | 
|  | 2036 | movel	%d7,%d0 | 
|  | 2037 | bra	statick | 
|  | 2038 |  | 
|  | 2039 | |end |