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