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