Annotation of sys/arch/m68k/fpsp/x_operr.sa, Revision 1.1
1.1 ! nbrk 1: * $OpenBSD: x_operr.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
! 2: * $NetBSD: x_operr.sa,v 1.4 1994/10/26 07:50:24 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: * x_operr.sa 3.5 7/1/91
! 36: *
! 37: * fpsp_operr --- FPSP handler for operand error exception
! 38: *
! 39: * See 68040 User's Manual pp. 9-44f
! 40: *
! 41: * Note 1: For trap disabled 040 does the following:
! 42: * If the dest is a fp reg, then an extended precision non_signaling
! 43: * NAN is stored in the dest reg. If the dest format is b, w, or l and
! 44: * the source op is a NAN, then garbage is stored as the result (actually
! 45: * the upper 32 bits of the mantissa are sent to the integer unit). If
! 46: * the dest format is integer (b, w, l) and the operr is caused by
! 47: * integer overflow, or the source op is inf, then the result stored is
! 48: * garbage.
! 49: * There are three cases in which operr is incorrectly signaled on the
! 50: * 040. This occurs for move_out of format b, w, or l for the largest
! 51: * negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
! 52: *
! 53: * On opclass = 011 fmove.(b,w,l) that causes a conversion
! 54: * overflow -> OPERR, the exponent in wbte (and fpte) is:
! 55: * byte 56 - (62 - exp)
! 56: * word 48 - (62 - exp)
! 57: * long 32 - (62 - exp)
! 58: *
! 59: * where exp = (true exp) - 1
! 60: *
! 61: * So, wbtemp and fptemp will contain the following on erroneoulsy
! 62: * signalled operr:
! 63: * fpts = 1
! 64: * fpte = $4000 (15 bit externally)
! 65: * byte fptm = $ffffffff ffffff80
! 66: * word fptm = $ffffffff ffff8000
! 67: * long fptm = $ffffffff 80000000
! 68: *
! 69: * Note 2: For trap enabled 040 does the following:
! 70: * If the inst is move_out, then same as Note 1.
! 71: * If the inst is not move_out, the dest is not modified.
! 72: * The exceptional operand is not defined for integer overflow
! 73: * during a move_out.
! 74: *
! 75:
! 76: X_OPERR IDNT 2,1 Motorola 040 Floating Point Software Package
! 77:
! 78: section 8
! 79:
! 80: include fpsp.h
! 81:
! 82: xref mem_write
! 83: xref real_operr
! 84: xref real_inex
! 85: xref get_fline
! 86: xref fpsp_done
! 87: xref reg_dest
! 88:
! 89: xdef fpsp_operr
! 90: fpsp_operr:
! 91: *
! 92: link a6,#-LOCAL_SIZE
! 93: fsave -(a7)
! 94: movem.l d0-d1/a0-a1,USER_DA(a6)
! 95: fmovem.x fp0-fp3,USER_FP0(a6)
! 96: fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6)
! 97:
! 98: *
! 99: * Check if this is an opclass 3 instruction.
! 100: * If so, fall through, else branch to operr_end
! 101: *
! 102: btst.b #TFLAG,T_BYTE(a6)
! 103: beq.b operr_end
! 104:
! 105: *
! 106: * If the destination size is B,W,or L, the operr must be
! 107: * handled here.
! 108: *
! 109: move.l CMDREG1B(a6),d0
! 110: bfextu d0{3:3},d0 ;0=long, 4=word, 6=byte
! 111: tst.b d0 ;determine size; check long
! 112: beq.w operr_long
! 113: cmpi.b #4,d0 ;check word
! 114: beq.w operr_word
! 115: cmpi.b #6,d0 ;check byte
! 116: beq.w operr_byte
! 117:
! 118: *
! 119: * The size is not B,W,or L, so the operr is handled by the
! 120: * kernel handler. Set the operr bits and clean up, leaving
! 121: * only the integer exception frame on the stack, and the
! 122: * fpu in the original exceptional state.
! 123: *
! 124: operr_end:
! 125: bset.b #operr_bit,FPSR_EXCEPT(a6)
! 126: bset.b #aiop_bit,FPSR_AEXCEPT(a6)
! 127:
! 128: movem.l USER_DA(a6),d0-d1/a0-a1
! 129: fmovem.x USER_FP0(a6),fp0-fp3
! 130: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 131: frestore (a7)+
! 132: unlk a6
! 133: bra.l real_operr
! 134:
! 135: operr_long:
! 136: moveq.l #4,d1 ;write size to d1
! 137: move.b STAG(a6),d0 ;test stag for nan
! 138: andi.b #$e0,d0 ;clr all but tag
! 139: cmpi.b #$60,d0 ;check for nan
! 140: beq operr_nan
! 141: cmpi.l #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
! 142: bne.b chklerr ;if not equal, check for incorrect operr
! 143: bsr check_upper ;check if exp and ms mant are special
! 144: tst.l d0
! 145: bne.b chklerr ;if d0 is true, check for incorrect operr
! 146: move.l #$80000000,d0 ;store special case result
! 147: bsr operr_store
! 148: bra.w not_enabled ;clean and exit
! 149: *
! 150: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
! 151: *
! 152: chklerr:
! 153: move.w FPTEMP_EX(a6),d0
! 154: and.w #$7FFF,d0 ;ignore sign bit
! 155: cmp.w #$3FFE,d0 ;this is the only possible exponent value
! 156: bne.b chklerr2
! 157: fixlong:
! 158: move.l FPTEMP_LO(a6),d0
! 159: bsr operr_store
! 160: bra.w not_enabled
! 161: chklerr2:
! 162: move.w FPTEMP_EX(a6),d0
! 163: and.w #$7FFF,d0 ;ignore sign bit
! 164: cmp.w #$4000,d0
! 165: bcc.w store_max ;exponent out of range
! 166:
! 167: move.l FPTEMP_LO(a6),d0
! 168: and.l #$7FFF0000,d0 ;look for all 1's on bits 30-16
! 169: cmp.l #$7FFF0000,d0
! 170: beq.b fixlong
! 171:
! 172: tst.l FPTEMP_LO(a6)
! 173: bpl.b chklepos
! 174: cmp.l #$FFFFFFFF,FPTEMP_HI(a6)
! 175: beq.b fixlong
! 176: bra.w store_max
! 177: chklepos:
! 178: tst.l FPTEMP_HI(a6)
! 179: beq.b fixlong
! 180: bra.w store_max
! 181:
! 182: operr_word:
! 183: moveq.l #2,d1 ;write size to d1
! 184: move.b STAG(a6),d0 ;test stag for nan
! 185: andi.b #$e0,d0 ;clr all but tag
! 186: cmpi.b #$60,d0 ;check for nan
! 187: beq.w operr_nan
! 188: cmpi.l #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
! 189: bne.b chkwerr ;if not equal, check for incorrect operr
! 190: bsr check_upper ;check if exp and ms mant are special
! 191: tst.l d0
! 192: bne.b chkwerr ;if d0 is true, check for incorrect operr
! 193: move.l #$80000000,d0 ;store special case result
! 194: bsr operr_store
! 195: bra.w not_enabled ;clean and exit
! 196: *
! 197: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
! 198: *
! 199: chkwerr:
! 200: move.w FPTEMP_EX(a6),d0
! 201: and.w #$7FFF,d0 ;ignore sign bit
! 202: cmp.w #$3FFE,d0 ;this is the only possible exponent value
! 203: bne.b store_max
! 204: move.l FPTEMP_LO(a6),d0
! 205: swap d0
! 206: bsr operr_store
! 207: bra.w not_enabled
! 208:
! 209: operr_byte:
! 210: moveq.l #1,d1 ;write size to d1
! 211: move.b STAG(a6),d0 ;test stag for nan
! 212: andi.b #$e0,d0 ;clr all but tag
! 213: cmpi.b #$60,d0 ;check for nan
! 214: beq.b operr_nan
! 215: cmpi.l #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
! 216: bne.b chkberr ;if not equal, check for incorrect operr
! 217: bsr check_upper ;check if exp and ms mant are special
! 218: tst.l d0
! 219: bne.b chkberr ;if d0 is true, check for incorrect operr
! 220: move.l #$80000000,d0 ;store special case result
! 221: bsr operr_store
! 222: bra.w not_enabled ;clean and exit
! 223: *
! 224: * CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
! 225: *
! 226: chkberr:
! 227: move.w FPTEMP_EX(a6),d0
! 228: and.w #$7FFF,d0 ;ignore sign bit
! 229: cmp.w #$3FFE,d0 ;this is the only possible exponent value
! 230: bne.b store_max
! 231: move.l FPTEMP_LO(a6),d0
! 232: asl.l #8,d0
! 233: swap d0
! 234: bsr operr_store
! 235: bra.w not_enabled
! 236:
! 237: *
! 238: * This operr condition is not of the special case. Set operr
! 239: * and aiop and write the portion of the nan to memory for the
! 240: * given size.
! 241: *
! 242: operr_nan:
! 243: or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
! 244:
! 245: move.l ETEMP_HI(a6),d0 ;output will be from upper 32 bits
! 246: bsr operr_store
! 247: bra end_operr
! 248: *
! 249: * Store_max loads the max pos or negative for the size, sets
! 250: * the operr and aiop bits, and clears inex and ainex, incorrectly
! 251: * set by the 040.
! 252: *
! 253: store_max:
! 254: or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop
! 255: bclr.b #inex2_bit,FPSR_EXCEPT(a6)
! 256: bclr.b #ainex_bit,FPSR_AEXCEPT(a6)
! 257: fmove.l #0,FPSR
! 258:
! 259: tst.w FPTEMP_EX(a6) ;check sign
! 260: blt.b load_neg
! 261: move.l #$7fffffff,d0
! 262: bsr operr_store
! 263: bra end_operr
! 264: load_neg:
! 265: move.l #$80000000,d0
! 266: bsr operr_store
! 267: bra end_operr
! 268:
! 269: *
! 270: * This routine stores the data in d0, for the given size in d1,
! 271: * to memory or data register as required. A read of the fline
! 272: * is required to determine the destination.
! 273: *
! 274: operr_store:
! 275: move.l d0,L_SCR1(a6) ;move write data to L_SCR1
! 276: move.l d1,-(a7) ;save register size
! 277: bsr.l get_fline ;fline returned in d0
! 278: move.l (a7)+,d1
! 279: bftst d0{26:3} ;if mode is zero, dest is Dn
! 280: bne.b dest_mem
! 281: *
! 282: * Destination is Dn. Get register number from d0. Data is on
! 283: * the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
! 284: *
! 285: andi.l #7,d0 ;isolate register number
! 286: cmpi.l #4,d1
! 287: beq.b op_long ;the most frequent case
! 288: cmpi.l #2,d1
! 289: bne.b op_con
! 290: or.l #8,d0
! 291: bra.b op_con
! 292: op_long:
! 293: or.l #$10,d0
! 294: op_con:
! 295: move.l d0,d1 ;format size:reg for reg_dest
! 296: bra.l reg_dest ;call to reg_dest returns to caller
! 297: * ;of operr_store
! 298: *
! 299: * Destination is memory. Get <ea> from integer exception frame
! 300: * and call mem_write.
! 301: *
! 302: dest_mem:
! 303: lea.l L_SCR1(a6),a0 ;put ptr to write data in a0
! 304: move.l EXC_EA(a6),a1 ;put user destination address in a1
! 305: move.l d1,d0 ;put size in d0
! 306: bsr.l mem_write
! 307: rts
! 308: *
! 309: * Check the exponent for $c000 and the upper 32 bits of the
! 310: * mantissa for $ffffffff. If both are true, return d0 clr
! 311: * and store the lower n bits of the least lword of FPTEMP
! 312: * to d0 for write out. If not, it is a real operr, and set d0.
! 313: *
! 314: check_upper:
! 315: cmpi.l #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
! 316: bne.b true_operr ;if not all 1's then was true operr
! 317: cmpi.w #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
! 318: beq.b not_true_operr ;branch if not true operr
! 319: cmpi.w #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
! 320: beq.b not_true_operr ;branch if not true operr
! 321: true_operr:
! 322: move.l #1,d0 ;signal real operr
! 323: rts
! 324: not_true_operr:
! 325: clr.l d0 ;signal no real operr
! 326: rts
! 327:
! 328: *
! 329: * End_operr tests for operr enabled. If not, it cleans up the stack
! 330: * and does an rte. If enabled, it cleans up the stack and branches
! 331: * to the kernel operr handler with only the integer exception
! 332: * frame on the stack and the fpu in the original exceptional state
! 333: * with correct data written to the destination.
! 334: *
! 335: end_operr:
! 336: btst.b #operr_bit,FPCR_ENABLE(a6)
! 337: beq.b not_enabled
! 338: enabled:
! 339: movem.l USER_DA(a6),d0-d1/a0-a1
! 340: fmovem.x USER_FP0(a6),fp0-fp3
! 341: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 342: frestore (a7)+
! 343: unlk a6
! 344: bra.l real_operr
! 345:
! 346: not_enabled:
! 347: *
! 348: * It is possible to have either inex2 or inex1 exceptions with the
! 349: * operr. If the inex enable bit is set in the FPCR, and either
! 350: * inex2 or inex1 occurred, we must clean up and branch to the
! 351: * real inex handler.
! 352: *
! 353: ck_inex:
! 354: move.b FPCR_ENABLE(a6),d0
! 355: and.b FPSR_EXCEPT(a6),d0
! 356: andi.b #$3,d0
! 357: beq.w operr_exit
! 358: *
! 359: * Inexact enabled and reported, and we must take an inexact exception.
! 360: *
! 361: take_inex:
! 362: move.b #INEX_VEC,EXC_VEC+1(a6)
! 363: move.l USER_FPSR(a6),FPSR_SHADOW(a6)
! 364: or.l #sx_mask,E_BYTE(a6)
! 365: movem.l USER_DA(a6),d0-d1/a0-a1
! 366: fmovem.x USER_FP0(a6),fp0-fp3
! 367: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 368: frestore (a7)+
! 369: unlk a6
! 370: bra.l real_inex
! 371: *
! 372: * Since operr is only an E1 exception, there is no need to frestore
! 373: * any state back to the fpu.
! 374: *
! 375: operr_exit:
! 376: movem.l USER_DA(a6),d0-d1/a0-a1
! 377: fmovem.x USER_FP0(a6),fp0-fp3
! 378: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 379: unlk a6
! 380: bra.l fpsp_done
! 381:
! 382: end
CVSweb