^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) | res_func.sa 3.9 7/29/91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) | Normalizes denormalized numbers if necessary and updates the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) | stack frame. The function is then restored back into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) | machine and the 040 completes the operation. This routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) | is only used by the unsupported data type/format handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) | (Exception vector 55).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) | For packed move out (fmove.p fpm,<ea>) the operation is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) | completed here; data is packed and moved to user memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) | The stack is restored to the 040 only in the case of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) | reportable exception in the conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) | Copyright (C) Motorola, Inc. 1990
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) | All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) | For details on the license for this file, please see the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) | file, README, in this same directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) RES_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) |section 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "fpsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) sp_bnds: .short 0x3f81,0x407e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .short 0x3f6a,0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) dp_bnds: .short 0x3c01,0x43fe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .short 0x3bcd,0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) |xref mem_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) |xref bindec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) |xref get_fline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) |xref round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) |xref denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) |xref dest_ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) |xref dest_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) |xref dest_sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) |xref unf_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) |xref nrm_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) |xref dnrm_lp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) |xref ovf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) |xref reg_dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) |xref t_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) |xref t_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .global res_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .global p_move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) res_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) clrb DNRM_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) clrb RES_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) clrb CU_ONLY(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) tstb DY_MO_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) beqs monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) dyadic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) btstb #7,DTAG(%a6) |if dop = norm=000, zero=001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) | ;inf=010 or nan=011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) beqs monadic |then branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) | ;else denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) | HANDLE DESTINATION DENORM HERE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) | ;set dtag to norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) | ;write the tag & fpte15 to the fstack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) leal FPTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) bsr nrm_set |normalize number (exp will go negative)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) beqs dpos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dpos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bfclr DTAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) bsetb #4,DTAG(%a6) |set FPTE15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) orb #0x0f,DNRM_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) monadic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) leal ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) btstb #direction_bit,CMDREG1B(%a6) |check direction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bne opclass3 |it is a mv out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) | At this point, only opclass 0 and 2 possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) btstb #7,STAG(%a6) |if sop = norm=000, zero=001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) | ;inf=010 or nan=011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) bne mon_dnrm |else denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bne normal |require normalization of denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) | At this point:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) | monadic instructions: fabs = $18 fneg = $1a ftst = $3a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) | fmove = $00 fsmove = $40 fdmove = $44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) | fsqrt = $05* fssqrt = $41 fdsqrt = $45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) | (*fsqrt reencoded to $05)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) movew CMDREG1B(%a6),%d0 |get command register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) andil #0x7f,%d0 |strip to only command word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) | fdsqrt are possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) btstl #0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) bne normal |weed out fsqrt instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) | cu_norm handles fmove in instructions with normalized inputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) | The routine round is used to correctly round the input for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) | destination precision and mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) cu_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) st CU_ONLY(%a6) |set cu-only inst flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) andib #0x3b,%d0 |isolate bits to select inst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) tstb %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) beql cu_nmove |if zero, it is an fmove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) cmpib #0x18,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) beql cu_nabs |if $18, it is fabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) cmpib #0x1a,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) beql cu_nneg |if $1a, it is fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) | Inst is ftst. Check the source operand and set the cc's accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) | No write is done, so simply rts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) cu_ntst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) movew LOCAL_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) bclrl #15,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) beqs cu_ntpo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) orl #neg_mask,USER_FPSR(%a6) |set N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) cu_ntpo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) cmpiw #0x7fff,%d0 |test for inf/nan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) bnes cu_ntcz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) tstl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) bnes cu_ntn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bnes cu_ntn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) orl #inf_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) cu_ntn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) orl #nan_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) | ;snan handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) cu_ntcz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) tstl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) bnel cu_ntsx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bnel cu_ntsx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cu_ntsx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) | Inst is fabs. Execute the absolute value function on the input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) | Branch to the fmove code. If the operand is NaN, do nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cu_nabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) moveb STAG(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) btstl #5,%d0 |test for NaN or zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bne wr_etemp |if either, simply write it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) bclrb #7,LOCAL_EX(%a0) |do abs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bras cu_nmove |fmove code will finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) | Inst is fneg. Execute the negate value function on the input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) | Fall though to the fmove code. If the operand is NaN, do nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) cu_nneg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) moveb STAG(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) btstl #5,%d0 |test for NaN or zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) bne wr_etemp |if either, simply write it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) bchgb #7,LOCAL_EX(%a0) |do neg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) | Inst is fmove. This code also handles all result writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) | If bit 2 is set, round is forced to double. If it is clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) | and bit 6 is set, round is forced to single. If both are clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) | the round precision is found in the fpcr. If the rounding precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) | is double or single, round the result before the write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) cu_nmove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) moveb STAG(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) andib #0xe0,%d0 |isolate stag bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bne wr_etemp |if not norm, simply write it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) btstb #2,CMDREG1B+1(%a6) |check for rd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) bne cu_nmrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) btstb #6,CMDREG1B+1(%a6) |check for rs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) bne cu_nmrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) | The move or operation is not with forced precision. Test for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) | nan or inf as the input; if so, simply write it to FPn. Use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) | FPCR_MODE byte to get rounding on norms and zeros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) cu_nmnr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) bfextu FPCR_MODE(%a6){#0:#2},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tstb %d0 |check for extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) beq cu_wrexn |if so, just write result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) cmpib #1,%d0 |check for single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) beq cu_nmrs |fall through to double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) | The move is fdmove or round precision is double.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) cu_nmrd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) movel #2,%d0 |set up the size for denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) movew LOCAL_EX(%a0),%d1 |compare exponent to double threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) andw #0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) cmpw #0x3c01,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) bls cu_nunfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) orl #0x00020000,%d1 |or in rprec (double)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) clrl %d0 |clear g,r,s for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bclrb #sign_bit,LOCAL_EX(%a0) |convert to internal format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) bsrl round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bfclr LOCAL_SGN(%a0){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) beqs cu_nmrdc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) cu_nmrdc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) movew LOCAL_EX(%a0),%d1 |check for overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) andw #0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cmpw #0x43ff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) bge cu_novfl |take care of overflow case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) bra cu_wrexn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) | The move is fsmove or round precision is single.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) cu_nmrs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) movel #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) movew LOCAL_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) andw #0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cmpw #0x3f81,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) bls cu_nunfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bfextu FPCR_MODE(%a6){#2:#2},%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) orl #0x00010000,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) clrl %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) bsrl round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) bfclr LOCAL_SGN(%a0){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) beqs cu_nmrsc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) cu_nmrsc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) movew LOCAL_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) andw #0x7FFF,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) cmpw #0x407f,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) blt cu_wrexn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) | The operand is above precision boundaries. Use t_ovfl to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) | generate the correct value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) cu_novfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bsr t_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) bra cu_wrexn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) | The operand is below precision boundaries. Use denorm to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) | generate the correct value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) cu_nunfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bsr denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) beqs cu_nucont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) cu_nucont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) bfextu FPCR_MODE(%a6){#2:#2},%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) btstb #2,CMDREG1B+1(%a6) |check for rd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) bne inst_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) btstb #6,CMDREG1B+1(%a6) |check for rs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) bne inst_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) moveb FPCR_MODE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) lsrb #6,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) bra inst_sd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) inst_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) orl #0x00020000,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) bra inst_sd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) inst_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) orl #0x00010000,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) inst_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) bsrl round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) bfclr LOCAL_SGN(%a0){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) beqs cu_nuflp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) cu_nuflp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) btstb #inex2_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) beqs cu_nuninx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) orl #aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) cu_nuninx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tstl LOCAL_HI(%a0) |test for zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bnes cu_nunzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) bnes cu_nunzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) | The mantissa is zero from the denorm loop. Check sign and rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) | to see if rounding should have occurred which would leave the lsb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) andil #0x30,%d0 |isolate rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) cmpil #0x20,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) blts cu_nzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) bnes cu_nrp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) cu_nrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) tstw LOCAL_EX(%a0) |if positive, set lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) bges cu_nzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) btstb #7,FPCR_MODE(%a6) |check for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) beqs cu_nincs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) bras cu_nincd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cu_nrp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) tstw LOCAL_EX(%a0) |if positive, set lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) blts cu_nzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) btstb #7,FPCR_MODE(%a6) |check for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) beqs cu_nincs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) cu_nincd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) orl #0x800,LOCAL_LO(%a0) |inc for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) bra cu_nunzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) cu_nincs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) orl #0x100,LOCAL_HI(%a0) |inc for single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) bra cu_nunzro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) cu_nzro:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) moveb STAG(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) andib #0xe0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) cmpib #0x40,%d0 |check if input was tagged zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) beqs cu_numv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) cu_nunzro:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) orl #unfl_mask,USER_FPSR(%a6) |set unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) cu_numv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) movel (%a0),ETEMP(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) movel 4(%a0),ETEMP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) movel 8(%a0),ETEMP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) | Write the result to memory, setting the fpsr cc bits. NaN and Inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) | bypass cu_wrexn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) cu_wrexn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) tstw LOCAL_EX(%a0) |test for zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) beqs cu_wrzero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cmpw #0x8000,LOCAL_EX(%a0) |test for zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bnes cu_wreon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) cu_wrzero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) orl #z_mask,USER_FPSR(%a6) |set Z bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) cu_wreon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) tstw LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) bpl wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) | HANDLE SOURCE DENORM HERE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) | ;clear denorm stag to norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) | ;write the new tag & ete15 to the fstack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mon_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) | At this point, check for the cases in which normalizing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) | denorm produces incorrect results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) bnes nrm_src |require normalization of denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) | At this point:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) | monadic instructions: fabs = $18 fneg = $1a ftst = $3a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) | fmove = $00 fsmove = $40 fdmove = $44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) | fsqrt = $05* fssqrt = $41 fdsqrt = $45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) | (*fsqrt reencoded to $05)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) movew CMDREG1B(%a6),%d0 |get command register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) andil #0x7f,%d0 |strip to only command word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) | fdsqrt are possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) btstl #0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) bnes nrm_src |weed out fsqrt instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) st CU_ONLY(%a6) |set cu-only inst flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) bra cu_dnrm |fmove, fabs, fneg, ftst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) | ;cases go to cu_dnrm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) nrm_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) bsr nrm_set |normalize number (exponent will go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) | ; negative)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) beqs spos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) bsetb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) spos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) bfclr STAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) bsetb #4,STAG(%a6) |set ETE15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) orb #0xf0,DNRM_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) tstb DNRM_FLG(%a6) |check if any of the ops were denorms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) bne ck_wrap |if so, check if it is a potential
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) | ;wrap-around case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) fix_stk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) moveb #0xfe,CU_SAVEPC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) st RES_FLG(%a6) |indicate that a restore is needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) | cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) | ftst) completely in software without an frestore to the 040.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) cu_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) st CU_ONLY(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) andib #0x3b,%d0 |isolate bits to select inst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) tstb %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) beql cu_dmove |if zero, it is an fmove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) cmpib #0x18,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) beql cu_dabs |if $18, it is fabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cmpib #0x1a,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) beql cu_dneg |if $1a, it is fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) | Inst is ftst. Check the source operand and set the cc's accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) | No write is done, so simply rts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) cu_dtst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) movew LOCAL_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) bclrl #15,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) beqs cu_dtpo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) orl #neg_mask,USER_FPSR(%a6) |set N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) cu_dtpo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) cmpiw #0x7fff,%d0 |test for inf/nan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) bnes cu_dtcz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) tstl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) bnes cu_dtn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) bnes cu_dtn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) orl #inf_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) cu_dtn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) orl #nan_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) | ;snan handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) cu_dtcz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) tstl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) bnel cu_dtsx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) bnel cu_dtsx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) cu_dtsx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) | Inst is fabs. Execute the absolute value function on the input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) | Branch to the fmove code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) cu_dabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) bclrb #7,LOCAL_EX(%a0) |do abs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) bras cu_dmove |fmove code will finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) | Inst is fneg. Execute the negate value function on the input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) | Fall though to the fmove code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) cu_dneg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) bchgb #7,LOCAL_EX(%a0) |do neg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) | Inst is fmove. This code also handles all result writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) | If bit 2 is set, round is forced to double. If it is clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) | and bit 6 is set, round is forced to single. If both are clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) | the round precision is found in the fpcr. If the rounding precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) | is double or single, the result is zero, and the mode is checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) | to determine if the lsb of the result should be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) cu_dmove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) btstb #2,CMDREG1B+1(%a6) |check for rd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) bne cu_dmrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) btstb #6,CMDREG1B+1(%a6) |check for rs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) bne cu_dmrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) | The move or operation is not with forced precision. Use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) | FPCR_MODE byte to get rounding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) cu_dmnr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) bfextu FPCR_MODE(%a6){#0:#2},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tstb %d0 |check for extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) beq cu_wrexd |if so, just write result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cmpib #1,%d0 |check for single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) beq cu_dmrs |fall through to double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) | The move is fdmove or round precision is double. Result is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) | Check rmode for rp or rm and set lsb accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) cu_dmrd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) tstw LOCAL_EX(%a0) |check sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) blts cu_dmdn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) cmpib #3,%d1 |check for rp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) bne cu_dpd |load double pos zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) bra cu_dpdr |load double pos zero w/lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) cu_dmdn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) cmpib #2,%d1 |check for rm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) bne cu_dnd |load double neg zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) bra cu_dndr |load double neg zero w/lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) | The move is fsmove or round precision is single. Result is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) | Check for rp or rm and set lsb accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) cu_dmrs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) tstw LOCAL_EX(%a0) |check sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) blts cu_dmsn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) cmpib #3,%d1 |check for rp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) bne cu_spd |load single pos zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) bra cu_spdr |load single pos zero w/lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cu_dmsn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) cmpib #2,%d1 |check for rm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) bne cu_snd |load single neg zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) bra cu_sndr |load single neg zero w/lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) | The precision is extended, so the result in etemp is correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) | Simply set unfl (not inex2 or aunfl) and write the result to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) | the correct fp register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) cu_wrexd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) orl #unfl_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) tstw LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) beq wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) | These routines write +/- zero in double format. The routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) | cu_dpdr and cu_dndr set the double lsb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) cu_dpd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) cu_dpdr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) movel #0x800,LOCAL_LO(%a0) |with lsb set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) cu_dnd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) cu_dndr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) movel #0x800,LOCAL_LO(%a0) |with lsb set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) | These routines write +/- zero in single format. The routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) | cu_dpdr and cu_dndr set the single lsb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) cu_spd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) cu_spdr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) movel #0x100,LOCAL_HI(%a0) |with lsb set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) cu_snd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) orl #z_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) cu_sndr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) movel #0x100,LOCAL_HI(%a0) |with lsb set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bra wr_etemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) | This code checks for 16-bit overflow conditions on dyadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) | operations which are not restorable into the floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) | unit and must be completed in software. Basically, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) | condition exists with a very large norm and a denorm. One
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) | of the operands must be denormalized to enter this code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) | Flags used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) | DY_MO_FLG contains 0 for monadic op, $ff for dyadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) | DNRM_FLG contains $00 for neither op denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) | $0f for the destination op denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) | $f0 for the source op denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) | $ff for both ops denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) | The wrap-around condition occurs for add, sub, div, and cmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) | when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) | abs(dest_exp - src_exp) >= $8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) | and for mul when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) | (dest_exp + src_exp) < $0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) | we must process the operation here if this case is true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) | The rts following the frcfpn routine is the exit from res_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) | for this condition. The restore flag (RES_FLG) is left clear.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) | No frestore is done unless an exception is to be reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) | For fadd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) | if(sign_of(dest) != sign_of(src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) | replace exponent of src with $3fff (keep sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) | use fpu to perform dest+new_src (user's rmode and X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) | clr sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) | else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) | set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) | call round with user's precision and mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) | move result to fpn and wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) | For fsub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) | if(sign_of(dest) == sign_of(src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) | replace exponent of src with $3fff (keep sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) | use fpu to perform dest+new_src (user's rmode and X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) | clr sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) | else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) | set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) | call round with user's precision and mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) | move result to fpn and wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) | For fdiv/fsgldiv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) | if(both operands are denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) | restore_to_fpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) | if(dest is norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) | force_ovf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) | else(dest is denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) | force_unf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) | For fcmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) | if(dest is norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) | N = sign_of(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) | else(dest is denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) | N = sign_of(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) | For fmul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) | if(both operands are denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) | force_unf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) | if((dest_exp + src_exp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) | force_unf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) | else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) | restore_to_fpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) | local equates:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) .set addcode,0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) .set subcode,0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .set mulcode,0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .set divcode,0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .set cmpcode,0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ck_wrap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) | tstb DY_MO_FLG(%a6) ;check for fsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) beq fix_stk |if zero, it is fsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) andiw #0x3b,%d0 |strip to command bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cmpiw #addcode,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) beq wrap_add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) cmpiw #subcode,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) beq wrap_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) cmpiw #mulcode,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) beq wrap_mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) cmpiw #cmpcode,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) beq wrap_cmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) | Inst is fdiv.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) wrap_div:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) beq fix_stk |restore to fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) | One of the ops is denormalized. Test for wrap condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) | and force the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) bnes div_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) div_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) bsrl ckinf_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) subl %d1,%d0 |subtract dest from src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cmpl #0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) clrb WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) movew ETEMP_EX(%a6),%d0 |find the sign of the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) movew FPTEMP_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) eorw %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) beq force_unf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) st WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) bra force_unf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ckinf_ns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) moveb STAG(%a6),%d0 |check source tag for inf or nan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) bra ck_in_com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ckinf_nd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) moveb DTAG(%a6),%d0 |check destination tag for inf or nan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ck_in_com:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) andib #0x60,%d0 |isolate tag bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) cmpb #0x40,%d0 |is it inf?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) beq nan_or_inf |not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) cmpb #0x60,%d0 |is it nan?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) beq nan_or_inf |yes, not wrap case?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) cmpb #0x20,%d0 |is it a zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) beq nan_or_inf |yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) clrl %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) rts |then ; it is either a zero of norm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) | ;check wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) nan_or_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) moveql #-1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) div_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) bsrl ckinf_nd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) subl %d1,%d0 |subtract src from dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) clrb WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) movew ETEMP_EX(%a6),%d0 |find the sign of the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) movew FPTEMP_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) eorw %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) beqs force_ovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) st WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) | This code handles the case of the instruction resulting in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) | an overflow condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) force_ovf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) orl #ovfl_inx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) leal WBTEMP(%a6),%a0 |point a0 to memory location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) btstl #6,%d0 |test for forced precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) beqs frcovf_fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) btstl #2,%d0 |check for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) bnes frcovf_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) movel #0x1,%d0 |inst is forced single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) bras frcovf_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) frcovf_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) movel #0x2,%d0 |inst is forced double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) bras frcovf_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) frcovf_fpcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) frcovf_rnd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) | The 881/882 does not set inex2 for the following case, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) | line is commented out to be compatible with 881/882
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) | tst.b %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) | beq.b frcovf_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) | or.l #inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) |frcovf_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) bsrl ovf_res |get correct result based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) | ;round precision/mode. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) | ;sets FPSR_CC correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) | ;returns in external format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) bfclr WBTEMP_SGN(%a6){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) beq frcfpn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) bra frcfpn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) | Inst is fadd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) wrap_add:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) beq fix_stk |restore to fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) | One of the ops is denormalized. Test for wrap condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) | and complete the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) bnes add_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) add_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) bsrl ckinf_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) subl %d1,%d0 |subtract dest from src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) bra add_wrap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) add_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) bsrl ckinf_nd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) subl %d1,%d0 |subtract src from dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) | Check the signs of the operands. If they are unlike, the fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) | can be used to add the norm and 1.0 with the sign of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) | denorm and it will correctly generate the result in extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) | precision. We can then call round with no sticky and the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) | will be correct for the user's rounding mode and precision. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) | the signs are the same, we call round with the sticky bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) | and the result will be correct for the user's rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) | precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) add_wrap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) movew ETEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) movew FPTEMP_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) eorw %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) beq add_same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) | The signs are unlike.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) bnes add_u_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) movew FPTEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) orw #0x3fff,%d0 |force the exponent to +/- 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) movew %d0,FPTEMP_EX(%a6) |in the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) fmovel %d0,%fpcr |set up users rmode and X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) fmovex ETEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) faddx FPTEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) fmovex %fp0,WBTEMP(%a6) |write result to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) clrl %d0 |force sticky to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) bclrb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) sne WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) beq frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) add_u_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) movew ETEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) orw #0x3fff,%d0 |force the exponent to +/- 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) movew %d0,ETEMP_EX(%a6) |in the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) fmovel %d0,%fpcr |set up users rmode and X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) fmovex ETEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) faddx FPTEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) fmovex %fp0,WBTEMP(%a6) |write result to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) clrl %d0 |force sticky to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bclrb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) sne WBTEMP_SGN(%a6) |use internal format for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) beq frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) | Signs are alike:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) add_same:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) bnes add_s_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) add_s_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) leal ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) movel #0x20000000,%d0 |set sticky for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) bclrb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) sne ETEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) beqs add_s_dclr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) bsetb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) add_s_dclr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) leal WBTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) movel ETEMP(%a6),(%a0) |write result to wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) movel ETEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) movel ETEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) tstw ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) bgt add_ckovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) bra add_ckovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) add_s_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) leal FPTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) movel #0x20000000,%d0 |set sticky for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) bclrb #sign_bit,FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) sne FPTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) beqs add_s_sclr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) bsetb #sign_bit,FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) add_s_sclr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) leal WBTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) movel FPTEMP(%a6),(%a0) |write result to wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) movel FPTEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) movel FPTEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) tstw FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) bgt add_ckovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) add_ckovf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) movew WBTEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) andiw #0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) cmpiw #0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) bne frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) | The result has overflowed to $7fff exponent. Set I, ovfl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) | and aovfl, and clr the mantissa (incorrectly set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) | round routine.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) clrl 4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) | Inst is fsub.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) wrap_sub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) beq fix_stk |restore to fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) | One of the ops is denormalized. Test for wrap condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) | and complete the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) bnes sub_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) sub_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) bsrl ckinf_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) subl %d1,%d0 |subtract src from dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) bra sub_wrap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) sub_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) bsrl ckinf_nd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) subl %d1,%d0 |subtract dest from src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) | Check the signs of the operands. If they are alike, the fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) | can be used to subtract from the norm 1.0 with the sign of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) | denorm and it will correctly generate the result in extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) | precision. We can then call round with no sticky and the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) | will be correct for the user's rounding mode and precision. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) | the signs are unlike, we call round with the sticky bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) | and the result will be correct for the user's rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) | precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) sub_wrap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) movew ETEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) movew FPTEMP_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) eorw %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) bne sub_diff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) | The signs are alike.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) bnes sub_u_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) movew FPTEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) orw #0x3fff,%d0 |force the exponent to +/- 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) movew %d0,FPTEMP_EX(%a6) |in the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) fmovel %d0,%fpcr |set up users rmode and X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) fmovex FPTEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) fsubx ETEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) fmovex %fp0,WBTEMP(%a6) |write result to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) clrl %d0 |force sticky to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) bclrb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) sne WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) beq frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) sub_u_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) movew ETEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) orw #0x3fff,%d0 |force the exponent to +/- 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) movew %d0,ETEMP_EX(%a6) |in the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) fmovel %d0,%fpcr |set up users rmode and X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) fmovex FPTEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) fsubx ETEMP(%a6),%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) fmovex %fp0,WBTEMP(%a6) |write result to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) clrl %d0 |force sticky to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) bclrb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) sne WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) beq frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) | Signs are unlike:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) sub_diff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) bnes sub_s_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) sub_s_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) leal ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) movel #0x20000000,%d0 |set sticky for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) | Since the dest is the denorm, the sign is the opposite of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) | norm sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) eoriw #0x8000,ETEMP_EX(%a6) |flip sign on result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) tstw ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) bgts sub_s_dwr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) sub_s_dwr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) bclrb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) sne ETEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) beqs sub_s_dclr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) bsetb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) sub_s_dclr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) leal WBTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) movel ETEMP(%a6),(%a0) |write result to wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) movel ETEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) movel ETEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) bra sub_ckovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) sub_s_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) leal FPTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) movel USER_FPCR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) andil #0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) lsrl #4,%d0 |put rmode in lower 2 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) movel USER_FPCR(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) andil #0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) lsrl #6,%d1 |put precision in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) orl %d0,%d1 |set up for round call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) movel #0x20000000,%d0 |set sticky for round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) bclrb #sign_bit,FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) sne FPTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) bsrl round |round result to users rmode & prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) beqs sub_s_sclr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) bsetb #sign_bit,FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) sub_s_sclr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) leal WBTEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) movel FPTEMP(%a6),(%a0) |write result to wbtemp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) movel FPTEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) movel FPTEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) tstw FPTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) bgt sub_ckovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) sub_ckovf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) movew WBTEMP_EX(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) andiw #0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) cmpiw #0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) bne frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) | The result has overflowed to $7fff exponent. Set I, ovfl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) | and aovfl, and clr the mantissa (incorrectly set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) | round routine.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) clrl 4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) bra frcfpnr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) | Inst is fcmp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) wrap_cmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) beq fix_stk |restore to fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) | One of the ops is denormalized. Test for wrap condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) | and complete the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) bnes cmp_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) cmp_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) bsrl ckinf_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) subl %d1,%d0 |subtract dest from src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) tstw ETEMP_EX(%a6) |set N to ~sign_of(src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) bge cmp_setn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) cmp_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) bsrl ckinf_nd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) subl %d1,%d0 |subtract src from dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) cmpl #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) blt fix_stk |if less, not wrap case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) tstw FPTEMP_EX(%a6) |set N to sign_of(dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) blt cmp_setn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) cmp_setn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) | Inst is fmul.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) wrap_mul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) beq force_unf |force an underflow (really!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) | One of the ops is denormalized. Test for wrap condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) | and complete the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) bnes mul_srcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) mul_destd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) bsrl ckinf_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) addl %d1,%d0 |subtract dest from src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) bgt fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) bra force_unf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) mul_srcd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) bsrl ckinf_nd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) bne fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) addl %d1,%d0 |subtract src from dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) bgt fix_stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) | This code handles the case of the instruction resulting in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) | an underflow condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) force_unf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) orl #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) clrb WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) movew ETEMP_EX(%a6),%d0 |find the sign of the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) movew FPTEMP_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) eorw %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) andiw #0x8000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) beqs frcunfcont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) st WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) frcunfcont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) lea WBTEMP(%a6),%a0 |point a0 to memory location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) btstl #6,%d0 |test for forced precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) beqs frcunf_fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) btstl #2,%d0 |check for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) bnes frcunf_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) movel #0x1,%d0 |inst is forced single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) bras frcunf_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) frcunf_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) movel #0x2,%d0 |inst is forced double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) bras frcunf_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) frcunf_fpcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) frcunf_rnd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) bsrl unf_sub |get correct result based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) | ;round precision/mode. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) | ;sets FPSR_CC correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) beqs frcfpn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) bra frcfpn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) | Write the result to the user's fpn. All results must be HUGE to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) | written; otherwise the results would have overflowed or underflowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) | If the rounding precision is single or double, the ovf_res routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) | is needed to correctly supply the max value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) frcfpnr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) btstl #6,%d0 |test for forced precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) beqs frcfpn_fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) btstl #2,%d0 |check for double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) bnes frcfpn_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) movel #0x1,%d0 |inst is forced single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) bras frcfpn_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) frcfpn_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) movel #0x2,%d0 |inst is forced double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) bras frcfpn_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) frcfpn_fpcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) tstb %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) beqs frcfpn |if extended, write what you got
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) frcfpn_rnd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) bclrb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) sne WBTEMP_SGN(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) bsrl ovf_res |get correct result based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) | ;round precision/mode. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) | ;sets FPSR_CC correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) beqs frcfpn_clr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) frcfpn_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) orl #ovfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) | Perform the write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) frcfpn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) cmpib #3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) bles frc0123 |check if dest is fp0-fp3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) movel #7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) subl %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) clrl %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) bsetl %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) fmovemx WBTEMP(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) frc0123:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) cmpib #0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) beqs frc0_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) cmpib #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) beqs frc1_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) cmpib #2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) beqs frc2_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) frc3_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) movel WBTEMP_EX(%a6),USER_FP3(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) movel WBTEMP_HI(%a6),USER_FP3+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) movel WBTEMP_LO(%a6),USER_FP3+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) frc2_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) movel WBTEMP_EX(%a6),USER_FP2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) movel WBTEMP_HI(%a6),USER_FP2+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) movel WBTEMP_LO(%a6),USER_FP2+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) frc1_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) movel WBTEMP_EX(%a6),USER_FP1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) movel WBTEMP_HI(%a6),USER_FP1+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) movel WBTEMP_LO(%a6),USER_FP1+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) frc0_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) movel WBTEMP_EX(%a6),USER_FP0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) movel WBTEMP_HI(%a6),USER_FP0+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) movel WBTEMP_LO(%a6),USER_FP0+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) | Write etemp to fpn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) | A check is made on enabled and signalled snan exceptions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) | and the destination is not overwritten if this condition exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) | This code is designed to make fmoveins of unsupported data types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) | faster.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) wr_etemp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) btstb #snan_bit,FPSR_EXCEPT(%a6) |if snan is set, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) beqs fmoveinc |enabled, force restore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) btstb #snan_bit,FPCR_ENABLE(%a6) |and don't overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) beqs fmoveinc |the dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) | ;snan handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) tstb ETEMP(%a6) |check for negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) blts snan_neg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) snan_neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) orl #neg_bit,USER_FPSR(%a6) |snan is negative; set N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) fmoveinc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) moveb STAG(%a6),%d0 |check if stag is inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) andib #0xe0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) cmpib #0x40,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) bnes fminc_cnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) orl #inf_mask,USER_FPSR(%a6) |if inf, nothing yet has set I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) tstw LOCAL_EX(%a0) |check sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) bges fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) bra fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) fminc_cnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) cmpib #0x60,%d0 |check if stag is NaN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) bnes fminc_czero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) orl #nan_mask,USER_FPSR(%a6) |if nan, nothing yet has set NaN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) | ;snan handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) tstw LOCAL_EX(%a0) |check sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) bges fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) bra fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) fminc_czero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) cmpib #0x20,%d0 |check if zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) bnes fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) orl #z_mask,USER_FPSR(%a6) |if zero, set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) tstw LOCAL_EX(%a0) |check sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) bges fminc_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) orl #neg_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) fminc_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) cmpib #3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) bles fp0123 |check if dest is fp0-fp3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) movel #7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) subl %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) clrl %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) bsetl %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) fmovemx ETEMP(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) fp0123:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) cmpib #0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) beqs fp0_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) cmpib #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) beqs fp1_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) cmpib #2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) beqs fp2_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) fp3_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) movel ETEMP_EX(%a6),USER_FP3(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) movel ETEMP_HI(%a6),USER_FP3+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) movel ETEMP_LO(%a6),USER_FP3+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) fp2_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) movel ETEMP_EX(%a6),USER_FP2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) movel ETEMP_HI(%a6),USER_FP2+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) movel ETEMP_LO(%a6),USER_FP2+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) fp1_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) movel ETEMP_EX(%a6),USER_FP1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) movel ETEMP_HI(%a6),USER_FP1+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) movel ETEMP_LO(%a6),USER_FP1+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) fp0_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) movel ETEMP_EX(%a6),USER_FP0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) movel ETEMP_HI(%a6),USER_FP0+4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) movel ETEMP_LO(%a6),USER_FP0+8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) opclass3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) st CU_ONLY(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) movew CMDREG1B(%a6),%d0 |check if packed moveout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) andiw #0x0c00,%d0 |isolate last 2 bits of size field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) cmpiw #0x0c00,%d0 |if size is 011 or 111, it is packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) beq pack_out |else it is norm or denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) bra mv_out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) | MOVE OUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) mv_tbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) .long li
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) .long sgp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) .long xp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) .long mvout_end |should never be taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) .long wi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) .long dp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) .long bi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) .long mvout_end |should never be taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) mv_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) bfextu CMDREG1B(%a6){#3:#3},%d1 |put source specifier in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) leal mv_tbl,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) movel %a0@(%d1:l:4),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) jmp (%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) | This exit is for move-out to memory. The aunfl bit is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) | set if the result is inex and unfl is signalled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) mvout_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) btstb #inex2_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) beqs no_aufl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) btstb #unfl_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) beqs no_aufl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) no_aufl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) fmovel #0,%FPSR |clear any cc bits from res_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) | Return ETEMP to extended format from internal extended format so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) | that gen_except will have a correctly signed value for ovfl/unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) | handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) bfclr ETEMP_SGN(%a6){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) beqs mvout_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) bsetb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) mvout_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) | This exit is for move-out to int register. The aunfl bit is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) | not set in any case for this move.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) mvouti_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) clrw NMNEXC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) bclrb #E1,E_BYTE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) fmovel #0,%FPSR |clear any cc bits from res_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) | Return ETEMP to extended format from internal extended format so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) | that gen_except will have a correctly signed value for ovfl/unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) | handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) bfclr ETEMP_SGN(%a6){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) beqs mvouti_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) bsetb #sign_bit,ETEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) mvouti_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) | li is used to handle a long integer source specifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) li:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) moveql #4,%d0 |set byte count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) bne int_dnrm |if so, branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) fmovemx ETEMP(%a6),%fp0-%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) fcmpd #0x41dfffffffc00000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) | 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) fbge lo_plrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) fcmpd #0xc1e0000000000000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) | c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) fble lo_nlrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) | at this point, the answer is between the largest pos and neg values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) movel USER_FPCR(%a6),%d1 |use user's rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) andil #0x30,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) fmovel %d1,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) fmovel %fp0,L_SCR1(%a6) |let the 040 perform conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) bra int_wrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) lo_plrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) movel #0x7fffffff,L_SCR1(%a6) |answer is largest positive int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) fcmpd #0x41dfffffffe00000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) | 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) fbge int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) lo_nlrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) movel #0x80000000,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) fcmpd #0xc1e0000000100000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) | c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) fblt int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) | wi is used to handle a word integer source specifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) wi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) moveql #2,%d0 |set byte count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) bne int_dnrm |branch if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) fmovemx ETEMP(%a6),%fp0-%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) fcmps #0x46fffe00,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) | 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) fbge wo_plrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) fcmps #0xc7000000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) | c7000000 in sgl prec = c00e00008000000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) fble wo_nlrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) | at this point, the answer is between the largest pos and neg values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) movel USER_FPCR(%a6),%d1 |use user's rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) andil #0x30,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) fmovel %d1,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) fmovew %fp0,L_SCR1(%a6) |let the 040 perform conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) bra int_wrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) wo_plrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) movew #0x7fff,L_SCR1(%a6) |answer is largest positive int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) fcmps #0x46ffff00,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) | 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) fbge int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) wo_nlrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) movew #0x8000,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) fcmps #0xc7000080,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) | c7000080 in sgl prec = c00e00008000800000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) fblt int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) | bi is used to handle a byte integer source specifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) bi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) moveql #1,%d0 |set byte count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) bne int_dnrm |branch if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) fmovemx ETEMP(%a6),%fp0-%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) fcmps #0x42fe0000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) | 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) fbge by_plrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) fcmps #0xc3000000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) | c3000000 in sgl prec = c00600008000000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) fble by_nlrg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) | at this point, the answer is between the largest pos and neg values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) movel USER_FPCR(%a6),%d1 |use user's rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) andil #0x30,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) fmovel %d1,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) fmoveb %fp0,L_SCR1(%a6) |let the 040 perform conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) fmovel %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) bra int_wrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) by_plrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) moveb #0x7f,L_SCR1(%a6) |answer is largest positive int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) fcmps #0x42ff0000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) | 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) fbge int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) by_nlrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) moveb #0x80,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) fbeq int_wrt |exact answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) fcmps #0xc3008000,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) | c3008000 in sgl prec = c00600008080000000000000 in ext prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) fblt int_operr |set operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) bra int_inx |set inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) | Common integer routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) | int_drnrm---account for possible nonzero result for round up with positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) | operand and round down for negative answer. In the first case (result = 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) | byte-width (store in d0) of result must be honored. In the second case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) | -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) int_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) movel #0,L_SCR1(%a6) | initialize result to 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) bfextu FPCR_MODE(%a6){#2:#2},%d1 | d1 is the rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) cmpb #2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) bmis int_inx | if RN or RZ, done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) bnes int_rp | if RP, continue below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) tstw ETEMP(%a6) | RM: store -1 in L_SCR1 if src is negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) bpls int_inx | otherwise result is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) movel #-1,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) bras int_inx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) int_rp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) tstw ETEMP(%a6) | RP: store +1 of proper width in L_SCR1 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) | ; source is greater than 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) bmis int_inx | otherwise, result is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) lea L_SCR1(%a6),%a1 | a1 is address of L_SCR1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) addal %d0,%a1 | offset by destination width -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) subal #1,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) bsetb #0,(%a1) | set low bit at a1 address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) int_inx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) oril #inx2a_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) bras int_wrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) int_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) fmovemx %fp0-%fp0,FPTEMP(%a6) |FPTEMP must contain the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) | ;precision source that needs to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) | ;converted to integer this is required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) | ;if the operr exception is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) | ;set operr/aiop (no inex2 on int ovfl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) oril #opaop_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) | ;fall through to perform int_wrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) int_wrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) movel EXC_EA(%a6),%a1 |load destination address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) tstl %a1 |check to see if it is a dest register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) beqs wrt_dn |write data register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) lea L_SCR1(%a6),%a0 |point to supervisor source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) bsrl mem_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) bra mvouti_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) wrt_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) movel %d0,-(%sp) |d0 currently contains the size to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) bsrl get_fline |get_fline returns Dn in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) andiw #0x7,%d0 |isolate register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) movel (%sp)+,%d1 |get size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) cmpil #4,%d1 |most frequent case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) beqs sz_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) cmpil #2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) bnes sz_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) orl #8,%d0 |add 'word' size to register#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) bras sz_con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) sz_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) orl #0x10,%d0 |add 'long' size to register#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) sz_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) movel %d0,%d1 |reg_dest expects size:reg in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) bsrl reg_dest |load proper data register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) bra mvouti_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) xp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) lea ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) bne xdnrm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) clrl %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) bras do_fp |do normal case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) sgp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) lea ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) bne sp_catas |branch if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) movew LOCAL_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) lea sp_bnds,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) cmpw (%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) blt sp_under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) cmpw 2(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) bgt sp_over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) movel #1,%d0 |set destination format to single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) bras do_fp |do normal case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) dp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) lea ETEMP(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) bclrb #sign_bit,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) sne LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) btstb #7,STAG(%a6) |check for extended denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) bne dp_catas |branch if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) movew LOCAL_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) lea dp_bnds,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) cmpw (%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) blt dp_under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) cmpw 2(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) bgt dp_over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) movel #2,%d0 |set destination format to double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) | ;fall through to do_fp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) do_fp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) bfextu FPCR_MODE(%a6){#2:#2},%d1 |rnd mode in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) swap %d0 |rnd prec in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) addl %d0,%d1 |d1 has PREC/MODE info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) clrl %d0 |clear g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) bsrl round |round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) movel %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) movel EXC_EA(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) bfextu CMDREG1B(%a6){#3:#3},%d1 |extract destination format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) | ;at this point only the dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) | ;formats sgl, dbl, ext are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) | ;possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) cmpb #2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) bgts ddbl |double=5, extended=2, single=1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) bnes dsgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) | ;fall through to dext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) dext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) bsrl dest_ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) dsgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) bsrl dest_sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) ddbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) bsrl dest_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) | Handle possible denorm or catastrophic underflow cases here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) xdnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) bsr set_xop |initialize WBTEMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) movel %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) movel EXC_EA(%a6),%a0 |a0 has the destination pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) bsrl dest_ext |store to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) bsetb #unfl_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) sp_under:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) bsetb #etemp15_bit,STAG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) cmpw 4(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) blts sp_catas |catastrophic underflow case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) movel #1,%d0 |load in round precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) movel #sgl_thresh,%d1 |load in single denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) bsrl dpspdnrm |expects d1 to have the proper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) | ;denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) bsrl dest_sgl |stores value to destination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) bsetb #unfl_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) bra mvout_end |exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) dp_under:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) bsetb #etemp15_bit,STAG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) cmpw 4(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) blts dp_catas |catastrophic underflow case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) movel #dbl_thresh,%d1 |load in double precision threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) movel #2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) bsrl dpspdnrm |expects d1 to have proper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) | ;denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) | ;expects d0 to have round precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) bsrl dest_dbl |store value to destination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) bsetb #unfl_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) bra mvout_end |exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) | Handle catastrophic underflow cases here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) sp_catas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) | Temp fix for z bit set in unf_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) movel USER_FPSR(%a6),-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) movel #1,%d0 |set round precision to sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) bsrl unf_sub |a0 points to result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) movel (%a7)+,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) movel #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) subw %d0,LOCAL_EX(%a0) |account for difference between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) | ;denorm/norm bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) movel %a0,%a1 |a1 has the operand input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) movel EXC_EA(%a6),%a0 |a0 has the destination pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) bsrl dest_sgl |store the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) oril #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) dp_catas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) | Temp fix for z bit set in unf_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) movel USER_FPSR(%a6),-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) movel #2,%d0 |set round precision to dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) bsrl unf_sub |a0 points to result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) movel (%a7)+,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) movel #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) subw %d0,LOCAL_EX(%a0) |account for difference between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) | ;denorm/norm bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) movel %a0,%a1 |a1 has the operand input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) movel EXC_EA(%a6),%a0 |a0 has the destination pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) bsrl dest_dbl |store the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) oril #unfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) | Handle catastrophic overflow cases here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) sp_over:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) | Temp fix for z bit set in unf_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) movel USER_FPSR(%a6),-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) movel #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) movel ETEMP_EX(%a6),(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) movel ETEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) movel ETEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) bsrl ovf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) movel (%a7)+,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) movel %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) movel EXC_EA(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) bsrl dest_sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) orl #ovfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) dp_over:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) | Temp fix for z bit set in ovf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) movel USER_FPSR(%a6),-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) movel #2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) movel ETEMP_EX(%a6),(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) movel ETEMP_HI(%a6),4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) movel ETEMP_LO(%a6),8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) bsrl ovf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) movel (%a7)+,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) movel %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) movel EXC_EA(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) bsrl dest_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) orl #ovfinx_mask,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) bra mvout_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) | DPSPDNRM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) | This subroutine takes an extended normalized number and denormalizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) | it to the given round precision. This subroutine also decrements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) | the input operand's exponent by 1 to account for the fact that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) | dest_sgl or dest_dbl expects a normalized number's bias.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) | Input: a0 points to a normalized number in internal extended format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) | d0 is the round precision (=1 for sgl; =2 for dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) | d1 is the single precision or double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) | denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) | Output: (In the format for dest_sgl or dest_dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) | a0 points to the destination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) | a1 points to the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) | Exceptions: Reports inexact 2 exception by setting USER_FPSR bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) dpspdnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) movel %d0,-(%a7) |save round precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) clrl %d0 |clear initial g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) bsrl dnrm_lp |careful with d0, it's needed by round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) movew 2(%a7),%d1 |set rounding precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) swap %d1 |at this point d1 has PREC/MODE info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) bsrl round |round result, sets the inex bit in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) | ;USER_FPSR if needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) movew #1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) subw %d0,LOCAL_EX(%a0) |account for difference in denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) | ;vs norm bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) movel %a0,%a1 |a1 has the operand input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) movel EXC_EA(%a6),%a0 |a0 has the destination pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) addw #4,%a7 |pop stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) | SET_XOP initialized WBTEMP with the value pointed to by a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) | input: a0 points to input operand in the internal extended format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) set_xop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) movel LOCAL_EX(%a0),WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) movel LOCAL_HI(%a0),WBTEMP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) movel LOCAL_LO(%a0),WBTEMP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) bfclr WBTEMP_SGN(%a6){#0:#8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) beqs sxop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) bsetb #sign_bit,WBTEMP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) sxop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) bfclr STAG(%a6){#5:#4} |clear wbtm66,wbtm1,wbtm0,sbit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) | P_MOVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) p_movet:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) .long p_move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) .long p_movez
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) .long p_movei
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) .long p_moven
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) .long p_move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) p_regd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) .long p_dyd0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) .long p_dyd1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) .long p_dyd2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) .long p_dyd3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) .long p_dyd4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) .long p_dyd5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) .long p_dyd6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) .long p_dyd7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) pack_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) leal p_movet,%a0 |load jmp table address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) movew STAG(%a6),%d0 |get source tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) bfextu %d0{#16:#3},%d0 |isolate source bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) movel (%a0,%d0.w*4),%a0 |load a0 with routine label for tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) jmp (%a0) |go to the routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) p_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) movel #0x0c,%d0 |get byte count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) movel EXC_EA(%a6),%a1 |get the destination address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) bsr mem_write |write the user's destination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) moveb #0,CU_SAVEPC(%a6) |set the cu save pc to all 0's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) | Also note that the dtag must be set to norm here - this is because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) | the 040 uses the dtag to execute the correct microcode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) bfclr DTAG(%a6){#0:#3} |set dtag to norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) | Notes on handling of special case (zero, inf, and nan) inputs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) | 1. Operr is not signalled if the k-factor is greater than 18.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) | 2. Per the manual, status bits are not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) p_move:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) movew CMDREG1B(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) btstl #kfact_bit,%d0 |test for dynamic k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) beqs statick |if clear, k-factor is static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) dynamick:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) bfextu %d0{#25:#3},%d0 |isolate register for dynamic k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) lea p_regd,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) movel %a0@(%d0:l:4),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) jmp (%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) statick:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) andiw #0x007f,%d0 |get k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) bfexts %d0{#25:#7},%d0 |sign extend d0 for bindec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) bsrl bindec |perform the convert; data at a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) leal FP_SCR1(%a6),%a0 |load a0 with result address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) bral p_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) p_movez:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) clrw 2(%a0) |clear lower word of exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) clrl 4(%a0) |load second lword of ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) clrl 8(%a0) |load third lword of ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) bra p_write |go write results
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) p_movei:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) fmovel #0,%FPSR |clear aiop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) clrw 2(%a0) |clear lower word of exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) bra p_write |go write the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) p_moven:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) leal ETEMP(%a6),%a0 |a0 will point to the packed decimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) clrw 2(%a0) |clear lower word of exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) bra p_write |go write the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) | Routines to read the dynamic k-factor from Dn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) p_dyd0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) movel USER_D0(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) p_dyd1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) movel USER_D1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) p_dyd2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) movel %d2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) p_dyd3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) movel %d3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) p_dyd4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) movel %d4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) p_dyd5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) movel %d5,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) bras statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) p_dyd6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) movel %d6,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) bra statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) p_dyd7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) movel %d7,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) bra statick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) |end