Annotation of sys/arch/m68k/fpsp/get_op.sa, Revision 1.1
1.1 ! nbrk 1: * $OpenBSD: get_op.sa,v 1.2 1996/05/29 21:05:29 niklas Exp $
! 2: * $NetBSD: get_op.sa,v 1.3 1994/10/26 07:49:09 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: * get_op.sa 3.6 5/19/92
! 36: *
! 37: * get_op.sa 3.5 4/26/91
! 38: *
! 39: * Description: This routine is called by the unsupported format/data
! 40: * type exception handler ('unsupp' - vector 55) and the unimplemented
! 41: * instruction exception handler ('unimp' - vector 11). 'get_op'
! 42: * determines the opclass (0, 2, or 3) and branches to the
! 43: * opclass handler routine. See 68881/2 User's Manual table 4-11
! 44: * for a description of the opclasses.
! 45: *
! 46: * For UNSUPPORTED data/format (exception vector 55) and for
! 47: * UNIMPLEMENTED instructions (exception vector 11) the following
! 48: * applies:
! 49: *
! 50: * - For unnormormalized numbers (opclass 0, 2, or 3) the
! 51: * number(s) is normalized and the operand type tag is updated.
! 52: *
! 53: * - For a packed number (opclass 2) the number is unpacked and the
! 54: * operand type tag is updated.
! 55: *
! 56: * - For denormalized numbers (opclass 0 or 2) the number(s) is not
! 57: * changed but passed to the next module. The next module for
! 58: * unimp is do_func, the next module for unsupp is res_func.
! 59: *
! 60: * For UNSUPPORTED data/format (exception vector 55) only the
! 61: * following applies:
! 62: *
! 63: * - If there is a move out with a packed number (opclass 3) the
! 64: * number is packed and written to user memory. For the other
! 65: * opclasses the number(s) are written back to the fsave stack
! 66: * and the instruction is then restored back into the '040. The
! 67: * '040 is then able to complete the instruction.
! 68: *
! 69: * For example:
! 70: * fadd.x fpm,fpn where the fpm contains an unnormalized number.
! 71: * The '040 takes an unsupported data trap and gets to this
! 72: * routine. The number is normalized, put back on the stack and
! 73: * then an frestore is done to restore the instruction back into
! 74: * the '040. The '040 then re-executes the fadd.x fpm,fpn with
! 75: * a normalized number in the source and the instruction is
! 76: * successful.
! 77: *
! 78: * Next consider if in the process of normalizing the un-
! 79: * normalized number it becomes a denormalized number. The
! 80: * routine which converts the unnorm to a norm (called mk_norm)
! 81: * detects this and tags the number as a denorm. The routine
! 82: * res_func sees the denorm tag and converts the denorm to a
! 83: * norm. The instruction is then restored back into the '040
! 84: * which re_executess the instruction.
! 85: *
! 86:
! 87: GET_OP IDNT 2,1 Motorola 040 Floating Point Software Package
! 88:
! 89: section 8
! 90:
! 91: include fpsp.h
! 92:
! 93: xdef PIRN,PIRZRM,PIRP
! 94: xdef SMALRN,SMALRZRM,SMALRP
! 95: xdef BIGRN,BIGRZRM,BIGRP
! 96:
! 97: PIRN:
! 98: dc.l $40000000,$c90fdaa2,$2168c235 ;pi
! 99: PIRZRM:
! 100: dc.l $40000000,$c90fdaa2,$2168c234 ;pi
! 101: PIRP:
! 102: dc.l $40000000,$c90fdaa2,$2168c235 ;pi
! 103:
! 104: *round to nearest
! 105: SMALRN:
! 106: dc.l $3ffd0000,$9a209a84,$fbcff798 ;log10(2)
! 107: dc.l $40000000,$adf85458,$a2bb4a9a ;e
! 108: dc.l $3fff0000,$b8aa3b29,$5c17f0bc ;log2(e)
! 109: dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
! 110: dc.l $00000000,$00000000,$00000000 ;0.0
! 111: * round to zero;round to negative infinity
! 112: SMALRZRM:
! 113: dc.l $3ffd0000,$9a209a84,$fbcff798 ;log10(2)
! 114: dc.l $40000000,$adf85458,$a2bb4a9a ;e
! 115: dc.l $3fff0000,$b8aa3b29,$5c17f0bb ;log2(e)
! 116: dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
! 117: dc.l $00000000,$00000000,$00000000 ;0.0
! 118: * round to positive infinity
! 119: SMALRP:
! 120: dc.l $3ffd0000,$9a209a84,$fbcff799 ;log10(2)
! 121: dc.l $40000000,$adf85458,$a2bb4a9b ;e
! 122: dc.l $3fff0000,$b8aa3b29,$5c17f0bc ;log2(e)
! 123: dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
! 124: dc.l $00000000,$00000000,$00000000 ;0.0
! 125:
! 126: *round to nearest
! 127: BIGRN:
! 128: dc.l $3ffe0000,$b17217f7,$d1cf79ac ;ln(2)
! 129: dc.l $40000000,$935d8ddd,$aaa8ac17 ;ln(10)
! 130: dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
! 131:
! 132: xdef PTENRN
! 133: PTENRN:
! 134: dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
! 135: dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
! 136: dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
! 137: dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
! 138: dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
! 139: dc.l $40690000,$9DC5ADA8,$2B70B59E ;10 ^ 32
! 140: dc.l $40D30000,$C2781F49,$FFCFA6D5 ;10 ^ 64
! 141: dc.l $41A80000,$93BA47C9,$80E98CE0 ;10 ^ 128
! 142: dc.l $43510000,$AA7EEBFB,$9DF9DE8E ;10 ^ 256
! 143: dc.l $46A30000,$E319A0AE,$A60E91C7 ;10 ^ 512
! 144: dc.l $4D480000,$C9767586,$81750C17 ;10 ^ 1024
! 145: dc.l $5A920000,$9E8B3B5D,$C53D5DE5 ;10 ^ 2048
! 146: dc.l $75250000,$C4605202,$8A20979B ;10 ^ 4096
! 147: *round to minus infinity
! 148: BIGRZRM:
! 149: dc.l $3ffe0000,$b17217f7,$d1cf79ab ;ln(2)
! 150: dc.l $40000000,$935d8ddd,$aaa8ac16 ;ln(10)
! 151: dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
! 152:
! 153: xdef PTENRM
! 154: PTENRM:
! 155: dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
! 156: dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
! 157: dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
! 158: dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
! 159: dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
! 160: dc.l $40690000,$9DC5ADA8,$2B70B59D ;10 ^ 32
! 161: dc.l $40D30000,$C2781F49,$FFCFA6D5 ;10 ^ 64
! 162: dc.l $41A80000,$93BA47C9,$80E98CDF ;10 ^ 128
! 163: dc.l $43510000,$AA7EEBFB,$9DF9DE8D ;10 ^ 256
! 164: dc.l $46A30000,$E319A0AE,$A60E91C6 ;10 ^ 512
! 165: dc.l $4D480000,$C9767586,$81750C17 ;10 ^ 1024
! 166: dc.l $5A920000,$9E8B3B5D,$C53D5DE5 ;10 ^ 2048
! 167: dc.l $75250000,$C4605202,$8A20979A ;10 ^ 4096
! 168: *round to positive infinity
! 169: BIGRP:
! 170: dc.l $3ffe0000,$b17217f7,$d1cf79ac ;ln(2)
! 171: dc.l $40000000,$935d8ddd,$aaa8ac17 ;ln(10)
! 172: dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
! 173:
! 174: xdef PTENRP
! 175: PTENRP:
! 176: dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
! 177: dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
! 178: dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
! 179: dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
! 180: dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
! 181: dc.l $40690000,$9DC5ADA8,$2B70B59E ;10 ^ 32
! 182: dc.l $40D30000,$C2781F49,$FFCFA6D6 ;10 ^ 64
! 183: dc.l $41A80000,$93BA47C9,$80E98CE0 ;10 ^ 128
! 184: dc.l $43510000,$AA7EEBFB,$9DF9DE8E ;10 ^ 256
! 185: dc.l $46A30000,$E319A0AE,$A60E91C7 ;10 ^ 512
! 186: dc.l $4D480000,$C9767586,$81750C18 ;10 ^ 1024
! 187: dc.l $5A920000,$9E8B3B5D,$C53D5DE6 ;10 ^ 2048
! 188: dc.l $75250000,$C4605202,$8A20979B ;10 ^ 4096
! 189:
! 190: xref nrm_zero
! 191: xref decbin
! 192: xref round
! 193:
! 194: xdef get_op
! 195: xdef uns_getop
! 196: xdef uni_getop
! 197: get_op:
! 198: clr.b DY_MO_FLG(a6)
! 199: tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
! 200: beq.b uni_getop
! 201:
! 202: uns_getop:
! 203: btst.b #direction_bit,CMDREG1B(a6)
! 204: bne.w opclass3 ;branch if a fmove out (any kind)
! 205: btst.b #6,CMDREG1B(a6)
! 206: beq.b uns_notpacked
! 207:
! 208: bfextu CMDREG1B(a6){3:3},d0
! 209: cmp.b #3,d0
! 210: beq.w pack_source ;check for a packed src op, branch if so
! 211: uns_notpacked:
! 212: bsr chk_dy_mo ;set the dyadic/monadic flag
! 213: tst.b DY_MO_FLG(a6)
! 214: beq.b src_op_ck ;if monadic, go check src op
! 215: * ;else, check dst op (fall through)
! 216:
! 217: btst.b #7,DTAG(a6)
! 218: beq.b src_op_ck ;if dst op is norm, check src op
! 219: bra.b dst_ex_dnrm ;else, handle destination unnorm/dnrm
! 220:
! 221: uni_getop:
! 222: bfextu CMDREG1B(a6){0:6},d0 ;get opclass and src fields
! 223: cmpi.l #$17,d0 ;if op class and size fields are $17,
! 224: * ;it is FMOVECR; if not, continue
! 225: *
! 226: * If the instruction is fmovecr, exit get_op. It is handled
! 227: * in do_func and smovecr.sa.
! 228: *
! 229: bne.w not_fmovecr ;handle fmovecr as an unimplemented inst
! 230: rts
! 231:
! 232: not_fmovecr:
! 233: btst.b #E1,E_BYTE(a6) ;if set, there is a packed operand
! 234: bne.w pack_source ;check for packed src op, branch if so
! 235:
! 236: * The following lines of are coded to optimize on normalized operands
! 237: move.b STAG(a6),d0
! 238: or.b DTAG(a6),d0 ;check if either of STAG/DTAG msb set
! 239: bmi.b dest_op_ck ;if so, some op needs to be fixed
! 240: rts
! 241:
! 242: dest_op_ck:
! 243: btst.b #7,DTAG(a6) ;check for unsupported data types in
! 244: beq.b src_op_ck ;the destination, if not, check src op
! 245: bsr chk_dy_mo ;set dyadic/monadic flag
! 246: tst.b DY_MO_FLG(a6) ;
! 247: beq.b src_op_ck ;if monadic, check src op
! 248: *
! 249: * At this point, destination has an extended denorm or unnorm.
! 250: *
! 251: dst_ex_dnrm:
! 252: move.w FPTEMP_EX(a6),d0 ;get destination exponent
! 253: andi.w #$7fff,d0 ;mask sign, check if exp = 0000
! 254: beq.b src_op_ck ;if denorm then check source op.
! 255: * ;denorms are taken care of in res_func
! 256: * ;(unsupp) or do_func (unimp)
! 257: * ;else unnorm fall through
! 258: lea.l FPTEMP(a6),a0 ;point a0 to dop - used in mk_norm
! 259: bsr mk_norm ;go normalize - mk_norm returns:
! 260: * ;L_SCR1{7:5} = operand tag
! 261: * ; (000 = norm, 100 = denorm)
! 262: * ;L_SCR1{4} = fpte15 or ete15
! 263: * ; 0 = exp > $3fff
! 264: * ; 1 = exp <= $3fff
! 265: * ;and puts the normalized num back
! 266: * ;on the fsave stack
! 267: *
! 268: move.b L_SCR1(a6),DTAG(a6) ;write the new tag & fpte15
! 269: * ;to the fsave stack and fall
! 270: * ;through to check source operand
! 271: *
! 272: src_op_ck:
! 273: btst.b #7,STAG(a6)
! 274: beq.w end_getop ;check for unsupported data types on the
! 275: * ;source operand
! 276: btst.b #5,STAG(a6)
! 277: bne.b src_sd_dnrm ;if bit 5 set, handle sgl/dbl denorms
! 278: *
! 279: * At this point only unnorms or extended denorms are possible.
! 280: *
! 281: src_ex_dnrm:
! 282: move.w ETEMP_EX(a6),d0 ;get source exponent
! 283: andi.w #$7fff,d0 ;mask sign, check if exp = 0000
! 284: beq.w end_getop ;if denorm then exit, denorms are
! 285: * ;handled in do_func
! 286: lea.l ETEMP(a6),a0 ;point a0 to sop - used in mk_norm
! 287: bsr mk_norm ;go normalize - mk_norm returns:
! 288: * ;L_SCR1{7:5} = operand tag
! 289: * ; (000 = norm, 100 = denorm)
! 290: * ;L_SCR1{4} = fpte15 or ete15
! 291: * ; 0 = exp > $3fff
! 292: * ; 1 = exp <= $3fff
! 293: * ;and puts the normalized num back
! 294: * ;on the fsave stack
! 295: *
! 296: move.b L_SCR1(a6),STAG(a6) ;write the new tag & ete15
! 297: rts ;end_getop
! 298:
! 299: *
! 300: * At this point, only single or double denorms are possible.
! 301: * If the inst is not fmove, normalize the source. If it is,
! 302: * do nothing to the input.
! 303: *
! 304: src_sd_dnrm:
! 305: btst.b #4,CMDREG1B(a6) ;differentiate between sgl/dbl denorm
! 306: bne.b is_double
! 307: is_single:
! 308: move.w #$3f81,d1 ;write bias for sgl denorm
! 309: bra.b common ;goto the common code
! 310: is_double:
! 311: move.w #$3c01,d1 ;write the bias for a dbl denorm
! 312: common:
! 313: btst.b #sign_bit,ETEMP_EX(a6) ;grab sign bit of mantissa
! 314: beq.b pos
! 315: bset #15,d1 ;set sign bit because it is negative
! 316: pos:
! 317: move.w d1,ETEMP_EX(a6)
! 318: * ;put exponent on stack
! 319:
! 320: move.w CMDREG1B(a6),d1
! 321: and.w #$e3ff,d1 ;clear out source specifier
! 322: or.w #$0800,d1 ;set source specifier to extended prec
! 323: move.w d1,CMDREG1B(a6) ;write back to the command word in stack
! 324: * ;this is needed to fix unsupp data stack
! 325: lea.l ETEMP(a6),a0 ;point a0 to sop
! 326:
! 327: bsr mk_norm ;convert sgl/dbl denorm to norm
! 328: move.b L_SCR1(a6),STAG(a6) ;put tag into source tag reg - d0
! 329: rts ;end_getop
! 330: *
! 331: * At this point, the source is definitely packed, whether
! 332: * instruction is dyadic or monadic is still unknown
! 333: *
! 334: pack_source:
! 335: move.l FPTEMP_LO(a6),ETEMP(a6) ;write ms part of packed
! 336: * ;number to etemp slot
! 337: bsr chk_dy_mo ;set dyadic/monadic flag
! 338: bsr unpack
! 339:
! 340: tst.b DY_MO_FLG(a6)
! 341: beq.b end_getop ;if monadic, exit
! 342: * ;else, fix FPTEMP
! 343: pack_dya:
! 344: bfextu CMDREG1B(a6){6:3},d0 ;extract dest fp reg
! 345: move.l #7,d1
! 346: sub.l d0,d1
! 347: clr.l d0
! 348: bset.l d1,d0 ;set up d0 as a dynamic register mask
! 349: fmovem.x d0,FPTEMP(a6) ;write to FPTEMP
! 350:
! 351: btst.b #7,DTAG(a6) ;check dest tag for unnorm or denorm
! 352: bne.w dst_ex_dnrm ;else, handle the unnorm or ext denorm
! 353: *
! 354: * Dest is not denormalized. Check for norm, and set fpte15
! 355: * accordingly.
! 356: *
! 357: move.b DTAG(a6),d0
! 358: andi.b #$f0,d0 ;strip to only dtag:fpte15
! 359: tst.b d0 ;check for normalized value
! 360: bne.b end_getop ;if inf/nan/zero leave get_op
! 361: move.w FPTEMP_EX(a6),d0
! 362: andi.w #$7fff,d0
! 363: cmpi.w #$3fff,d0 ;check if fpte15 needs setting
! 364: bge.b end_getop ;if >= $3fff, leave fpte15=0
! 365: or.b #$10,DTAG(a6)
! 366: bra.b end_getop
! 367:
! 368: *
! 369: * At this point, it is either an fmoveout packed, unnorm or denorm
! 370: *
! 371: opclass3:
! 372: clr.b DY_MO_FLG(a6) ;set dyadic/monadic flag to monadic
! 373: bfextu CMDREG1B(a6){4:2},d0
! 374: cmpi.b #3,d0
! 375: bne.w src_ex_dnrm ;if not equal, must be unnorm or denorm
! 376: * ;else it is a packed move out
! 377: * ;exit
! 378: end_getop:
! 379: rts
! 380:
! 381: *
! 382: * Sets the DY_MO_FLG correctly. This is used only on if it is an
! 383: * unuspported data type exception. Set if dyadic.
! 384: *
! 385: chk_dy_mo:
! 386: move.w CMDREG1B(a6),d0
! 387: btst.l #5,d0 ;testing extension command word
! 388: beq.b set_mon ;if bit 5 = 0 then monadic
! 389: btst.l #4,d0 ;know that bit 5 = 1
! 390: beq.b set_dya ;if bit 4 = 0 then dyadic
! 391: andi.w #$007f,d0 ;get rid of all but extension bits {6:0}
! 392: cmpi.w #$0038,d0 ;if extension = $38 then fcmp (dyadic)
! 393: bne.b set_mon
! 394: set_dya:
! 395: st.b DY_MO_FLG(a6) ;set the inst flag type to dyadic
! 396: rts
! 397: set_mon:
! 398: clr.b DY_MO_FLG(a6) ;set the inst flag type to monadic
! 399: rts
! 400: *
! 401: * MK_NORM
! 402: *
! 403: * Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
! 404: * exception if denorm.
! 405: *
! 406: * CASE opclass 0x0 unsupp
! 407: * mk_norm till msb set
! 408: * set tag = norm
! 409: *
! 410: * CASE opclass 0x0 unimp
! 411: * mk_norm till msb set or exp = 0
! 412: * if integer bit = 0
! 413: * tag = denorm
! 414: * else
! 415: * tag = norm
! 416: *
! 417: * CASE opclass 011 unsupp
! 418: * mk_norm till msb set or exp = 0
! 419: * if integer bit = 0
! 420: * tag = denorm
! 421: * set unfl_nmcexe = 1
! 422: * else
! 423: * tag = norm
! 424: *
! 425: * if exp <= $3fff
! 426: * set ete15 or fpte15 = 1
! 427: * else set ete15 or fpte15 = 0
! 428:
! 429: * input:
! 430: * a0 = points to operand to be normalized
! 431: * output:
! 432: * L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
! 433: * L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
! 434: * the normalized operand is placed back on the fsave stack
! 435: mk_norm:
! 436: clr.l L_SCR1(a6)
! 437: bclr.b #sign_bit,LOCAL_EX(a0)
! 438: sne LOCAL_SGN(a0) ;transform into internal extended format
! 439:
! 440: cmpi.b #$2c,1+EXC_VEC(a6) ;check if unimp
! 441: bne.b uns_data ;branch if unsupp
! 442: bsr uni_inst ;call if unimp (opclass 0x0)
! 443: bra.b reload
! 444: uns_data:
! 445: btst.b #direction_bit,CMDREG1B(a6) ;check transfer direction
! 446: bne.b bit_set ;branch if set (opclass 011)
! 447: bsr uns_opx ;call if opclass 0x0
! 448: bra.b reload
! 449: bit_set:
! 450: bsr uns_op3 ;opclass 011
! 451: reload:
! 452: cmp.w #$3fff,LOCAL_EX(a0) ;if exp > $3fff
! 453: bgt.b end_mk ; fpte15/ete15 already set to 0
! 454: bset.b #4,L_SCR1(a6) ;else set fpte15/ete15 to 1
! 455: * ;calling routine actually sets the
! 456: * ;value on the stack (along with the
! 457: * ;tag), since this routine doesn't
! 458: * ;know if it should set ete15 or fpte15
! 459: * ;ie, it doesn't know if this is the
! 460: * ;src op or dest op.
! 461: end_mk:
! 462: bfclr LOCAL_SGN(a0){0:8}
! 463: beq.b end_mk_pos
! 464: bset.b #sign_bit,LOCAL_EX(a0) ;convert back to IEEE format
! 465: end_mk_pos:
! 466: rts
! 467: *
! 468: * CASE opclass 011 unsupp
! 469: *
! 470: uns_op3:
! 471: bsr nrm_zero ;normalize till msb = 1 or exp = zero
! 472: btst.b #7,LOCAL_HI(a0) ;if msb = 1
! 473: bne.b no_unfl ;then branch
! 474: set_unfl:
! 475: or.b #dnrm_tag,L_SCR1(a6) ;set denorm tag
! 476: bset.b #unfl_bit,FPSR_EXCEPT(a6) ;set unfl exception bit
! 477: no_unfl:
! 478: rts
! 479: *
! 480: * CASE opclass 0x0 unsupp
! 481: *
! 482: uns_opx:
! 483: bsr nrm_zero ;normalize the number
! 484: btst.b #7,LOCAL_HI(a0) ;check if integer bit (j-bit) is set
! 485: beq.b uns_den ;if clear then now have a denorm
! 486: uns_nrm:
! 487: or.b #norm_tag,L_SCR1(a6) ;set tag to norm
! 488: rts
! 489: uns_den:
! 490: or.b #dnrm_tag,L_SCR1(a6) ;set tag to denorm
! 491: rts
! 492: *
! 493: * CASE opclass 0x0 unimp
! 494: *
! 495: uni_inst:
! 496: bsr nrm_zero
! 497: btst.b #7,LOCAL_HI(a0) ;check if integer bit (j-bit) is set
! 498: beq.b uni_den ;if clear then now have a denorm
! 499: uni_nrm:
! 500: or.b #norm_tag,L_SCR1(a6) ;set tag to norm
! 501: rts
! 502: uni_den:
! 503: or.b #dnrm_tag,L_SCR1(a6) ;set tag to denorm
! 504: rts
! 505:
! 506: *
! 507: * Decimal to binary conversion
! 508: *
! 509: * Special cases of inf and NaNs are completed outside of decbin.
! 510: * If the input is an snan, the snan bit is not set.
! 511: *
! 512: * input:
! 513: * ETEMP(a6) - points to packed decimal string in memory
! 514: * output:
! 515: * fp0 - contains packed string converted to extended precision
! 516: * ETEMP - same as fp0
! 517: unpack:
! 518: move.w CMDREG1B(a6),d0 ;examine command word, looking for fmove's
! 519: and.w #$3b,d0
! 520: beq move_unpack ;special handling for fmove: must set FPSR_CC
! 521:
! 522: move.w ETEMP(a6),d0 ;get word with inf information
! 523: bfextu d0{20:12},d1 ;get exponent into d1
! 524: cmpi.w #$0fff,d1 ;test for inf or NaN
! 525: bne.b try_zero ;if not equal, it is not special
! 526: bfextu d0{17:3},d1 ;get SE and y bits into d1
! 527: cmpi.w #7,d1 ;SE and y bits must be on for special
! 528: bne.b try_zero ;if not on, it is not special
! 529: *input is of the special cases of inf and NaN
! 530: tst.l ETEMP_HI(a6) ;check ms mantissa
! 531: bne.b fix_nan ;if non-zero, it is a NaN
! 532: tst.l ETEMP_LO(a6) ;check ls mantissa
! 533: bne.b fix_nan ;if non-zero, it is a NaN
! 534: bra.w finish ;special already on stack
! 535: fix_nan:
! 536: btst.b #signan_bit,ETEMP_HI(a6) ;test for snan
! 537: bne.w finish
! 538: or.l #snaniop_mask,USER_FPSR(a6) ;always set snan if it is so
! 539: bra.w finish
! 540: try_zero:
! 541: move.w ETEMP_EX+2(a6),d0 ;get word 4
! 542: andi.w #$000f,d0 ;clear all but last ni(y)bble
! 543: tst.w d0 ;check for zero.
! 544: bne.w not_spec
! 545: tst.l ETEMP_HI(a6) ;check words 3 and 2
! 546: bne.w not_spec
! 547: tst.l ETEMP_LO(a6) ;check words 1 and 0
! 548: bne.w not_spec
! 549: tst.l ETEMP(a6) ;test sign of the zero
! 550: bge.b pos_zero
! 551: move.l #$80000000,ETEMP(a6) ;write neg zero to etemp
! 552: clr.l ETEMP_HI(a6)
! 553: clr.l ETEMP_LO(a6)
! 554: bra.w finish
! 555: pos_zero:
! 556: clr.l ETEMP(a6)
! 557: clr.l ETEMP_HI(a6)
! 558: clr.l ETEMP_LO(a6)
! 559: bra.w finish
! 560:
! 561: not_spec:
! 562: fmovem.x fp0-fp1,-(a7) ;save fp0 - decbin returns in it
! 563: bsr decbin
! 564: fmove.x fp0,ETEMP(a6) ;put the unpacked sop in the fsave stack
! 565: fmovem.x (a7)+,fp0-fp1
! 566: fmove.l #0,FPSR ;clr fpsr from decbin
! 567: bra finish
! 568:
! 569: *
! 570: * Special handling for packed move in: Same results as all other
! 571: * packed cases, but we must set the FPSR condition codes properly.
! 572: *
! 573: move_unpack:
! 574: move.w ETEMP(a6),d0 ;get word with inf information
! 575: bfextu d0{20:12},d1 ;get exponent into d1
! 576: cmpi.w #$0fff,d1 ;test for inf or NaN
! 577: bne.b mtry_zero ;if not equal, it is not special
! 578: bfextu d0{17:3},d1 ;get SE and y bits into d1
! 579: cmpi.w #7,d1 ;SE and y bits must be on for special
! 580: bne.b mtry_zero ;if not on, it is not special
! 581: *input is of the special cases of inf and NaN
! 582: tst.l ETEMP_HI(a6) ;check ms mantissa
! 583: bne.b mfix_nan ;if non-zero, it is a NaN
! 584: tst.l ETEMP_LO(a6) ;check ls mantissa
! 585: bne.b mfix_nan ;if non-zero, it is a NaN
! 586: *input is inf
! 587: or.l #inf_mask,USER_FPSR(a6) ;set I bit
! 588: tst.l ETEMP(a6) ;check sign
! 589: bge.w finish
! 590: or.l #neg_mask,USER_FPSR(a6) ;set N bit
! 591: bra.w finish ;special already on stack
! 592: mfix_nan:
! 593: or.l #nan_mask,USER_FPSR(a6) ;set NaN bit
! 594: move.b #nan_tag,STAG(a6) ;set stag to NaN
! 595: btst.b #signan_bit,ETEMP_HI(a6) ;test for snan
! 596: bne.b mn_snan
! 597: or.l #snaniop_mask,USER_FPSR(a6) ;set snan bit
! 598: btst.b #snan_bit,FPCR_ENABLE(a6) ;test for snan enabled
! 599: bne.b mn_snan
! 600: bset.b #signan_bit,ETEMP_HI(a6) ;force snans to qnans
! 601: mn_snan:
! 602: tst.l ETEMP(a6) ;check for sign
! 603: bge.w finish ;if clr, go on
! 604: or.l #neg_mask,USER_FPSR(a6) ;set N bit
! 605: bra.w finish
! 606:
! 607: mtry_zero:
! 608: move.w ETEMP_EX+2(a6),d0 ;get word 4
! 609: andi.w #$000f,d0 ;clear all but last ni(y)bble
! 610: tst.w d0 ;check for zero.
! 611: bne.b mnot_spec
! 612: tst.l ETEMP_HI(a6) ;check words 3 and 2
! 613: bne.b mnot_spec
! 614: tst.l ETEMP_LO(a6) ;check words 1 and 0
! 615: bne.b mnot_spec
! 616: tst.l ETEMP(a6) ;test sign of the zero
! 617: bge.b mpos_zero
! 618: or.l #neg_mask+z_mask,USER_FPSR(a6) ;set N and Z
! 619: move.l #$80000000,ETEMP(a6) ;write neg zero to etemp
! 620: clr.l ETEMP_HI(a6)
! 621: clr.l ETEMP_LO(a6)
! 622: bra.b finish
! 623: mpos_zero:
! 624: or.l #z_mask,USER_FPSR(a6) ;set Z
! 625: clr.l ETEMP(a6)
! 626: clr.l ETEMP_HI(a6)
! 627: clr.l ETEMP_LO(a6)
! 628: bra.b finish
! 629:
! 630: mnot_spec:
! 631: fmovem.x fp0-fp1,-(a7) ;save fp0 ,fp1 - decbin returns in fp0
! 632: bsr decbin
! 633: fmove.x fp0,ETEMP(a6)
! 634: * ;put the unpacked sop in the fsave stack
! 635: fmovem.x (a7)+,fp0-fp1
! 636:
! 637: finish:
! 638: move.w CMDREG1B(a6),d0 ;get the command word
! 639: and.w #$fbff,d0 ;change the source specifier field to
! 640: * ;extended (was packed).
! 641: move.w d0,CMDREG1B(a6) ;write command word back to fsave stack
! 642: * ;we need to do this so the 040 will
! 643: * ;re-execute the inst. without taking
! 644: * ;another packed trap.
! 645:
! 646: fix_stag:
! 647: *Converted result is now in etemp on fsave stack, now set the source
! 648: *tag (stag)
! 649: * if (ete =$7fff) then INF or NAN
! 650: * if (etemp = $x.0----0) then
! 651: * stag = INF
! 652: * else
! 653: * stag = NAN
! 654: * else
! 655: * if (ete = $0000) then
! 656: * stag = ZERO
! 657: * else
! 658: * stag = NORM
! 659: *
! 660: * Note also that the etemp_15 bit (just right of the stag) must
! 661: * be set accordingly.
! 662: *
! 663: move.w ETEMP_EX(a6),d1
! 664: andi.w #$7fff,d1 ;strip sign
! 665: cmp.w #$7fff,d1
! 666: bne.b z_or_nrm
! 667: move.l ETEMP_HI(a6),d1
! 668: bne.b is_nan
! 669: move.l ETEMP_LO(a6),d1
! 670: bne.b is_nan
! 671: is_inf:
! 672: move.b #$40,STAG(a6)
! 673: move.l #$40,d0
! 674: rts
! 675: is_nan:
! 676: move.b #$60,STAG(a6)
! 677: move.l #$60,d0
! 678: rts
! 679: z_or_nrm:
! 680: tst.w d1
! 681: bne.b is_nrm
! 682: is_zro:
! 683: * For a zero, set etemp_15
! 684: move.b #$30,STAG(a6)
! 685: move.l #$20,d0
! 686: rts
! 687: is_nrm:
! 688: * For a norm, check if the exp <= $3fff; if so, set etemp_15
! 689: cmpi.w #$3fff,d1
! 690: ble.b set_bit15
! 691: clr.b STAG(a6)
! 692: bra.b end_is_nrm
! 693: set_bit15:
! 694: move.b #$10,STAG(a6)
! 695: end_is_nrm:
! 696: clr.l d0
! 697: end_fix:
! 698: rts
! 699:
! 700: end_get:
! 701: rts
! 702: end
CVSweb