1 * $NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 cgd Exp $ 2 3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 4 * M68000 Hi-Performance Microprocessor Division 5 * M68040 Software Package 6 * 7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 8 * All rights reserved. 9 * 10 * THE SOFTWARE is provided on an "AS IS" basis and without warranty. 11 * To the maximum extent permitted by applicable law, 12 * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 13 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 14 * PARTICULAR PURPOSE and any warranty against infringement with 15 * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 16 * and any accompanying written materials. 17 * 18 * To the maximum extent permitted by applicable law, 19 * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 20 * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 21 * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 22 * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 23 * SOFTWARE. Motorola assumes no responsibility for the maintenance 24 * and support of the SOFTWARE. 25 * 26 * You are hereby granted a copyright license to use, modify, and 27 * distribute the SOFTWARE so long as this entire notice is retained 28 * without alteration in any modified and/or redistributed versions, 29 * and that such modified versions are clearly identified as such. 30 * No licenses are granted by implication, estoppel or otherwise 31 * under any patents or trademarks of Motorola, Inc. 32 33 * 34 * scale.sa 3.3 7/30/91 35 * 36 * The entry point sSCALE computes the destination operand 37 * scaled by the source operand. If the absoulute value of 38 * the source operand is (>= 2^14) an overflow or underflow 39 * is returned. 40 * 41 * The entry point sscale is called from do_func to emulate 42 * the fscale unimplemented instruction. 43 * 44 * Input: Double-extended destination operand in FPTEMP, 45 * double-extended source operand in ETEMP. 46 * 47 * Output: The function returns scale(X,Y) to fp0. 48 * 49 * Modifies: fp0. 50 * 51 * Algorithm: 52 * 53 54 SCALE IDNT 2,1 Motorola 040 Floating Point Software Package 55 56 section 8 57 58 include fpsp.h 59 60 xref t_ovfl2 61 xref t_unfl 62 xref round 63 xref t_resdnrm 64 65 SRC_BNDS dc.w $3fff,$400c 66 67 * 68 * This entry point is used by the unimplemented instruction exception 69 * handler. 70 * 71 * 72 * 73 * FSCALE 74 * 75 xdef sscale 76 sscale: 77 fmove.l #0,fpcr ;clr user enabled exc 78 clr.l d1 79 move.w FPTEMP(a6),d1 ;get dest exponent 80 smi L_SCR1(a6) ;use L_SCR1 to hold sign 81 andi.l #$7fff,d1 ;strip sign 82 move.w ETEMP(a6),d0 ;check src bounds 83 andi.w #$7fff,d0 ;clr sign bit 84 cmp2.w SRC_BNDS,d0 85 bcc.b src_in 86 cmpi.w #$400c,d0 ;test for too large 87 bge.w src_out 88 * 89 * The source input is below 1, so we check for denormalized numbers 90 * and set unfl. 91 * 92 src_small: 93 move.b DTAG(a6),d0 94 andi.b #$e0,d0 95 tst.b d0 96 beq.b no_denorm 97 st STORE_FLG(a6) ;dest already contains result 98 or.l #unfl_mask,USER_FPSR(a6) ;set UNFL 99 den_done: 100 lea.l FPTEMP(a6),a0 101 bra t_resdnrm 102 no_denorm: 103 fmove.l USER_FPCR(a6),FPCR 104 fmove.x FPTEMP(a6),fp0 ;simply return dest 105 rts 106 107 108 * 109 * Source is within 2^14 range. To perform the int operation, 110 * move it to d0. 111 * 112 src_in: 113 fmove.x ETEMP(a6),fp0 ;move in src for int 114 fmove.l #rz_mode,fpcr ;force rz for src conversion 115 fmove.l fp0,d0 ;int src to d0 116 fmove.l #0,FPSR ;clr status from above 117 tst.w ETEMP(a6) ;check src sign 118 blt.w src_neg 119 * 120 * Source is positive. Add the src to the dest exponent. 121 * The result can be denormalized, if src = 0, or overflow, 122 * if the result of the add sets a bit in the upper word. 123 * 124 src_pos: 125 tst.w d1 ;check for denorm 126 beq.w dst_dnrm 127 add.l d0,d1 ;add src to dest exp 128 beq.b denorm ;if zero, result is denorm 129 cmpi.l #$7fff,d1 ;test for overflow 130 bge.b ovfl 131 tst.b L_SCR1(a6) 132 beq.b spos_pos 133 or.w #$8000,d1 134 spos_pos: 135 move.w d1,FPTEMP(a6) ;result in FPTEMP 136 fmove.l USER_FPCR(a6),FPCR 137 fmove.x FPTEMP(a6),fp0 ;write result to fp0 138 rts 139 ovfl: 140 tst.b L_SCR1(a6) 141 beq.b sovl_pos 142 or.w #$8000,d1 143 sovl_pos: 144 move.w FPTEMP(a6),ETEMP(a6) ;result in ETEMP 145 move.l FPTEMP_HI(a6),ETEMP_HI(a6) 146 move.l FPTEMP_LO(a6),ETEMP_LO(a6) 147 bra t_ovfl2 148 149 denorm: 150 tst.b L_SCR1(a6) 151 beq.b den_pos 152 or.w #$8000,d1 153 den_pos: 154 tst.l FPTEMP_HI(a6) ;check j bit 155 blt.b nden_exit ;if set, not denorm 156 move.w d1,ETEMP(a6) ;input expected in ETEMP 157 move.l FPTEMP_HI(a6),ETEMP_HI(a6) 158 move.l FPTEMP_LO(a6),ETEMP_LO(a6) 159 or.l #unfl_bit,USER_FPSR(a6) ;set unfl 160 lea.l ETEMP(a6),a0 161 bra t_resdnrm 162 nden_exit: 163 move.w d1,FPTEMP(a6) ;result in FPTEMP 164 fmove.l USER_FPCR(a6),FPCR 165 fmove.x FPTEMP(a6),fp0 ;write result to fp0 166 rts 167 168 * 169 * Source is negative. Add the src to the dest exponent. 170 * (The result exponent will be reduced). The result can be 171 * denormalized. 172 * 173 src_neg: 174 add.l d0,d1 ;add src to dest 175 beq.b denorm ;if zero, result is denorm 176 blt.b fix_dnrm ;if negative, result is 177 * ;needing denormalization 178 tst.b L_SCR1(a6) 179 beq.b sneg_pos 180 or.w #$8000,d1 181 sneg_pos: 182 move.w d1,FPTEMP(a6) ;result in FPTEMP 183 fmove.l USER_FPCR(a6),FPCR 184 fmove.x FPTEMP(a6),fp0 ;write result to fp0 185 rts 186 187 188 * 189 * The result exponent is below denorm value. Test for catastrophic 190 * underflow and force zero if true. If not, try to shift the 191 * mantissa right until a zero exponent exists. 192 * 193 fix_dnrm: 194 cmpi.w #$ffc0,d1 ;lower bound for normalization 195 blt.w fix_unfl ;if lower, catastrophic unfl 196 move.w d1,d0 ;use d0 for exp 197 move.l d2,-(a7) ;free d2 for norm 198 move.l FPTEMP_HI(a6),d1 199 move.l FPTEMP_LO(a6),d2 200 clr.l L_SCR2(a6) 201 fix_loop: 202 add.w #1,d0 ;drive d0 to 0 203 lsr.l #1,d1 ;while shifting the 204 roxr.l #1,d2 ;mantissa to the right 205 bcc.b no_carry 206 st L_SCR2(a6) ;use L_SCR2 to capture inex 207 no_carry: 208 tst.w d0 ;it is finished when 209 blt.b fix_loop ;d0 is zero or the mantissa 210 tst.b L_SCR2(a6) 211 beq.b tst_zero 212 or.l #unfl_inx_mask,USER_FPSR(a6) 213 * ;set unfl, aunfl, ainex 214 * 215 * Test for zero. If zero, simply use fmove to return +/- zero 216 * to the fpu. 217 * 218 tst_zero: 219 clr.w FPTEMP_EX(a6) 220 tst.b L_SCR1(a6) ;test for sign 221 beq.b tst_con 222 or.w #$8000,FPTEMP_EX(a6) ;set sign bit 223 tst_con: 224 move.l d1,FPTEMP_HI(a6) 225 move.l d2,FPTEMP_LO(a6) 226 move.l (a7)+,d2 227 tst.l d1 228 bne.b not_zero 229 tst.l FPTEMP_LO(a6) 230 bne.b not_zero 231 * 232 * Result is zero. Check for rounding mode to set lsb. If the 233 * mode is rp, and the zero is positive, return smallest denorm. 234 * If the mode is rm, and the zero is negative, return smallest 235 * negative denorm. 236 * 237 btst.b #5,FPCR_MODE(a6) ;test if rm or rp 238 beq.b no_dir 239 btst.b #4,FPCR_MODE(a6) ;check which one 240 beq.b zer_rm 241 zer_rp: 242 tst.b L_SCR1(a6) ;check sign 243 bne.b no_dir ;if set, neg op, no inc 244 move.l #1,FPTEMP_LO(a6) ;set lsb 245 bra.b sm_dnrm 246 zer_rm: 247 tst.b L_SCR1(a6) ;check sign 248 beq.b no_dir ;if clr, neg op, no inc 249 move.l #1,FPTEMP_LO(a6) ;set lsb 250 or.l #neg_mask,USER_FPSR(a6) ;set N 251 bra.b sm_dnrm 252 no_dir: 253 fmove.l USER_FPCR(a6),FPCR 254 fmove.x FPTEMP(a6),fp0 ;use fmove to set cc's 255 rts 256 257 * 258 * The rounding mode changed the zero to a smallest denorm. Call 259 * t_resdnrm with exceptional operand in ETEMP. 260 * 261 sm_dnrm: 262 move.l FPTEMP_EX(a6),ETEMP_EX(a6) 263 move.l FPTEMP_HI(a6),ETEMP_HI(a6) 264 move.l FPTEMP_LO(a6),ETEMP_LO(a6) 265 lea.l ETEMP(a6),a0 266 bra t_resdnrm 267 268 * 269 * Result is still denormalized. 270 * 271 not_zero: 272 or.l #unfl_mask,USER_FPSR(a6) ;set unfl 273 tst.b L_SCR1(a6) ;check for sign 274 beq.b fix_exit 275 or.l #neg_mask,USER_FPSR(a6) ;set N 276 fix_exit: 277 bra.b sm_dnrm 278 279 280 * 281 * The result has underflowed to zero. Return zero and set 282 * unfl, aunfl, and ainex. 283 * 284 fix_unfl: 285 or.l #unfl_inx_mask,USER_FPSR(a6) 286 btst.b #5,FPCR_MODE(a6) ;test if rm or rp 287 beq.b no_dir2 288 btst.b #4,FPCR_MODE(a6) ;check which one 289 beq.b zer_rm2 290 zer_rp2: 291 tst.b L_SCR1(a6) ;check sign 292 bne.b no_dir2 ;if set, neg op, no inc 293 clr.l FPTEMP_EX(a6) 294 clr.l FPTEMP_HI(a6) 295 move.l #1,FPTEMP_LO(a6) ;set lsb 296 bra.b sm_dnrm ;return smallest denorm 297 zer_rm2: 298 tst.b L_SCR1(a6) ;check sign 299 beq.b no_dir2 ;if clr, neg op, no inc 300 move.w #$8000,FPTEMP_EX(a6) 301 clr.l FPTEMP_HI(a6) 302 move.l #1,FPTEMP_LO(a6) ;set lsb 303 or.l #neg_mask,USER_FPSR(a6) ;set N 304 bra.w sm_dnrm ;return smallest denorm 305 306 no_dir2: 307 tst.b L_SCR1(a6) 308 bge.b pos_zero 309 neg_zero: 310 clr.l FP_SCR1(a6) ;clear the exceptional operand 311 clr.l FP_SCR1+4(a6) ;for gen_except. 312 clr.l FP_SCR1+8(a6) 313 fmove.s #:80000000,fp0 314 rts 315 pos_zero: 316 clr.l FP_SCR1(a6) ;clear the exceptional operand 317 clr.l FP_SCR1+4(a6) ;for gen_except. 318 clr.l FP_SCR1+8(a6) 319 fmove.s #:00000000,fp0 320 rts 321 322 * 323 * The destination is a denormalized number. It must be handled 324 * by first shifting the bits in the mantissa until it is normalized, 325 * then adding the remainder of the source to the exponent. 326 * 327 dst_dnrm: 328 movem.l d2/d3,-(a7) 329 move.w FPTEMP_EX(a6),d1 330 move.l FPTEMP_HI(a6),d2 331 move.l FPTEMP_LO(a6),d3 332 dst_loop: 333 tst.l d2 ;test for normalized result 334 blt.b dst_norm ;exit loop if so 335 tst.l d0 ;otherwise, test shift count 336 beq.b dst_fin ;if zero, shifting is done 337 subq.l #1,d0 ;dec src 338 add.l d3,d3 339 addx.l d2,d2 340 bra.b dst_loop 341 * 342 * Destination became normalized. Simply add the remaining 343 * portion of the src to the exponent. 344 * 345 dst_norm: 346 add.w d0,d1 ;dst is normalized; add src 347 tst.b L_SCR1(a6) 348 beq.b dnrm_pos 349 or.w #$8000,d1 350 dnrm_pos: 351 movem.w d1,FPTEMP_EX(a6) 352 movem.l d2,FPTEMP_HI(a6) 353 movem.l d3,FPTEMP_LO(a6) 354 fmove.l USER_FPCR(a6),FPCR 355 fmove.x FPTEMP(a6),fp0 356 movem.l (a7)+,d2/d3 357 rts 358 359 * 360 * Destination remained denormalized. Call t_excdnrm with 361 * exceptional operand in ETEMP. 362 * 363 dst_fin: 364 tst.b L_SCR1(a6) ;check for sign 365 beq.b dst_exit 366 or.l #neg_mask,USER_FPSR(a6) ;set N 367 or.w #$8000,d1 368 dst_exit: 369 movem.w d1,ETEMP_EX(a6) 370 movem.l d2,ETEMP_HI(a6) 371 movem.l d3,ETEMP_LO(a6) 372 or.l #unfl_mask,USER_FPSR(a6) ;set unfl 373 movem.l (a7)+,d2/d3 374 lea.l ETEMP(a6),a0 375 bra t_resdnrm 376 377 * 378 * Source is outside of 2^14 range. Test the sign and branch 379 * to the appropriate exception handler. 380 * 381 src_out: 382 tst.b L_SCR1(a6) 383 beq.b scro_pos 384 or.w #$8000,d1 385 scro_pos: 386 move.l FPTEMP_HI(a6),ETEMP_HI(a6) 387 move.l FPTEMP_LO(a6),ETEMP_LO(a6) 388 tst.w ETEMP(a6) 389 blt.b res_neg 390 res_pos: 391 move.w d1,ETEMP(a6) ;result in ETEMP 392 bra t_ovfl2 393 res_neg: 394 move.w d1,ETEMP(a6) ;result in ETEMP 395 lea.l ETEMP(a6),a0 396 bra t_unfl 397 end 398