| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | | 
|  | 2 | |	scale.sa 3.3 7/30/91 | 
|  | 3 | | | 
|  | 4 | |	The entry point sSCALE computes the destination operand | 
|  | 5 | |	scaled by the source operand.  If the absolute value of | 
|  | 6 | |	the source operand is (>= 2^14) an overflow or underflow | 
|  | 7 | |	is returned. | 
|  | 8 | | | 
|  | 9 | |	The entry point sscale is called from do_func to emulate | 
|  | 10 | |	the fscale unimplemented instruction. | 
|  | 11 | | | 
|  | 12 | |	Input: Double-extended destination operand in FPTEMP, | 
|  | 13 | |		double-extended source operand in ETEMP. | 
|  | 14 | | | 
|  | 15 | |	Output: The function returns scale(X,Y) to fp0. | 
|  | 16 | | | 
|  | 17 | |	Modifies: fp0. | 
|  | 18 | | | 
|  | 19 | |	Algorithm: | 
|  | 20 | | | 
|  | 21 | |		Copyright (C) Motorola, Inc. 1990 | 
|  | 22 | |			All Rights Reserved | 
|  | 23 | | | 
| Matt Waddel | e00d82d | 2006-02-11 17:55:48 -0800 | [diff] [blame] | 24 | |       For details on the license for this file, please see the | 
|  | 25 | |       file, README, in this same directory. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 |  | 
|  | 27 | |SCALE    idnt    2,1 | Motorola 040 Floating Point Software Package | 
|  | 28 |  | 
|  | 29 | |section	8 | 
|  | 30 |  | 
|  | 31 | #include "fpsp.h" | 
|  | 32 |  | 
|  | 33 | |xref	t_ovfl2 | 
|  | 34 | |xref	t_unfl | 
|  | 35 | |xref	round | 
|  | 36 | |xref	t_resdnrm | 
|  | 37 |  | 
|  | 38 | SRC_BNDS: .short	0x3fff,0x400c | 
|  | 39 |  | 
|  | 40 | | | 
|  | 41 | | This entry point is used by the unimplemented instruction exception | 
|  | 42 | | handler. | 
|  | 43 | | | 
|  | 44 | | | 
|  | 45 | | | 
|  | 46 | |	FSCALE | 
|  | 47 | | | 
|  | 48 | .global	sscale | 
|  | 49 | sscale: | 
|  | 50 | fmovel		#0,%fpcr		|clr user enabled exc | 
|  | 51 | clrl		%d1 | 
|  | 52 | movew		FPTEMP(%a6),%d1	|get dest exponent | 
|  | 53 | smi		L_SCR1(%a6)	|use L_SCR1 to hold sign | 
|  | 54 | andil		#0x7fff,%d1	|strip sign | 
|  | 55 | movew		ETEMP(%a6),%d0	|check src bounds | 
|  | 56 | andiw		#0x7fff,%d0	|clr sign bit | 
|  | 57 | cmp2w		SRC_BNDS,%d0 | 
|  | 58 | bccs		src_in | 
|  | 59 | cmpiw		#0x400c,%d0	|test for too large | 
|  | 60 | bge		src_out | 
|  | 61 | | | 
|  | 62 | | The source input is below 1, so we check for denormalized numbers | 
|  | 63 | | and set unfl. | 
|  | 64 | | | 
|  | 65 | src_small: | 
|  | 66 | moveb		DTAG(%a6),%d0 | 
|  | 67 | andib		#0xe0,%d0 | 
|  | 68 | tstb		%d0 | 
|  | 69 | beqs		no_denorm | 
|  | 70 | st		STORE_FLG(%a6)	|dest already contains result | 
|  | 71 | orl		#unfl_mask,USER_FPSR(%a6) |set UNFL | 
|  | 72 | den_done: | 
|  | 73 | leal		FPTEMP(%a6),%a0 | 
|  | 74 | bra		t_resdnrm | 
|  | 75 | no_denorm: | 
|  | 76 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 77 | fmovex		FPTEMP(%a6),%fp0	|simply return dest | 
|  | 78 | rts | 
|  | 79 |  | 
|  | 80 |  | 
|  | 81 | | | 
|  | 82 | | Source is within 2^14 range.  To perform the int operation, | 
|  | 83 | | move it to d0. | 
|  | 84 | | | 
|  | 85 | src_in: | 
|  | 86 | fmovex		ETEMP(%a6),%fp0	|move in src for int | 
|  | 87 | fmovel		#rz_mode,%fpcr	|force rz for src conversion | 
|  | 88 | fmovel		%fp0,%d0		|int src to d0 | 
|  | 89 | fmovel		#0,%FPSR		|clr status from above | 
|  | 90 | tstw		ETEMP(%a6)	|check src sign | 
|  | 91 | blt		src_neg | 
|  | 92 | | | 
|  | 93 | | Source is positive.  Add the src to the dest exponent. | 
|  | 94 | | The result can be denormalized, if src = 0, or overflow, | 
|  | 95 | | if the result of the add sets a bit in the upper word. | 
|  | 96 | | | 
|  | 97 | src_pos: | 
|  | 98 | tstw		%d1		|check for denorm | 
|  | 99 | beq		dst_dnrm | 
|  | 100 | addl		%d0,%d1		|add src to dest exp | 
|  | 101 | beqs		denorm		|if zero, result is denorm | 
|  | 102 | cmpil		#0x7fff,%d1	|test for overflow | 
|  | 103 | bges		ovfl | 
|  | 104 | tstb		L_SCR1(%a6) | 
|  | 105 | beqs		spos_pos | 
|  | 106 | orw		#0x8000,%d1 | 
|  | 107 | spos_pos: | 
|  | 108 | movew		%d1,FPTEMP(%a6)	|result in FPTEMP | 
|  | 109 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 110 | fmovex		FPTEMP(%a6),%fp0	|write result to fp0 | 
|  | 111 | rts | 
|  | 112 | ovfl: | 
|  | 113 | tstb		L_SCR1(%a6) | 
|  | 114 | beqs		sovl_pos | 
|  | 115 | orw		#0x8000,%d1 | 
|  | 116 | sovl_pos: | 
|  | 117 | movew		FPTEMP(%a6),ETEMP(%a6)	|result in ETEMP | 
|  | 118 | movel		FPTEMP_HI(%a6),ETEMP_HI(%a6) | 
|  | 119 | movel		FPTEMP_LO(%a6),ETEMP_LO(%a6) | 
|  | 120 | bra		t_ovfl2 | 
|  | 121 |  | 
|  | 122 | denorm: | 
|  | 123 | tstb		L_SCR1(%a6) | 
|  | 124 | beqs		den_pos | 
|  | 125 | orw		#0x8000,%d1 | 
|  | 126 | den_pos: | 
|  | 127 | tstl		FPTEMP_HI(%a6)	|check j bit | 
|  | 128 | blts		nden_exit	|if set, not denorm | 
|  | 129 | movew		%d1,ETEMP(%a6)	|input expected in ETEMP | 
|  | 130 | movel		FPTEMP_HI(%a6),ETEMP_HI(%a6) | 
|  | 131 | movel		FPTEMP_LO(%a6),ETEMP_LO(%a6) | 
|  | 132 | orl		#unfl_bit,USER_FPSR(%a6)	|set unfl | 
|  | 133 | leal		ETEMP(%a6),%a0 | 
|  | 134 | bra		t_resdnrm | 
|  | 135 | nden_exit: | 
|  | 136 | movew		%d1,FPTEMP(%a6)	|result in FPTEMP | 
|  | 137 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 138 | fmovex		FPTEMP(%a6),%fp0	|write result to fp0 | 
|  | 139 | rts | 
|  | 140 |  | 
|  | 141 | | | 
|  | 142 | | Source is negative.  Add the src to the dest exponent. | 
|  | 143 | | (The result exponent will be reduced).  The result can be | 
|  | 144 | | denormalized. | 
|  | 145 | | | 
|  | 146 | src_neg: | 
|  | 147 | addl		%d0,%d1		|add src to dest | 
|  | 148 | beqs		denorm		|if zero, result is denorm | 
|  | 149 | blts		fix_dnrm	|if negative, result is | 
|  | 150 | |					;needing denormalization | 
|  | 151 | tstb		L_SCR1(%a6) | 
|  | 152 | beqs		sneg_pos | 
|  | 153 | orw		#0x8000,%d1 | 
|  | 154 | sneg_pos: | 
|  | 155 | movew		%d1,FPTEMP(%a6)	|result in FPTEMP | 
|  | 156 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 157 | fmovex		FPTEMP(%a6),%fp0	|write result to fp0 | 
|  | 158 | rts | 
|  | 159 |  | 
|  | 160 |  | 
|  | 161 | | | 
|  | 162 | | The result exponent is below denorm value.  Test for catastrophic | 
|  | 163 | | underflow and force zero if true.  If not, try to shift the | 
|  | 164 | | mantissa right until a zero exponent exists. | 
|  | 165 | | | 
|  | 166 | fix_dnrm: | 
|  | 167 | cmpiw		#0xffc0,%d1	|lower bound for normalization | 
|  | 168 | blt		fix_unfl	|if lower, catastrophic unfl | 
|  | 169 | movew		%d1,%d0		|use d0 for exp | 
|  | 170 | movel		%d2,-(%a7)	|free d2 for norm | 
|  | 171 | movel		FPTEMP_HI(%a6),%d1 | 
|  | 172 | movel		FPTEMP_LO(%a6),%d2 | 
|  | 173 | clrl		L_SCR2(%a6) | 
|  | 174 | fix_loop: | 
|  | 175 | addw		#1,%d0		|drive d0 to 0 | 
|  | 176 | lsrl		#1,%d1		|while shifting the | 
|  | 177 | roxrl		#1,%d2		|mantissa to the right | 
|  | 178 | bccs		no_carry | 
|  | 179 | st		L_SCR2(%a6)	|use L_SCR2 to capture inex | 
|  | 180 | no_carry: | 
|  | 181 | tstw		%d0		|it is finished when | 
|  | 182 | blts		fix_loop	|d0 is zero or the mantissa | 
|  | 183 | tstb		L_SCR2(%a6) | 
|  | 184 | beqs		tst_zero | 
|  | 185 | orl		#unfl_inx_mask,USER_FPSR(%a6) | 
|  | 186 | |					;set unfl, aunfl, ainex | 
|  | 187 | | | 
|  | 188 | | Test for zero. If zero, simply use fmove to return +/- zero | 
|  | 189 | | to the fpu. | 
|  | 190 | | | 
|  | 191 | tst_zero: | 
|  | 192 | clrw		FPTEMP_EX(%a6) | 
|  | 193 | tstb		L_SCR1(%a6)	|test for sign | 
|  | 194 | beqs		tst_con | 
|  | 195 | orw		#0x8000,FPTEMP_EX(%a6) |set sign bit | 
|  | 196 | tst_con: | 
|  | 197 | movel		%d1,FPTEMP_HI(%a6) | 
|  | 198 | movel		%d2,FPTEMP_LO(%a6) | 
|  | 199 | movel		(%a7)+,%d2 | 
|  | 200 | tstl		%d1 | 
|  | 201 | bnes		not_zero | 
|  | 202 | tstl		FPTEMP_LO(%a6) | 
|  | 203 | bnes		not_zero | 
|  | 204 | | | 
|  | 205 | | Result is zero.  Check for rounding mode to set lsb.  If the | 
|  | 206 | | mode is rp, and the zero is positive, return smallest denorm. | 
|  | 207 | | If the mode is rm, and the zero is negative, return smallest | 
|  | 208 | | negative denorm. | 
|  | 209 | | | 
|  | 210 | btstb		#5,FPCR_MODE(%a6) |test if rm or rp | 
|  | 211 | beqs		no_dir | 
|  | 212 | btstb		#4,FPCR_MODE(%a6) |check which one | 
|  | 213 | beqs		zer_rm | 
|  | 214 | zer_rp: | 
|  | 215 | tstb		L_SCR1(%a6)	|check sign | 
|  | 216 | bnes		no_dir		|if set, neg op, no inc | 
|  | 217 | movel		#1,FPTEMP_LO(%a6) |set lsb | 
|  | 218 | bras		sm_dnrm | 
|  | 219 | zer_rm: | 
|  | 220 | tstb		L_SCR1(%a6)	|check sign | 
|  | 221 | beqs		no_dir		|if clr, neg op, no inc | 
|  | 222 | movel		#1,FPTEMP_LO(%a6) |set lsb | 
|  | 223 | orl		#neg_mask,USER_FPSR(%a6) |set N | 
|  | 224 | bras		sm_dnrm | 
|  | 225 | no_dir: | 
|  | 226 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 227 | fmovex		FPTEMP(%a6),%fp0	|use fmove to set cc's | 
|  | 228 | rts | 
|  | 229 |  | 
|  | 230 | | | 
|  | 231 | | The rounding mode changed the zero to a smallest denorm. Call | 
|  | 232 | | t_resdnrm with exceptional operand in ETEMP. | 
|  | 233 | | | 
|  | 234 | sm_dnrm: | 
|  | 235 | movel		FPTEMP_EX(%a6),ETEMP_EX(%a6) | 
|  | 236 | movel		FPTEMP_HI(%a6),ETEMP_HI(%a6) | 
|  | 237 | movel		FPTEMP_LO(%a6),ETEMP_LO(%a6) | 
|  | 238 | leal		ETEMP(%a6),%a0 | 
|  | 239 | bra		t_resdnrm | 
|  | 240 |  | 
|  | 241 | | | 
|  | 242 | | Result is still denormalized. | 
|  | 243 | | | 
|  | 244 | not_zero: | 
|  | 245 | orl		#unfl_mask,USER_FPSR(%a6) |set unfl | 
|  | 246 | tstb		L_SCR1(%a6)	|check for sign | 
|  | 247 | beqs		fix_exit | 
|  | 248 | orl		#neg_mask,USER_FPSR(%a6) |set N | 
|  | 249 | fix_exit: | 
|  | 250 | bras		sm_dnrm | 
|  | 251 |  | 
|  | 252 |  | 
|  | 253 | | | 
|  | 254 | | The result has underflowed to zero. Return zero and set | 
|  | 255 | | unfl, aunfl, and ainex. | 
|  | 256 | | | 
|  | 257 | fix_unfl: | 
|  | 258 | orl		#unfl_inx_mask,USER_FPSR(%a6) | 
|  | 259 | btstb		#5,FPCR_MODE(%a6) |test if rm or rp | 
|  | 260 | beqs		no_dir2 | 
|  | 261 | btstb		#4,FPCR_MODE(%a6) |check which one | 
|  | 262 | beqs		zer_rm2 | 
|  | 263 | zer_rp2: | 
|  | 264 | tstb		L_SCR1(%a6)	|check sign | 
|  | 265 | bnes		no_dir2		|if set, neg op, no inc | 
|  | 266 | clrl		FPTEMP_EX(%a6) | 
|  | 267 | clrl		FPTEMP_HI(%a6) | 
|  | 268 | movel		#1,FPTEMP_LO(%a6) |set lsb | 
|  | 269 | bras		sm_dnrm		|return smallest denorm | 
|  | 270 | zer_rm2: | 
|  | 271 | tstb		L_SCR1(%a6)	|check sign | 
|  | 272 | beqs		no_dir2		|if clr, neg op, no inc | 
|  | 273 | movew		#0x8000,FPTEMP_EX(%a6) | 
|  | 274 | clrl		FPTEMP_HI(%a6) | 
|  | 275 | movel		#1,FPTEMP_LO(%a6) |set lsb | 
|  | 276 | orl		#neg_mask,USER_FPSR(%a6) |set N | 
|  | 277 | bra		sm_dnrm		|return smallest denorm | 
|  | 278 |  | 
|  | 279 | no_dir2: | 
|  | 280 | tstb		L_SCR1(%a6) | 
|  | 281 | bges		pos_zero | 
|  | 282 | neg_zero: | 
|  | 283 | clrl		FP_SCR1(%a6)	|clear the exceptional operand | 
|  | 284 | clrl		FP_SCR1+4(%a6)	|for gen_except. | 
|  | 285 | clrl		FP_SCR1+8(%a6) | 
|  | 286 | fmoves		#0x80000000,%fp0 | 
|  | 287 | rts | 
|  | 288 | pos_zero: | 
|  | 289 | clrl		FP_SCR1(%a6)	|clear the exceptional operand | 
|  | 290 | clrl		FP_SCR1+4(%a6)	|for gen_except. | 
|  | 291 | clrl		FP_SCR1+8(%a6) | 
|  | 292 | fmoves		#0x00000000,%fp0 | 
|  | 293 | rts | 
|  | 294 |  | 
|  | 295 | | | 
|  | 296 | | The destination is a denormalized number.  It must be handled | 
|  | 297 | | by first shifting the bits in the mantissa until it is normalized, | 
|  | 298 | | then adding the remainder of the source to the exponent. | 
|  | 299 | | | 
|  | 300 | dst_dnrm: | 
|  | 301 | moveml		%d2/%d3,-(%a7) | 
|  | 302 | movew		FPTEMP_EX(%a6),%d1 | 
|  | 303 | movel		FPTEMP_HI(%a6),%d2 | 
|  | 304 | movel		FPTEMP_LO(%a6),%d3 | 
|  | 305 | dst_loop: | 
|  | 306 | tstl		%d2		|test for normalized result | 
|  | 307 | blts		dst_norm	|exit loop if so | 
|  | 308 | tstl		%d0		|otherwise, test shift count | 
|  | 309 | beqs		dst_fin		|if zero, shifting is done | 
|  | 310 | subil		#1,%d0		|dec src | 
|  | 311 | lsll		#1,%d3 | 
|  | 312 | roxll		#1,%d2 | 
|  | 313 | bras		dst_loop | 
|  | 314 | | | 
|  | 315 | | Destination became normalized.  Simply add the remaining | 
|  | 316 | | portion of the src to the exponent. | 
|  | 317 | | | 
|  | 318 | dst_norm: | 
|  | 319 | addw		%d0,%d1		|dst is normalized; add src | 
|  | 320 | tstb		L_SCR1(%a6) | 
|  | 321 | beqs		dnrm_pos | 
|  | 322 | orl		#0x8000,%d1 | 
|  | 323 | dnrm_pos: | 
|  | 324 | movemw		%d1,FPTEMP_EX(%a6) | 
|  | 325 | moveml		%d2,FPTEMP_HI(%a6) | 
|  | 326 | moveml		%d3,FPTEMP_LO(%a6) | 
|  | 327 | fmovel		USER_FPCR(%a6),%FPCR | 
|  | 328 | fmovex		FPTEMP(%a6),%fp0 | 
|  | 329 | moveml		(%a7)+,%d2/%d3 | 
|  | 330 | rts | 
|  | 331 |  | 
|  | 332 | | | 
|  | 333 | | Destination remained denormalized.  Call t_excdnrm with | 
|  | 334 | | exceptional operand in ETEMP. | 
|  | 335 | | | 
|  | 336 | dst_fin: | 
|  | 337 | tstb		L_SCR1(%a6)	|check for sign | 
|  | 338 | beqs		dst_exit | 
|  | 339 | orl		#neg_mask,USER_FPSR(%a6) |set N | 
|  | 340 | orl		#0x8000,%d1 | 
|  | 341 | dst_exit: | 
|  | 342 | movemw		%d1,ETEMP_EX(%a6) | 
|  | 343 | moveml		%d2,ETEMP_HI(%a6) | 
|  | 344 | moveml		%d3,ETEMP_LO(%a6) | 
|  | 345 | orl		#unfl_mask,USER_FPSR(%a6) |set unfl | 
|  | 346 | moveml		(%a7)+,%d2/%d3 | 
|  | 347 | leal		ETEMP(%a6),%a0 | 
|  | 348 | bra		t_resdnrm | 
|  | 349 |  | 
|  | 350 | | | 
|  | 351 | | Source is outside of 2^14 range.  Test the sign and branch | 
|  | 352 | | to the appropriate exception handler. | 
|  | 353 | | | 
|  | 354 | src_out: | 
|  | 355 | tstb		L_SCR1(%a6) | 
|  | 356 | beqs		scro_pos | 
|  | 357 | orl		#0x8000,%d1 | 
|  | 358 | scro_pos: | 
|  | 359 | movel		FPTEMP_HI(%a6),ETEMP_HI(%a6) | 
|  | 360 | movel		FPTEMP_LO(%a6),ETEMP_LO(%a6) | 
|  | 361 | tstw		ETEMP(%a6) | 
|  | 362 | blts		res_neg | 
|  | 363 | res_pos: | 
|  | 364 | movew		%d1,ETEMP(%a6)	|result in ETEMP | 
|  | 365 | bra		t_ovfl2 | 
|  | 366 | res_neg: | 
|  | 367 | movew		%d1,ETEMP(%a6)	|result in ETEMP | 
|  | 368 | leal		ETEMP(%a6),%a0 | 
|  | 369 | bra		t_unfl | 
|  | 370 | |end |