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