| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | | 
|  | 2 | |	util.sa 3.7 7/29/91 | 
|  | 3 | | | 
|  | 4 | |	This file contains routines used by other programs. | 
|  | 5 | | | 
|  | 6 | |	ovf_res: used by overflow to force the correct | 
|  | 7 | |		 result. ovf_r_k, ovf_r_x2, ovf_r_x3 are | 
|  | 8 | |		 derivatives of this routine. | 
|  | 9 | |	get_fline: get user's opcode word | 
|  | 10 | |	g_dfmtou: returns the destination format. | 
|  | 11 | |	g_opcls: returns the opclass of the float instruction. | 
|  | 12 | |	g_rndpr: returns the rounding precision. | 
|  | 13 | |	reg_dest: write byte, word, or long data to Dn | 
|  | 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 | |UTIL	idnt    2,1 | Motorola 040 Floating Point Software Package | 
|  | 23 |  | 
|  | 24 | |section	8 | 
|  | 25 |  | 
|  | 26 | #include "fpsp.h" | 
|  | 27 |  | 
|  | 28 | |xref	mem_read | 
|  | 29 |  | 
|  | 30 | .global	g_dfmtou | 
|  | 31 | .global	g_opcls | 
|  | 32 | .global	g_rndpr | 
|  | 33 | .global	get_fline | 
|  | 34 | .global	reg_dest | 
|  | 35 |  | 
|  | 36 | | | 
|  | 37 | | Final result table for ovf_res. Note that the negative counterparts | 
|  | 38 | | are unnecessary as ovf_res always returns the sign separately from | 
|  | 39 | | the exponent. | 
|  | 40 | |					;+inf | 
|  | 41 | EXT_PINF:	.long	0x7fff0000,0x00000000,0x00000000,0x00000000 | 
|  | 42 | |					;largest +ext | 
|  | 43 | EXT_PLRG:	.long	0x7ffe0000,0xffffffff,0xffffffff,0x00000000 | 
|  | 44 | |					;largest magnitude +sgl in ext | 
|  | 45 | SGL_PLRG:	.long	0x407e0000,0xffffff00,0x00000000,0x00000000 | 
|  | 46 | |					;largest magnitude +dbl in ext | 
|  | 47 | DBL_PLRG:	.long	0x43fe0000,0xffffffff,0xfffff800,0x00000000 | 
|  | 48 | |					;largest -ext | 
|  | 49 |  | 
|  | 50 | tblovfl: | 
|  | 51 | .long	EXT_RN | 
|  | 52 | .long	EXT_RZ | 
|  | 53 | .long	EXT_RM | 
|  | 54 | .long	EXT_RP | 
|  | 55 | .long	SGL_RN | 
|  | 56 | .long	SGL_RZ | 
|  | 57 | .long	SGL_RM | 
|  | 58 | .long	SGL_RP | 
|  | 59 | .long	DBL_RN | 
|  | 60 | .long	DBL_RZ | 
|  | 61 | .long	DBL_RM | 
|  | 62 | .long	DBL_RP | 
|  | 63 | .long	error | 
|  | 64 | .long	error | 
|  | 65 | .long	error | 
|  | 66 | .long	error | 
|  | 67 |  | 
|  | 68 |  | 
|  | 69 | | | 
|  | 70 | |	ovf_r_k --- overflow result calculation | 
|  | 71 | | | 
|  | 72 | | This entry point is used by kernel_ex. | 
|  | 73 | | | 
|  | 74 | | This forces the destination precision to be extended | 
|  | 75 | | | 
|  | 76 | | Input:	operand in ETEMP | 
|  | 77 | | Output:	a result is in ETEMP (internal extended format) | 
|  | 78 | | | 
|  | 79 | .global	ovf_r_k | 
|  | 80 | ovf_r_k: | 
|  | 81 | lea	ETEMP(%a6),%a0	|a0 points to source operand | 
|  | 82 | bclrb	#sign_bit,ETEMP_EX(%a6) | 
|  | 83 | sne	ETEMP_SGN(%a6)	|convert to internal IEEE format | 
|  | 84 |  | 
|  | 85 | | | 
|  | 86 | |	ovf_r_x2 --- overflow result calculation | 
|  | 87 | | | 
|  | 88 | | This entry point used by x_ovfl.  (opclass 0 and 2) | 
|  | 89 | | | 
|  | 90 | | Input		a0  points to an operand in the internal extended format | 
|  | 91 | | Output	a0  points to the result in the internal extended format | 
|  | 92 | | | 
|  | 93 | | This sets the round precision according to the user's FPCR unless the | 
|  | 94 | | instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul, | 
|  | 95 | | fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg. | 
|  | 96 | | If the instruction is fsgldiv of fsglmul, the rounding precision must be | 
|  | 97 | | extended.  If the instruction is not fsgldiv or fsglmul but a force- | 
|  | 98 | | precision instruction, the rounding precision is then set to the force | 
|  | 99 | | precision. | 
|  | 100 |  | 
|  | 101 | .global	ovf_r_x2 | 
|  | 102 | ovf_r_x2: | 
|  | 103 | btstb	#E3,E_BYTE(%a6)		|check for nu exception | 
|  | 104 | beql	ovf_e1_exc		|it is cu exception | 
|  | 105 | ovf_e3_exc: | 
|  | 106 | movew	CMDREG3B(%a6),%d0		|get the command word | 
|  | 107 | andiw	#0x00000060,%d0		|clear all bits except 6 and 5 | 
|  | 108 | cmpil	#0x00000040,%d0 | 
|  | 109 | beql	ovff_sgl		|force precision is single | 
|  | 110 | cmpil	#0x00000060,%d0 | 
|  | 111 | beql	ovff_dbl		|force precision is double | 
|  | 112 | movew	CMDREG3B(%a6),%d0		|get the command word again | 
|  | 113 | andil	#0x7f,%d0			|clear all except operation | 
|  | 114 | cmpil	#0x33,%d0 | 
|  | 115 | beql	ovf_fsgl		|fsglmul or fsgldiv | 
|  | 116 | cmpil	#0x30,%d0 | 
|  | 117 | beql	ovf_fsgl | 
|  | 118 | bra	ovf_fpcr		|instruction is none of the above | 
|  | 119 | |					;use FPCR | 
|  | 120 | ovf_e1_exc: | 
|  | 121 | movew	CMDREG1B(%a6),%d0		|get command word | 
|  | 122 | andil	#0x00000044,%d0		|clear all bits except 6 and 2 | 
|  | 123 | cmpil	#0x00000040,%d0 | 
|  | 124 | beql	ovff_sgl		|the instruction is force single | 
|  | 125 | cmpil	#0x00000044,%d0 | 
|  | 126 | beql	ovff_dbl		|the instruction is force double | 
|  | 127 | movew	CMDREG1B(%a6),%d0		|again get the command word | 
|  | 128 | andil	#0x0000007f,%d0		|clear all except the op code | 
|  | 129 | cmpil	#0x00000027,%d0 | 
|  | 130 | beql	ovf_fsgl		|fsglmul | 
|  | 131 | cmpil	#0x00000024,%d0 | 
|  | 132 | beql	ovf_fsgl		|fsgldiv | 
|  | 133 | bra	ovf_fpcr		|none of the above, use FPCR | 
|  | 134 | | | 
|  | 135 | | | 
|  | 136 | | Inst is either fsgldiv or fsglmul.  Force extended precision. | 
|  | 137 | | | 
|  | 138 | ovf_fsgl: | 
|  | 139 | clrl	%d0 | 
|  | 140 | bra	ovf_res | 
|  | 141 |  | 
|  | 142 | ovff_sgl: | 
|  | 143 | movel	#0x00000001,%d0		|set single | 
|  | 144 | bra	ovf_res | 
|  | 145 | ovff_dbl: | 
|  | 146 | movel	#0x00000002,%d0		|set double | 
|  | 147 | bra	ovf_res | 
|  | 148 | | | 
|  | 149 | | The precision is in the fpcr. | 
|  | 150 | | | 
|  | 151 | ovf_fpcr: | 
|  | 152 | bfextu	FPCR_MODE(%a6){#0:#2},%d0 |set round precision | 
|  | 153 | bra	ovf_res | 
|  | 154 |  | 
|  | 155 | | | 
|  | 156 | | | 
|  | 157 | |	ovf_r_x3 --- overflow result calculation | 
|  | 158 | | | 
|  | 159 | | This entry point used by x_ovfl. (opclass 3 only) | 
|  | 160 | | | 
|  | 161 | | Input		a0  points to an operand in the internal extended format | 
|  | 162 | | Output	a0  points to the result in the internal extended format | 
|  | 163 | | | 
|  | 164 | | This sets the round precision according to the destination size. | 
|  | 165 | | | 
|  | 166 | .global	ovf_r_x3 | 
|  | 167 | ovf_r_x3: | 
|  | 168 | bsr	g_dfmtou	|get dest fmt in d0{1:0} | 
|  | 169 | |				;for fmovout, the destination format | 
|  | 170 | |				;is the rounding precision | 
|  | 171 |  | 
|  | 172 | | | 
|  | 173 | |	ovf_res --- overflow result calculation | 
|  | 174 | | | 
|  | 175 | | Input: | 
|  | 176 | |	a0	points to operand in internal extended format | 
|  | 177 | | Output: | 
|  | 178 | |	a0	points to result in internal extended format | 
|  | 179 | | | 
|  | 180 | .global	ovf_res | 
|  | 181 | ovf_res: | 
|  | 182 | lsll	#2,%d0		|move round precision to d0{3:2} | 
|  | 183 | bfextu	FPCR_MODE(%a6){#2:#2},%d1 |set round mode | 
|  | 184 | orl	%d1,%d0		|index is fmt:mode in d0{3:0} | 
|  | 185 | leal	tblovfl,%a1	|load a1 with table address | 
|  | 186 | movel	%a1@(%d0:l:4),%a1	|use d0 as index to the table | 
|  | 187 | jmp	(%a1)		|go to the correct routine | 
|  | 188 | | | 
|  | 189 | |case DEST_FMT = EXT | 
|  | 190 | | | 
|  | 191 | EXT_RN: | 
|  | 192 | leal	EXT_PINF,%a1	|answer is +/- infinity | 
|  | 193 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 194 | bra	set_sign	|now go set the sign | 
|  | 195 | EXT_RZ: | 
|  | 196 | leal	EXT_PLRG,%a1	|answer is +/- large number | 
|  | 197 | bra	set_sign	|now go set the sign | 
|  | 198 | EXT_RM: | 
|  | 199 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 200 | beqs	e_rm_pos | 
|  | 201 | e_rm_neg: | 
|  | 202 | leal	EXT_PINF,%a1	|answer is negative infinity | 
|  | 203 | orl	#neginf_mask,USER_FPSR(%a6) | 
|  | 204 | bra	end_ovfr | 
|  | 205 | e_rm_pos: | 
|  | 206 | leal	EXT_PLRG,%a1	|answer is large positive number | 
|  | 207 | bra	end_ovfr | 
|  | 208 | EXT_RP: | 
|  | 209 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 210 | beqs	e_rp_pos | 
|  | 211 | e_rp_neg: | 
|  | 212 | leal	EXT_PLRG,%a1	|answer is large negative number | 
|  | 213 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 214 | bra	end_ovfr | 
|  | 215 | e_rp_pos: | 
|  | 216 | leal	EXT_PINF,%a1	|answer is positive infinity | 
|  | 217 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 218 | bra	end_ovfr | 
|  | 219 | | | 
|  | 220 | |case DEST_FMT = DBL | 
|  | 221 | | | 
|  | 222 | DBL_RN: | 
|  | 223 | leal	EXT_PINF,%a1	|answer is +/- infinity | 
|  | 224 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 225 | bra	set_sign | 
|  | 226 | DBL_RZ: | 
|  | 227 | leal	DBL_PLRG,%a1	|answer is +/- large number | 
|  | 228 | bra	set_sign	|now go set the sign | 
|  | 229 | DBL_RM: | 
|  | 230 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 231 | beqs	d_rm_pos | 
|  | 232 | d_rm_neg: | 
|  | 233 | leal	EXT_PINF,%a1	|answer is negative infinity | 
|  | 234 | orl	#neginf_mask,USER_FPSR(%a6) | 
|  | 235 | bra	end_ovfr	|inf is same for all precisions (ext,dbl,sgl) | 
|  | 236 | d_rm_pos: | 
|  | 237 | leal	DBL_PLRG,%a1	|answer is large positive number | 
|  | 238 | bra	end_ovfr | 
|  | 239 | DBL_RP: | 
|  | 240 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 241 | beqs	d_rp_pos | 
|  | 242 | d_rp_neg: | 
|  | 243 | leal	DBL_PLRG,%a1	|answer is large negative number | 
|  | 244 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 245 | bra	end_ovfr | 
|  | 246 | d_rp_pos: | 
|  | 247 | leal	EXT_PINF,%a1	|answer is positive infinity | 
|  | 248 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 249 | bra	end_ovfr | 
|  | 250 | | | 
|  | 251 | |case DEST_FMT = SGL | 
|  | 252 | | | 
|  | 253 | SGL_RN: | 
|  | 254 | leal	EXT_PINF,%a1	|answer is +/-  infinity | 
|  | 255 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 256 | bras	set_sign | 
|  | 257 | SGL_RZ: | 
|  | 258 | leal	SGL_PLRG,%a1	|answer is +/- large number | 
|  | 259 | bras	set_sign | 
|  | 260 | SGL_RM: | 
|  | 261 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 262 | beqs	s_rm_pos | 
|  | 263 | s_rm_neg: | 
|  | 264 | leal	EXT_PINF,%a1	|answer is negative infinity | 
|  | 265 | orl	#neginf_mask,USER_FPSR(%a6) | 
|  | 266 | bras	end_ovfr | 
|  | 267 | s_rm_pos: | 
|  | 268 | leal	SGL_PLRG,%a1	|answer is large positive number | 
|  | 269 | bras	end_ovfr | 
|  | 270 | SGL_RP: | 
|  | 271 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 272 | beqs	s_rp_pos | 
|  | 273 | s_rp_neg: | 
|  | 274 | leal	SGL_PLRG,%a1	|answer is large negative number | 
|  | 275 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 276 | bras	end_ovfr | 
|  | 277 | s_rp_pos: | 
|  | 278 | leal	EXT_PINF,%a1	|answer is positive infinity | 
|  | 279 | bsetb	#inf_bit,FPSR_CC(%a6) | 
|  | 280 | bras	end_ovfr | 
|  | 281 |  | 
|  | 282 | set_sign: | 
|  | 283 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 284 | beqs	end_ovfr | 
|  | 285 | neg_sign: | 
|  | 286 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 287 |  | 
|  | 288 | end_ovfr: | 
|  | 289 | movew	LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign | 
|  | 290 | movel	LOCAL_HI(%a1),LOCAL_HI(%a0) | 
|  | 291 | movel	LOCAL_LO(%a1),LOCAL_LO(%a0) | 
|  | 292 | rts | 
|  | 293 |  | 
|  | 294 |  | 
|  | 295 | | | 
|  | 296 | |	ERROR | 
|  | 297 | | | 
|  | 298 | error: | 
|  | 299 | rts | 
|  | 300 | | | 
|  | 301 | |	get_fline --- get f-line opcode of interrupted instruction | 
|  | 302 | | | 
|  | 303 | |	Returns opcode in the low word of d0. | 
|  | 304 | | | 
|  | 305 | get_fline: | 
|  | 306 | movel	USER_FPIAR(%a6),%a0	|opcode address | 
|  | 307 | movel	#0,-(%a7)	|reserve a word on the stack | 
|  | 308 | leal	2(%a7),%a1	|point to low word of temporary | 
|  | 309 | movel	#2,%d0		|count | 
|  | 310 | bsrl	mem_read | 
|  | 311 | movel	(%a7)+,%d0 | 
|  | 312 | rts | 
|  | 313 | | | 
|  | 314 | |	g_rndpr --- put rounding precision in d0{1:0} | 
|  | 315 | | | 
|  | 316 | |	valid return codes are: | 
|  | 317 | |		00 - extended | 
|  | 318 | |		01 - single | 
|  | 319 | |		10 - double | 
|  | 320 | | | 
|  | 321 | | begin | 
|  | 322 | | get rounding precision (cmdreg3b{6:5}) | 
|  | 323 | | begin | 
|  | 324 | |  case	opclass = 011 (move out) | 
|  | 325 | |	get destination format - this is the also the rounding precision | 
|  | 326 | | | 
|  | 327 | |  case	opclass = 0x0 | 
|  | 328 | |	if E3 | 
|  | 329 | |	    *case RndPr(from cmdreg3b{6:5} = 11  then RND_PREC = DBL | 
|  | 330 | |	    *case RndPr(from cmdreg3b{6:5} = 10  then RND_PREC = SGL | 
|  | 331 | |	     case RndPr(from cmdreg3b{6:5} = 00 | 01 | 
|  | 332 | |		use precision from FPCR{7:6} | 
|  | 333 | |			case 00 then RND_PREC = EXT | 
|  | 334 | |			case 01 then RND_PREC = SGL | 
|  | 335 | |			case 10 then RND_PREC = DBL | 
|  | 336 | |	else E1 | 
|  | 337 | |	     use precision in FPCR{7:6} | 
|  | 338 | |	     case 00 then RND_PREC = EXT | 
|  | 339 | |	     case 01 then RND_PREC = SGL | 
|  | 340 | |	     case 10 then RND_PREC = DBL | 
|  | 341 | | end | 
|  | 342 | | | 
|  | 343 | g_rndpr: | 
|  | 344 | bsr	g_opcls		|get opclass in d0{2:0} | 
|  | 345 | cmpw	#0x0003,%d0	|check for opclass 011 | 
|  | 346 | bnes	op_0x0 | 
|  | 347 |  | 
|  | 348 | | | 
|  | 349 | | For move out instructions (opclass 011) the destination format | 
|  | 350 | | is the same as the rounding precision.  Pass results from g_dfmtou. | 
|  | 351 | | | 
|  | 352 | bsr	g_dfmtou | 
|  | 353 | rts | 
|  | 354 | op_0x0: | 
|  | 355 | btstb	#E3,E_BYTE(%a6) | 
|  | 356 | beql	unf_e1_exc	|branch to e1 underflow | 
|  | 357 | unf_e3_exc: | 
|  | 358 | movel	CMDREG3B(%a6),%d0	|rounding precision in d0{10:9} | 
|  | 359 | bfextu	%d0{#9:#2},%d0	|move the rounding prec bits to d0{1:0} | 
|  | 360 | cmpil	#0x2,%d0 | 
|  | 361 | beql	unff_sgl	|force precision is single | 
|  | 362 | cmpil	#0x3,%d0		|force precision is double | 
|  | 363 | beql	unff_dbl | 
|  | 364 | movew	CMDREG3B(%a6),%d0	|get the command word again | 
|  | 365 | andil	#0x7f,%d0		|clear all except operation | 
|  | 366 | cmpil	#0x33,%d0 | 
|  | 367 | beql	unf_fsgl	|fsglmul or fsgldiv | 
|  | 368 | cmpil	#0x30,%d0 | 
|  | 369 | beql	unf_fsgl	|fsgldiv or fsglmul | 
|  | 370 | bra	unf_fpcr | 
|  | 371 | unf_e1_exc: | 
|  | 372 | movel	CMDREG1B(%a6),%d0	|get 32 bits off the stack, 1st 16 bits | 
|  | 373 | |				;are the command word | 
|  | 374 | andil	#0x00440000,%d0	|clear all bits except bits 6 and 2 | 
|  | 375 | cmpil	#0x00400000,%d0 | 
|  | 376 | beql	unff_sgl	|force single | 
|  | 377 | cmpil	#0x00440000,%d0	|force double | 
|  | 378 | beql	unff_dbl | 
|  | 379 | movel	CMDREG1B(%a6),%d0	|get the command word again | 
|  | 380 | andil	#0x007f0000,%d0	|clear all bits except the operation | 
|  | 381 | cmpil	#0x00270000,%d0 | 
|  | 382 | beql	unf_fsgl	|fsglmul | 
|  | 383 | cmpil	#0x00240000,%d0 | 
|  | 384 | beql	unf_fsgl	|fsgldiv | 
|  | 385 | bra	unf_fpcr | 
|  | 386 |  | 
|  | 387 | | | 
|  | 388 | | Convert to return format.  The values from cmdreg3b and the return | 
|  | 389 | | values are: | 
|  | 390 | |	cmdreg3b	return	     precision | 
|  | 391 | |	--------	------	     --------- | 
|  | 392 | |	  00,01		  0		ext | 
|  | 393 | |	   10		  1		sgl | 
|  | 394 | |	   11		  2		dbl | 
|  | 395 | | Force single | 
|  | 396 | | | 
|  | 397 | unff_sgl: | 
|  | 398 | movel	#1,%d0		|return 1 | 
|  | 399 | rts | 
|  | 400 | | | 
|  | 401 | | Force double | 
|  | 402 | | | 
|  | 403 | unff_dbl: | 
|  | 404 | movel	#2,%d0		|return 2 | 
|  | 405 | rts | 
|  | 406 | | | 
|  | 407 | | Force extended | 
|  | 408 | | | 
|  | 409 | unf_fsgl: | 
|  | 410 | movel	#0,%d0 | 
|  | 411 | rts | 
|  | 412 | | | 
|  | 413 | | Get rounding precision set in FPCR{7:6}. | 
|  | 414 | | | 
|  | 415 | unf_fpcr: | 
|  | 416 | movel	USER_FPCR(%a6),%d0 |rounding precision bits in d0{7:6} | 
|  | 417 | bfextu	%d0{#24:#2},%d0	|move the rounding prec bits to d0{1:0} | 
|  | 418 | rts | 
|  | 419 | | | 
|  | 420 | |	g_opcls --- put opclass in d0{2:0} | 
|  | 421 | | | 
|  | 422 | g_opcls: | 
|  | 423 | btstb	#E3,E_BYTE(%a6) | 
|  | 424 | beqs	opc_1b		|if set, go to cmdreg1b | 
|  | 425 | opc_3b: | 
|  | 426 | clrl	%d0		|if E3, only opclass 0x0 is possible | 
|  | 427 | rts | 
|  | 428 | opc_1b: | 
|  | 429 | movel	CMDREG1B(%a6),%d0 | 
|  | 430 | bfextu	%d0{#0:#3},%d0	|shift opclass bits d0{31:29} to d0{2:0} | 
|  | 431 | rts | 
|  | 432 | | | 
|  | 433 | |	g_dfmtou --- put destination format in d0{1:0} | 
|  | 434 | | | 
|  | 435 | |	If E1, the format is from cmdreg1b{12:10} | 
|  | 436 | |	If E3, the format is extended. | 
|  | 437 | | | 
|  | 438 | |	Dest. Fmt. | 
|  | 439 | |		extended  010 -> 00 | 
|  | 440 | |		single    001 -> 01 | 
|  | 441 | |		double    101 -> 10 | 
|  | 442 | | | 
|  | 443 | g_dfmtou: | 
|  | 444 | btstb	#E3,E_BYTE(%a6) | 
|  | 445 | beqs	op011 | 
|  | 446 | clrl	%d0		|if E1, size is always ext | 
|  | 447 | rts | 
|  | 448 | op011: | 
|  | 449 | movel	CMDREG1B(%a6),%d0 | 
|  | 450 | bfextu	%d0{#3:#3},%d0	|dest fmt from cmdreg1b{12:10} | 
|  | 451 | cmpb	#1,%d0		|check for single | 
|  | 452 | bnes	not_sgl | 
|  | 453 | movel	#1,%d0 | 
|  | 454 | rts | 
|  | 455 | not_sgl: | 
|  | 456 | cmpb	#5,%d0		|check for double | 
|  | 457 | bnes	not_dbl | 
|  | 458 | movel	#2,%d0 | 
|  | 459 | rts | 
|  | 460 | not_dbl: | 
|  | 461 | clrl	%d0		|must be extended | 
|  | 462 | rts | 
|  | 463 |  | 
|  | 464 | | | 
|  | 465 | | | 
|  | 466 | | Final result table for unf_sub. Note that the negative counterparts | 
|  | 467 | | are unnecessary as unf_sub always returns the sign separately from | 
|  | 468 | | the exponent. | 
|  | 469 | |					;+zero | 
|  | 470 | EXT_PZRO:	.long	0x00000000,0x00000000,0x00000000,0x00000000 | 
|  | 471 | |					;+zero | 
|  | 472 | SGL_PZRO:	.long	0x3f810000,0x00000000,0x00000000,0x00000000 | 
|  | 473 | |					;+zero | 
|  | 474 | DBL_PZRO:	.long	0x3c010000,0x00000000,0x00000000,0x00000000 | 
|  | 475 | |					;smallest +ext denorm | 
|  | 476 | EXT_PSML:	.long	0x00000000,0x00000000,0x00000001,0x00000000 | 
|  | 477 | |					;smallest +sgl denorm | 
|  | 478 | SGL_PSML:	.long	0x3f810000,0x00000100,0x00000000,0x00000000 | 
|  | 479 | |					;smallest +dbl denorm | 
|  | 480 | DBL_PSML:	.long	0x3c010000,0x00000000,0x00000800,0x00000000 | 
|  | 481 | | | 
|  | 482 | |	UNF_SUB --- underflow result calculation | 
|  | 483 | | | 
|  | 484 | | Input: | 
|  | 485 | |	d0	contains round precision | 
|  | 486 | |	a0	points to input operand in the internal extended format | 
|  | 487 | | | 
|  | 488 | | Output: | 
|  | 489 | |	a0	points to correct internal extended precision result. | 
|  | 490 | | | 
|  | 491 |  | 
|  | 492 | tblunf: | 
|  | 493 | .long	uEXT_RN | 
|  | 494 | .long	uEXT_RZ | 
|  | 495 | .long	uEXT_RM | 
|  | 496 | .long	uEXT_RP | 
|  | 497 | .long	uSGL_RN | 
|  | 498 | .long	uSGL_RZ | 
|  | 499 | .long	uSGL_RM | 
|  | 500 | .long	uSGL_RP | 
|  | 501 | .long	uDBL_RN | 
|  | 502 | .long	uDBL_RZ | 
|  | 503 | .long	uDBL_RM | 
|  | 504 | .long	uDBL_RP | 
|  | 505 | .long	uDBL_RN | 
|  | 506 | .long	uDBL_RZ | 
|  | 507 | .long	uDBL_RM | 
|  | 508 | .long	uDBL_RP | 
|  | 509 |  | 
|  | 510 | .global	unf_sub | 
|  | 511 | unf_sub: | 
|  | 512 | lsll	#2,%d0		|move round precision to d0{3:2} | 
|  | 513 | bfextu	FPCR_MODE(%a6){#2:#2},%d1 |set round mode | 
|  | 514 | orl	%d1,%d0		|index is fmt:mode in d0{3:0} | 
|  | 515 | leal	tblunf,%a1	|load a1 with table address | 
|  | 516 | movel	%a1@(%d0:l:4),%a1	|use d0 as index to the table | 
|  | 517 | jmp	(%a1)		|go to the correct routine | 
|  | 518 | | | 
|  | 519 | |case DEST_FMT = EXT | 
|  | 520 | | | 
|  | 521 | uEXT_RN: | 
|  | 522 | leal	EXT_PZRO,%a1	|answer is +/- zero | 
|  | 523 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 524 | bra	uset_sign	|now go set the sign | 
|  | 525 | uEXT_RZ: | 
|  | 526 | leal	EXT_PZRO,%a1	|answer is +/- zero | 
|  | 527 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 528 | bra	uset_sign	|now go set the sign | 
|  | 529 | uEXT_RM: | 
|  | 530 | tstb	LOCAL_SGN(%a0)	|if negative underflow | 
|  | 531 | beqs	ue_rm_pos | 
|  | 532 | ue_rm_neg: | 
|  | 533 | leal	EXT_PSML,%a1	|answer is negative smallest denorm | 
|  | 534 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 535 | bra	end_unfr | 
|  | 536 | ue_rm_pos: | 
|  | 537 | leal	EXT_PZRO,%a1	|answer is positive zero | 
|  | 538 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 539 | bra	end_unfr | 
|  | 540 | uEXT_RP: | 
|  | 541 | tstb	LOCAL_SGN(%a0)	|if negative underflow | 
|  | 542 | beqs	ue_rp_pos | 
|  | 543 | ue_rp_neg: | 
|  | 544 | leal	EXT_PZRO,%a1	|answer is negative zero | 
|  | 545 | oril	#negz_mask,USER_FPSR(%a6) | 
|  | 546 | bra	end_unfr | 
|  | 547 | ue_rp_pos: | 
|  | 548 | leal	EXT_PSML,%a1	|answer is positive smallest denorm | 
|  | 549 | bra	end_unfr | 
|  | 550 | | | 
|  | 551 | |case DEST_FMT = DBL | 
|  | 552 | | | 
|  | 553 | uDBL_RN: | 
|  | 554 | leal	DBL_PZRO,%a1	|answer is +/- zero | 
|  | 555 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 556 | bra	uset_sign | 
|  | 557 | uDBL_RZ: | 
|  | 558 | leal	DBL_PZRO,%a1	|answer is +/- zero | 
|  | 559 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 560 | bra	uset_sign	|now go set the sign | 
|  | 561 | uDBL_RM: | 
|  | 562 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 563 | beqs	ud_rm_pos | 
|  | 564 | ud_rm_neg: | 
|  | 565 | leal	DBL_PSML,%a1	|answer is smallest denormalized negative | 
|  | 566 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 567 | bra	end_unfr | 
|  | 568 | ud_rm_pos: | 
|  | 569 | leal	DBL_PZRO,%a1	|answer is positive zero | 
|  | 570 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 571 | bra	end_unfr | 
|  | 572 | uDBL_RP: | 
|  | 573 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 574 | beqs	ud_rp_pos | 
|  | 575 | ud_rp_neg: | 
|  | 576 | leal	DBL_PZRO,%a1	|answer is negative zero | 
|  | 577 | oril	#negz_mask,USER_FPSR(%a6) | 
|  | 578 | bra	end_unfr | 
|  | 579 | ud_rp_pos: | 
|  | 580 | leal	DBL_PSML,%a1	|answer is smallest denormalized negative | 
|  | 581 | bra	end_unfr | 
|  | 582 | | | 
|  | 583 | |case DEST_FMT = SGL | 
|  | 584 | | | 
|  | 585 | uSGL_RN: | 
|  | 586 | leal	SGL_PZRO,%a1	|answer is +/- zero | 
|  | 587 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 588 | bras	uset_sign | 
|  | 589 | uSGL_RZ: | 
|  | 590 | leal	SGL_PZRO,%a1	|answer is +/- zero | 
|  | 591 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 592 | bras	uset_sign | 
|  | 593 | uSGL_RM: | 
|  | 594 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 595 | beqs	us_rm_pos | 
|  | 596 | us_rm_neg: | 
|  | 597 | leal	SGL_PSML,%a1	|answer is smallest denormalized negative | 
|  | 598 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 599 | bras	end_unfr | 
|  | 600 | us_rm_pos: | 
|  | 601 | leal	SGL_PZRO,%a1	|answer is positive zero | 
|  | 602 | bsetb	#z_bit,FPSR_CC(%a6) | 
|  | 603 | bras	end_unfr | 
|  | 604 | uSGL_RP: | 
|  | 605 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 606 | beqs	us_rp_pos | 
|  | 607 | us_rp_neg: | 
|  | 608 | leal	SGL_PZRO,%a1	|answer is negative zero | 
|  | 609 | oril	#negz_mask,USER_FPSR(%a6) | 
|  | 610 | bras	end_unfr | 
|  | 611 | us_rp_pos: | 
|  | 612 | leal	SGL_PSML,%a1	|answer is smallest denormalized positive | 
|  | 613 | bras	end_unfr | 
|  | 614 |  | 
|  | 615 | uset_sign: | 
|  | 616 | tstb	LOCAL_SGN(%a0)	|if negative overflow | 
|  | 617 | beqs	end_unfr | 
|  | 618 | uneg_sign: | 
|  | 619 | bsetb	#neg_bit,FPSR_CC(%a6) | 
|  | 620 |  | 
|  | 621 | end_unfr: | 
|  | 622 | movew	LOCAL_EX(%a1),LOCAL_EX(%a0) |be careful not to overwrite sign | 
|  | 623 | movel	LOCAL_HI(%a1),LOCAL_HI(%a0) | 
|  | 624 | movel	LOCAL_LO(%a1),LOCAL_LO(%a0) | 
|  | 625 | rts | 
|  | 626 | | | 
|  | 627 | |	reg_dest --- write byte, word, or long data to Dn | 
|  | 628 | | | 
|  | 629 | | | 
|  | 630 | | Input: | 
|  | 631 | |	L_SCR1: Data | 
|  | 632 | |	d1:     data size and dest register number formatted as: | 
|  | 633 | | | 
|  | 634 | |	32		5    4     3     2     1     0 | 
|  | 635 | |       ----------------------------------------------- | 
|  | 636 | |       |        0        |    Size   |  Dest Reg #   | | 
|  | 637 | |       ----------------------------------------------- | 
|  | 638 | | | 
|  | 639 | |	Size is: | 
|  | 640 | |		0 - Byte | 
|  | 641 | |		1 - Word | 
|  | 642 | |		2 - Long/Single | 
|  | 643 | | | 
|  | 644 | pregdst: | 
|  | 645 | .long	byte_d0 | 
|  | 646 | .long	byte_d1 | 
|  | 647 | .long	byte_d2 | 
|  | 648 | .long	byte_d3 | 
|  | 649 | .long	byte_d4 | 
|  | 650 | .long	byte_d5 | 
|  | 651 | .long	byte_d6 | 
|  | 652 | .long	byte_d7 | 
|  | 653 | .long	word_d0 | 
|  | 654 | .long	word_d1 | 
|  | 655 | .long	word_d2 | 
|  | 656 | .long	word_d3 | 
|  | 657 | .long	word_d4 | 
|  | 658 | .long	word_d5 | 
|  | 659 | .long	word_d6 | 
|  | 660 | .long	word_d7 | 
|  | 661 | .long	long_d0 | 
|  | 662 | .long	long_d1 | 
|  | 663 | .long	long_d2 | 
|  | 664 | .long	long_d3 | 
|  | 665 | .long	long_d4 | 
|  | 666 | .long	long_d5 | 
|  | 667 | .long	long_d6 | 
|  | 668 | .long	long_d7 | 
|  | 669 |  | 
|  | 670 | reg_dest: | 
|  | 671 | leal	pregdst,%a0 | 
|  | 672 | movel	%a0@(%d1:l:4),%a0 | 
|  | 673 | jmp	(%a0) | 
|  | 674 |  | 
|  | 675 | byte_d0: | 
|  | 676 | moveb	L_SCR1(%a6),USER_D0+3(%a6) | 
|  | 677 | rts | 
|  | 678 | byte_d1: | 
|  | 679 | moveb	L_SCR1(%a6),USER_D1+3(%a6) | 
|  | 680 | rts | 
|  | 681 | byte_d2: | 
|  | 682 | moveb	L_SCR1(%a6),%d2 | 
|  | 683 | rts | 
|  | 684 | byte_d3: | 
|  | 685 | moveb	L_SCR1(%a6),%d3 | 
|  | 686 | rts | 
|  | 687 | byte_d4: | 
|  | 688 | moveb	L_SCR1(%a6),%d4 | 
|  | 689 | rts | 
|  | 690 | byte_d5: | 
|  | 691 | moveb	L_SCR1(%a6),%d5 | 
|  | 692 | rts | 
|  | 693 | byte_d6: | 
|  | 694 | moveb	L_SCR1(%a6),%d6 | 
|  | 695 | rts | 
|  | 696 | byte_d7: | 
|  | 697 | moveb	L_SCR1(%a6),%d7 | 
|  | 698 | rts | 
|  | 699 | word_d0: | 
|  | 700 | movew	L_SCR1(%a6),USER_D0+2(%a6) | 
|  | 701 | rts | 
|  | 702 | word_d1: | 
|  | 703 | movew	L_SCR1(%a6),USER_D1+2(%a6) | 
|  | 704 | rts | 
|  | 705 | word_d2: | 
|  | 706 | movew	L_SCR1(%a6),%d2 | 
|  | 707 | rts | 
|  | 708 | word_d3: | 
|  | 709 | movew	L_SCR1(%a6),%d3 | 
|  | 710 | rts | 
|  | 711 | word_d4: | 
|  | 712 | movew	L_SCR1(%a6),%d4 | 
|  | 713 | rts | 
|  | 714 | word_d5: | 
|  | 715 | movew	L_SCR1(%a6),%d5 | 
|  | 716 | rts | 
|  | 717 | word_d6: | 
|  | 718 | movew	L_SCR1(%a6),%d6 | 
|  | 719 | rts | 
|  | 720 | word_d7: | 
|  | 721 | movew	L_SCR1(%a6),%d7 | 
|  | 722 | rts | 
|  | 723 | long_d0: | 
|  | 724 | movel	L_SCR1(%a6),USER_D0(%a6) | 
|  | 725 | rts | 
|  | 726 | long_d1: | 
|  | 727 | movel	L_SCR1(%a6),USER_D1(%a6) | 
|  | 728 | rts | 
|  | 729 | long_d2: | 
|  | 730 | movel	L_SCR1(%a6),%d2 | 
|  | 731 | rts | 
|  | 732 | long_d3: | 
|  | 733 | movel	L_SCR1(%a6),%d3 | 
|  | 734 | rts | 
|  | 735 | long_d4: | 
|  | 736 | movel	L_SCR1(%a6),%d4 | 
|  | 737 | rts | 
|  | 738 | long_d5: | 
|  | 739 | movel	L_SCR1(%a6),%d5 | 
|  | 740 | rts | 
|  | 741 | long_d6: | 
|  | 742 | movel	L_SCR1(%a6),%d6 | 
|  | 743 | rts | 
|  | 744 | long_d7: | 
|  | 745 | movel	L_SCR1(%a6),%d7 | 
|  | 746 | rts | 
|  | 747 | |end |