^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) M68000 Hi-Performance Microprocessor Division
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) M68060 Software Package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Production Release P1.00 -- October 10, 1994
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) THE SOFTWARE is provided on an "AS IS" basis and without warranty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) To the maximum extent permitted by applicable law,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) and any warranty against infringement with regard to the SOFTWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) To the maximum extent permitted by applicable law,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) so long as this entire notice is retained without alteration in any modified and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) redistributed versions, and that such modified versions are clearly identified as such.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) No licenses are granted by implication, estoppel or otherwise under any patents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) or trademarks of Motorola, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) # litop.s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) # This file is appended to the top of the 060FPLSP package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) # and contains the entry points into the package. The user, in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) # effect, branches to one of the branch table entries located here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) bra.l _060LSP__idivs64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) bra.l _060LSP__idivu64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) bra.l _060LSP__imuls64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) bra.l _060LSP__imulu64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) bra.l _060LSP__cmp2_Ab_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bra.l _060LSP__cmp2_Aw_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bra.l _060LSP__cmp2_Al_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) bra.l _060LSP__cmp2_Db_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) bra.l _060LSP__cmp2_Dw_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) bra.l _060LSP__cmp2_Dl_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) # leave room for future possible aditions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) align 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) # _060LSP__idivu64_(): Emulate 64-bit unsigned div instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) # _060LSP__idivs64_(): Emulate 64-bit signed div instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) # This is the library version which is accessed as a subroutine #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) # and therefore does not work exactly like the 680X0 div{s,u}.l #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) # 64-bit divide instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) # None. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) # 0x4(sp) = divisor #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) # 0x8(sp) = hi(dividend) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) # 0xc(sp) = lo(dividend) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) # 0x10(sp) = pointer to location to place quotient/remainder #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) # 0x10(sp) = points to location of remainder/quotient. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) # remainder is in first longword, quotient is in 2nd. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) # If the operands are signed, make them unsigned and save the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) # sign info for later. Separate out special cases like divide-by-zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) # or 32-bit divides if possible. Else, use a special math algorithm #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) # to calculate the result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) # Restore sign info if signed instruction. Set the condition #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) # codes before performing the final "rts". If the divisor was equal to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) # zero, then perform a divide-by-zero using a 16-bit implemented #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) # divide instruction. This way, the operating system can record that #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) # the event occurred even though it may not point to the correct place. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) set POSNEG, -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) set NDIVISOR, -2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) set NDIVIDEND, -3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) set DDSECOND, -4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) set DDNORMAL, -8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) set DDQUOTIENT, -12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) set DIV64_CC, -16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) # divs.l #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) global _060LSP__idivs64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) _060LSP__idivs64_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) link.w %a6,&-16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) movm.l &0x3f00,-(%sp) # save d2-d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mov.w %cc,DIV64_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) st POSNEG(%a6) # signed operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) bra.b ldiv64_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) # divu.l #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) global _060LSP__idivu64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) _060LSP__idivu64_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) link.w %a6,&-16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) movm.l &0x3f00,-(%sp) # save d2-d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) mov.w %cc,DIV64_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) sf POSNEG(%a6) # unsigned operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ldiv64_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) mov.l 0x8(%a6),%d7 # fetch divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) beq.w ldiv64eq0 # divisor is = 0!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mov.l 0xc(%a6), %d5 # get dividend hi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) mov.l 0x10(%a6), %d6 # get dividend lo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) # separate signed and unsigned divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) tst.b POSNEG(%a6) # signed or unsigned?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) beq.b ldspecialcases # use positive divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) # save the sign of the divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) # make divisor unsigned if it's negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tst.l %d7 # chk sign of divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) slt NDIVISOR(%a6) # save sign of divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) bpl.b ldsgndividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) neg.l %d7 # complement negative divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) # save the sign of the dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) # make dividend unsigned if it's negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ldsgndividend:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tst.l %d5 # chk sign of hi(dividend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) slt NDIVIDEND(%a6) # save sign of dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) bpl.b ldspecialcases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) mov.w &0x0, %cc # clear 'X' cc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) negx.l %d6 # complement signed dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) negx.l %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) # extract some special cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) # - is (dividend == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) # - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ldspecialcases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) tst.l %d5 # is (hi(dividend) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bne.b ldnormaldivide # no, so try it the long way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) tst.l %d6 # is (lo(dividend) == 0), too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) beq.w lddone # yes, so (dividend == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cmp.l %d7,%d6 # is (divisor <= lo(dividend))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) bls.b ld32bitdivide # yes, so use 32 bit divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) exg %d5,%d6 # q = 0, r = dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) bra.w ldivfinish # can't divide, we're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ld32bitdivide:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) bra.b ldivfinish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ldnormaldivide:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) # last special case:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) # - is hi(dividend) >= divisor ? if yes, then overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cmp.l %d7,%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) bls.b lddovf # answer won't fit in 32 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) # perform the divide algorithm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bsr.l ldclassical # do int divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) # separate into signed and unsigned finishes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ldivfinish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tst.b POSNEG(%a6) # do divs, divu separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) beq.b lddone # divu has no processing!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) # it was a divs.l, so ccode setting is a little more complicated...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) tst.b NDIVIDEND(%a6) # remainder has same sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) beq.b ldcc # as dividend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) neg.l %d5 # sgn(rem) = sgn(dividend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ldcc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mov.b NDIVISOR(%a6), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) beq.b ldqpos # branch to quot positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) # 0x80000000 is the largest number representable as a 32-bit negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) # number. the negative of 0x80000000 is 0x80000000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) bhi.b lddovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) neg.l %d6 # make (-quot) 2's comp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bra.b lddone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ldqpos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) btst &0x1f, %d6 # will (+quot) fit in 32 bits?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bne.b lddovf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) lddone:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) # if the register numbers are the same, only the quotient gets saved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) # so, if we always save the quotient second, we save ourselves a cmp&beq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) andi.w &0x10,DIV64_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) mov.w DIV64_CC(%a6),%cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) tst.l %d6 # may set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) # here, the result is in d1 and d0. the current strategy is to save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) # the values at the location pointed to by a0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) # use movm here to not disturb the condition codes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ldexit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) movm.l &0x0060,([0x14,%a6]) # save result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) # EPILOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) # fmovm.l (%sp)+,&0x0 # restore no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) movm.l (%sp)+,&0x00fc # restore d2-d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) # EPILOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) # the result should be the unchanged dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) lddovf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) mov.l 0xc(%a6), %d5 # get dividend hi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mov.l 0x10(%a6), %d6 # get dividend lo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) andi.w &0x1c,DIV64_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ori.w &0x02,DIV64_CC(%a6) # set 'V' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) mov.w DIV64_CC(%a6),%cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) bra.b ldexit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ldiv64eq0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) mov.l 0xc(%a6),([0x14,%a6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mov.l 0x10(%a6),([0x14,%a6],0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mov.w DIV64_CC(%a6),%cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) # EPILOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) # fmovm.l (%sp)+,&0x0 # restore no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) movm.l (%sp)+,&0x00fc # restore d2-d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) # EPILOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) divu.w &0x0,%d0 # force a divbyzero exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ###########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) # This routine uses the 'classical' Algorithm D from Donald Knuth's #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) # Art of Computer Programming, vol II, Seminumerical Algorithms. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) # For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) # where U,V are words of the quadword dividend and longword divisor, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) # and U1, V1 are the most significant words. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) # The most sig. longword of the 64 bit dividend must be in %d5, least #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) # in %d6. The divisor must be in the variable ddivisor, and the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) # signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) # The quotient is returned in %d6, remainder in %d5, unless the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) # v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) # is unchanged. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ldclassical:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) # if the divisor msw is 0, use simpler algorithm then the full blown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) # one at ddknuth:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) cmpi.l %d7, &0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) bhi.b lddknuth # go use D. Knuth algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) # Since the divisor is only a word (and larger than the mslw of the dividend),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) # a simpler algorithm may be used :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) # In the general case, four quotient words would be created by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) # dividing the divisor word into each dividend word. In this case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) # the first two quotient words must be zero, or overflow would occur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) # Since we already checked this case above, we can treat the most significant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) # longword of the dividend as (0) remainder (see Knuth) and merely complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) # the last two divisions to get a quotient longword and word remainder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) swap %d5 # same as r*b if previous step rqd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) swap %d6 # get u3 to lsw position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mov.w %d6, %d5 # rb + u3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) divu.w %d7, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) mov.w %d5, %d1 # first quotient word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) swap %d6 # get u4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mov.w %d6, %d5 # rb + u4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) divu.w %d7, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mov.w %d5, %d1 # 2nd quotient 'digit'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) clr.w %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) swap %d5 # now remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) mov.l %d1, %d6 # and quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) lddknuth:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) # In this algorithm, the divisor is treated as a 2 digit (word) number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) # which is divided into a 3 digit (word) dividend to get one quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) # digit (word). After subtraction, the dividend is shifted and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) # process repeated. Before beginning, the divisor and quotient are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) # 'normalized' so that the process of estimating the quotient digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) # will yield verifiably correct results..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) clr.l DDNORMAL(%a6) # count of shifts for normalization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) clr.b DDSECOND(%a6) # clear flag for quotient digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) clr.l %d1 # %d1 will hold trial quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) lddnchk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) btst &31, %d7 # must we normalize? first word of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) bne.b lddnormalized # divisor (V1) must be >= 65536/2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) addq.l &0x1, DDNORMAL(%a6) # count normalization shifts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) lsl.l &0x1, %d7 # shift the divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) roxl.l &0x1, %d5 # shift u1,u2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) bra.w lddnchk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) lddnormalized:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) # Now calculate an estimate of the quotient words (msw first, then lsw).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) # The comments use subscripts for the first quotient digit determination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) mov.l %d7, %d3 # divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) mov.l %d5, %d2 # dividend mslw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) swap %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) swap %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) cmp.w %d2, %d3 # V1 = U1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) bne.b lddqcalc1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mov.w &0xffff, %d1 # use max trial quotient word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) bra.b lddadj0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) lddqcalc1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) mov.l %d5, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) divu.w %d3, %d1 # use quotient of mslw/msw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) andi.l &0x0000ffff, %d1 # zero any remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) lddadj0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) # now test the trial quotient and adjust. This step plus the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) # normalization assures (according to Knuth) that the trial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) # quotient will be at worst 1 too large.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mov.l %d6, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) clr.w %d6 # word u3 left
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) swap %d6 # in lsw position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) lddadj1: mov.l %d7, %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) mov.l %d1, %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mulu.w %d7, %d2 # V2q
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) swap %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) mulu.w %d1, %d3 # V1q
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) mov.l %d5, %d4 # U1U2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) sub.l %d3, %d4 # U1U2 - V1q
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) swap %d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) mov.w %d4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) mov.w %d6,%d4 # insert lower word (U3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) tst.w %d0 # is upper word set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) bne.w lddadjd1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) # add.l %d6, %d4 # (U1U2 - V1q) + U3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) cmp.l %d2, %d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) bls.b lddadjd1 # is V2q > (U1U2-V1q) + U3 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) subq.l &0x1, %d1 # yes, decrement and recheck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) bra.b lddadj1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) lddadjd1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) # now test the word by multiplying it by the divisor (V1V2) and comparing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) # the 3 digit (word) result with the current dividend words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mov.l %d5, -(%sp) # save %d5 (%d6 already saved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mov.l %d1, %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) swap %d6 # shift answer to ms 3 words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mov.l %d7, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) bsr.l ldmm2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) mov.l %d5, %d2 # now %d2,%d3 are trial*divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) mov.l %d6, %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) mov.l (%sp)+, %d5 # restore dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mov.l (%sp)+, %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) sub.l %d3, %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) subx.l %d2, %d5 # subtract double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) bcc ldd2nd # no carry, do next quotient digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) subq.l &0x1, %d1 # q is one too large
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) # need to add back divisor longword to current ms 3 digits of dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) # - according to Knuth, this is done only 2 out of 65536 times for random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) # divisor, dividend selection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) clr.l %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mov.l %d7, %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) swap %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) clr.w %d3 # %d3 now ls word of divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) add.l %d3, %d6 # aligned with 3rd word of dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) addx.l %d2, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) mov.l %d7, %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) clr.w %d3 # %d3 now ms word of divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) swap %d3 # aligned with 2nd word of dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) add.l %d3, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ldd2nd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) tst.b DDSECOND(%a6) # both q words done?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) bne.b lddremain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) # first quotient digit now correct. store digit and shift the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) # (subtracted) dividend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) mov.w %d1, DDQUOTIENT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) swap %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) swap %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mov.w %d6, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) clr.w %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) st DDSECOND(%a6) # second digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) bra.w lddnormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) lddremain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) # add 2nd word to quotient, get the remainder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) mov.w %d1, DDQUOTIENT+2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) # shift down one word/digit to renormalize remainder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) mov.w %d5, %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) swap %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) swap %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) mov.l DDNORMAL(%a6), %d7 # get norm shift count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) beq.b lddrn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) subq.l &0x1, %d7 # set for loop count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) lddnlp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) lsr.l &0x1, %d5 # shift into %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) roxr.l &0x1, %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dbf %d7, lddnlp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) lddrn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) mov.l %d6, %d5 # remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) mov.l DDQUOTIENT(%a6), %d6 # quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ldmm2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) # factors for the 32X32->64 multiplication are in %d5 and %d6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) # returns 64 bit result in %d5 (hi) %d6(lo).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) # destroys %d2,%d3,%d4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) # multiply hi,lo words of each factor to get 4 intermediate products
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) mov.l %d6, %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mov.l %d6, %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) mov.l %d5, %d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) swap %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) swap %d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) mulu.w %d5, %d6 # %d6 <- lsw*lsw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) mulu.w %d4, %d3 # %d3 <- msw*msw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) # now use swap and addx to consolidate to two longwords
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) clr.l %d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) swap %d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) add.w %d5, %d6 # add msw of l*l to lsw of m*l product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) addx.w %d4, %d3 # add any carry to m*m product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) add.w %d2, %d6 # add in lsw of other m*l product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) addx.w %d4, %d3 # add any carry to m*m product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) swap %d6 # %d6 is low 32 bits of final product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) clr.w %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) clr.w %d2 # lsw of two mixed products used,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) swap %d5 # now use msws of longwords
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) swap %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) add.l %d2, %d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) add.l %d3, %d5 # %d5 now ms 32 bits of final product
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) # _060LSP__imulu64_(): Emulate 64-bit unsigned mul instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) # _060LSP__imuls64_(): Emulate 64-bit signed mul instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) # This is the library version which is accessed as a subroutine #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) # and therefore does not work exactly like the 680X0 mul{s,u}.l #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) # 64-bit multiply instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) # 0x4(sp) = multiplier #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) # 0x8(sp) = multiplicand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) # 0xc(sp) = pointer to location to place 64-bit result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) # 0xc(sp) = points to location of 64-bit result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) # Perform the multiply in pieces using 16x16->32 unsigned #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) # multiplies and "add" instructions. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) # Set the condition codes as appropriate before performing an #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) # "rts". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) set MUL64_CC, -4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) global _060LSP__imulu64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) _060LSP__imulu64_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mov.w %cc,MUL64_CC(%a6) # save incoming ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) mov.l 0x8(%a6),%d0 # store multiplier in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) beq.w mulu64_zero # handle zero separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mov.l 0xc(%a6),%d1 # get multiplicand in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) beq.w mulu64_zero # handle zero separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) # 63 32 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) # ---------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) # | hi(mplier) * hi(mplicand)| #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) # ---------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) # | hi(mplier) * lo(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) # | lo(mplier) * hi(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) # | ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) # --|-- | lo(mplier) * lo(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) # | ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) # ======================================================== #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) # -------------------------------------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) # | hi(result) | lo(result) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) # -------------------------------------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) mulu64_alg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) # load temp registers with operands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) mov.l %d0,%d2 # mr in d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) mov.l %d0,%d3 # mr in d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mov.l %d1,%d4 # md in d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) swap %d3 # hi(mr) in lo d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) swap %d4 # hi(md) in lo d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) # complete necessary multiplies:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mulu.w %d1,%d0 # [1] lo(mr) * lo(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) mulu.w %d3,%d1 # [2] hi(mr) * lo(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mulu.w %d4,%d2 # [3] lo(mr) * hi(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) mulu.w %d4,%d3 # [4] hi(mr) * hi(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) # add lo portions of [2],[3] to hi portion of [1].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) # add carries produced from these adds to [4].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) # lo([1]) is the final lo 16 bits of the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) clr.l %d4 # load d4 w/ zero value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) swap %d0 # hi([1]) <==> lo([1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) add.w %d1,%d0 # hi([1]) + lo([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) addx.l %d4,%d3 # [4] + carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) add.w %d2,%d0 # hi([1]) + lo([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) addx.l %d4,%d3 # [4] + carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) swap %d0 # lo([1]) <==> hi([1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) # lo portions of [2],[3] have been added in to final result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) # now, clear lo, put hi in lo reg, and add to [4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) clr.w %d1 # clear lo([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) clr.w %d2 # clear hi([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) swap %d1 # hi([2]) in lo d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) swap %d2 # hi([3]) in lo d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) add.l %d2,%d1 # [4] + hi([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) add.l %d3,%d1 # [4] + hi([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) # now, grab the condition codes. only one that can be set is 'N'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) # 'N' CAN be set if the operation is unsigned if bit 63 is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) mov.w MUL64_CC(%a6),%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) andi.b &0x10,%d4 # keep old 'X' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) tst.l %d1 # may set 'N' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) bpl.b mulu64_ddone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ori.b &0x8,%d4 # set 'N' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mulu64_ddone:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) mov.w %d4,%cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) # here, the result is in d1 and d0. the current strategy is to save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) # the values at the location pointed to by a0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) # use movm here to not disturb the condition codes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mulu64_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) exg %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) movm.l &0x0003,([0x10,%a6]) # save result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) # EPILOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) # fmovm.l (%sp)+,&0x0 # restore no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) movm.l (%sp)+,&0x001c # restore d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) # EPILOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) # one or both of the operands is zero so the result is also zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) # save the zero result to the register file and set the 'Z' ccode bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) mulu64_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) mov.w MUL64_CC(%a6),%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) andi.b &0x10,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ori.b &0x4,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) mov.w %d4,%cc # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) bra.b mulu64_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) # muls.l #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) global _060LSP__imuls64_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) _060LSP__imuls64_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) movm.l &0x3c00,-(%sp) # save d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mov.w %cc,MUL64_CC(%a6) # save incoming ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mov.l 0x8(%a6),%d0 # store multiplier in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) beq.b mulu64_zero # handle zero separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) mov.l 0xc(%a6),%d1 # get multiplicand in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) beq.b mulu64_zero # handle zero separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) clr.b %d5 # clear sign tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) tst.l %d0 # is multiplier negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) bge.b muls64_chk_md_sgn # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) neg.l %d0 # make multiplier positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ori.b &0x1,%d5 # save multiplier sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) # the result sign is the exclusive or of the operand sign bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) muls64_chk_md_sgn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) tst.l %d1 # is multiplicand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) bge.b muls64_alg # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) neg.l %d1 # make multiplicand positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) eori.b &0x1,%d5 # calculate correct sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) # 63 32 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) # ---------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) # | hi(mplier) * hi(mplicand)| #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) # ---------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) # | hi(mplier) * lo(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) # | lo(mplier) * hi(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) # ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) # | ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) # --|-- | lo(mplier) * lo(mplicand) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) # | ----------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) # ======================================================== #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) # -------------------------------------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) # | hi(result) | lo(result) | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) # -------------------------------------------------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) muls64_alg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) # load temp registers with operands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mov.l %d0,%d2 # mr in d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) mov.l %d0,%d3 # mr in d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mov.l %d1,%d4 # md in d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) swap %d3 # hi(mr) in lo d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) swap %d4 # hi(md) in lo d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) # complete necessary multiplies:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) mulu.w %d1,%d0 # [1] lo(mr) * lo(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) mulu.w %d3,%d1 # [2] hi(mr) * lo(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) mulu.w %d4,%d2 # [3] lo(mr) * hi(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mulu.w %d4,%d3 # [4] hi(mr) * hi(md)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) # add lo portions of [2],[3] to hi portion of [1].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) # add carries produced from these adds to [4].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) # lo([1]) is the final lo 16 bits of the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) clr.l %d4 # load d4 w/ zero value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) swap %d0 # hi([1]) <==> lo([1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) add.w %d1,%d0 # hi([1]) + lo([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) addx.l %d4,%d3 # [4] + carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) add.w %d2,%d0 # hi([1]) + lo([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) addx.l %d4,%d3 # [4] + carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) swap %d0 # lo([1]) <==> hi([1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) # lo portions of [2],[3] have been added in to final result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) # now, clear lo, put hi in lo reg, and add to [4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) clr.w %d1 # clear lo([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) clr.w %d2 # clear hi([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) swap %d1 # hi([2]) in lo d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) swap %d2 # hi([3]) in lo d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) add.l %d2,%d1 # [4] + hi([2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) add.l %d3,%d1 # [4] + hi([3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) tst.b %d5 # should result be signed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) beq.b muls64_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) # result should be a signed negative number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) # compute 2's complement of the unsigned number:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) # -negate all bits and add 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) muls64_neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) not.l %d0 # negate lo(result) bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) not.l %d1 # negate hi(result) bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) addq.l &1,%d0 # add 1 to lo(result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) addx.l %d4,%d1 # add carry to hi(result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) muls64_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) mov.w MUL64_CC(%a6),%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) andi.b &0x10,%d4 # keep old 'X' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) tst.l %d1 # may set 'N' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) bpl.b muls64_ddone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ori.b &0x8,%d4 # set 'N' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) muls64_ddone:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) mov.w %d4,%cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) # here, the result is in d1 and d0. the current strategy is to save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) # the values at the location pointed to by a0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) # use movm here to not disturb the condition codes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) muls64_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) exg %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) movm.l &0x0003,([0x10,%a6]) # save result at (a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) # EPILOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) # fmovm.l (%sp)+,&0x0 # restore no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) movm.l (%sp)+,&0x003c # restore d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) # EPILOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) # one or both of the operands is zero so the result is also zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) # save the zero result to the register file and set the 'Z' ccode bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) muls64_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) mov.w MUL64_CC(%a6),%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) andi.b &0x10,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ori.b &0x4,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) mov.w %d4,%cc # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) bra.b muls64_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) # _060LSP__cmp2_Ab_(): Emulate "cmp2.b An,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) # _060LSP__cmp2_Aw_(): Emulate "cmp2.w An,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) # _060LSP__cmp2_Al_(): Emulate "cmp2.l An,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) # _060LSP__cmp2_Db_(): Emulate "cmp2.b Dn,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) # _060LSP__cmp2_Dw_(): Emulate "cmp2.w Dn,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) # _060LSP__cmp2_Dl_(): Emulate "cmp2.l Dn,<ea>". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) # This is the library version which is accessed as a subroutine #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) # and therefore does not work exactly like the 680X0 "cmp2" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) # instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) # 0x4(sp) = Rn #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) # 0x8(sp) = pointer to boundary pair #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) # cc = condition codes are set correctly #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) # In the interest of simplicity, all operands are converted to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) # longword size whether the operation is byte, word, or long. The #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) # bounds are sign extended accordingly. If Rn is a data register, Rn is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) # also sign extended. If Rn is an address register, it need not be sign #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) # extended since the full register is always used. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) # The condition codes are set correctly before the final "rts". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) set CMP2_CC, -4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) global _060LSP__cmp2_Ab_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) _060LSP__cmp2_Ab_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mov.b ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) mov.b ([0xc,%a6],0x1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) extb.l %d0 # sign extend lo bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) extb.l %d1 # sign extend hi bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) bra.w l_cmp2_cmp # go do the compare emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) global _060LSP__cmp2_Aw_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) _060LSP__cmp2_Aw_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) mov.w ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mov.w ([0xc,%a6],0x2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) ext.l %d0 # sign extend lo bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ext.l %d1 # sign extend hi bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) bra.w l_cmp2_cmp # go do the compare emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) global _060LSP__cmp2_Al_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) _060LSP__cmp2_Al_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mov.l ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) mov.l ([0xc,%a6],0x4),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) bra.w l_cmp2_cmp # go do the compare emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) global _060LSP__cmp2_Db_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) _060LSP__cmp2_Db_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) mov.b ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) mov.b ([0xc,%a6],0x1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) extb.l %d0 # sign extend lo bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) extb.l %d1 # sign extend hi bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) # operation is a data register compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) # sign extend byte to long so we can do simple longword compares.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) extb.l %d2 # sign extend data byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) bra.w l_cmp2_cmp # go do the compare emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) global _060LSP__cmp2_Dw_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) _060LSP__cmp2_Dw_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) mov.w ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) mov.w ([0xc,%a6],0x2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ext.l %d0 # sign extend lo bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ext.l %d1 # sign extend hi bnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) # operation is a data register compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) # sign extend word to long so we can do simple longword compares.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ext.l %d2 # sign extend data word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) bra.w l_cmp2_cmp # go emulate compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) global _060LSP__cmp2_Dl_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) _060LSP__cmp2_Dl_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) # PROLOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) link.w %a6,&-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) movm.l &0x3800,-(%sp) # save d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) # fmovm.l &0x0,-(%sp) # save no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) # PROLOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) mov.w %cc,CMP2_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) mov.l 0x8(%a6), %d2 # get regval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mov.l ([0xc,%a6],0x0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) mov.l ([0xc,%a6],0x4),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) # To set the ccodes correctly:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) # (1) save 'Z' bit from (Rn - lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) # (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) # (3) keep 'X', 'N', and 'V' from before instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) # (4) combine ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) l_cmp2_cmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) sub.l %d0, %d2 # (Rn - lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mov.w %cc, %d3 # fetch resulting ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) andi.b &0x4, %d3 # keep 'Z' bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) sub.l %d0, %d1 # (hi - lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) mov.w %cc, %d4 # fetch resulting ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) or.b %d4, %d3 # combine w/ earlier ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) andi.b &0x5, %d3 # keep 'Z' and 'N'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) mov.w CMP2_CC(%a6), %d4 # fetch old ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) andi.b &0x1a, %d4 # keep 'X','N','V' bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) or.b %d3, %d4 # insert new ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) mov.w %d4,%cc # save new ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) # EPILOGUE BEGIN ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) # fmovm.l (%sp)+,&0x0 # restore no fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) movm.l (%sp)+,&0x001c # restore d2-d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) # EPILOGUE END ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) rts