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