diff options
Diffstat (limited to 'ANDROID_3.4.5/arch/m68k/ifpsp060/src/ilsp.S')
-rw-r--r-- | ANDROID_3.4.5/arch/m68k/ifpsp060/src/ilsp.S | 932 |
1 files changed, 0 insertions, 932 deletions
diff --git a/ANDROID_3.4.5/arch/m68k/ifpsp060/src/ilsp.S b/ANDROID_3.4.5/arch/m68k/ifpsp060/src/ilsp.S deleted file mode 100644 index 970abaf3..00000000 --- a/ANDROID_3.4.5/arch/m68k/ifpsp060/src/ilsp.S +++ /dev/null @@ -1,932 +0,0 @@ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP -M68000 Hi-Performance Microprocessor Division -M68060 Software Package -Production Release P1.00 -- October 10, 1994 - -M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. - -THE SOFTWARE is provided on an "AS IS" basis and without warranty. -To the maximum extent permitted by applicable law, -MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, -INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -and any warranty against infringement with regard to the SOFTWARE -(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. - -To the maximum extent permitted by applicable law, -IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER -(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, -BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) -ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. -Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. - -You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE -so long as this entire notice is retained without alteration in any modified and/or -redistributed versions, and that such modified versions are clearly identified as such. -No licenses are granted by implication, estoppel or otherwise under any patents -or trademarks of Motorola, Inc. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# litop.s: -# This file is appended to the top of the 060FPLSP package -# and contains the entry points into the package. The user, in -# effect, branches to one of the branch table entries located here. -# - - bra.l _060LSP__idivs64_ - short 0x0000 - bra.l _060LSP__idivu64_ - short 0x0000 - - bra.l _060LSP__imuls64_ - short 0x0000 - bra.l _060LSP__imulu64_ - short 0x0000 - - bra.l _060LSP__cmp2_Ab_ - short 0x0000 - bra.l _060LSP__cmp2_Aw_ - short 0x0000 - bra.l _060LSP__cmp2_Al_ - short 0x0000 - bra.l _060LSP__cmp2_Db_ - short 0x0000 - bra.l _060LSP__cmp2_Dw_ - short 0x0000 - bra.l _060LSP__cmp2_Dl_ - short 0x0000 - -# leave room for future possible aditions. - align 0x200 - -######################################################################### -# XDEF **************************************************************** # -# _060LSP__idivu64_(): Emulate 64-bit unsigned div instruction. # -# _060LSP__idivs64_(): Emulate 64-bit signed div instruction. # -# # -# This is the library version which is accessed as a subroutine # -# and therefore does not work exactly like the 680X0 div{s,u}.l # -# 64-bit divide instruction. # -# # -# XREF **************************************************************** # -# None. # -# # -# INPUT *************************************************************** # -# 0x4(sp) = divisor # -# 0x8(sp) = hi(dividend) # -# 0xc(sp) = lo(dividend) # -# 0x10(sp) = pointer to location to place quotient/remainder # -# # -# OUTPUT ************************************************************** # -# 0x10(sp) = points to location of remainder/quotient. # -# remainder is in first longword, quotient is in 2nd. # -# # -# ALGORITHM *********************************************************** # -# If the operands are signed, make them unsigned and save the # -# sign info for later. Separate out special cases like divide-by-zero # -# or 32-bit divides if possible. Else, use a special math algorithm # -# to calculate the result. # -# Restore sign info if signed instruction. Set the condition # -# codes before performing the final "rts". If the divisor was equal to # -# zero, then perform a divide-by-zero using a 16-bit implemented # -# divide instruction. This way, the operating system can record that # -# the event occurred even though it may not point to the correct place. # -# # -######################################################################### - -set POSNEG, -1 -set NDIVISOR, -2 -set NDIVIDEND, -3 -set DDSECOND, -4 -set DDNORMAL, -8 -set DDQUOTIENT, -12 -set DIV64_CC, -16 - -########## -# divs.l # -########## - global _060LSP__idivs64_ -_060LSP__idivs64_: -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-16 - movm.l &0x3f00,-(%sp) # save d2-d7 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,DIV64_CC(%a6) - st POSNEG(%a6) # signed operation - bra.b ldiv64_cont - -########## -# divu.l # -########## - global _060LSP__idivu64_ -_060LSP__idivu64_: -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-16 - movm.l &0x3f00,-(%sp) # save d2-d7 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,DIV64_CC(%a6) - sf POSNEG(%a6) # unsigned operation - -ldiv64_cont: - mov.l 0x8(%a6),%d7 # fetch divisor - - beq.w ldiv64eq0 # divisor is = 0!!! - - mov.l 0xc(%a6), %d5 # get dividend hi - mov.l 0x10(%a6), %d6 # get dividend lo - -# separate signed and unsigned divide - tst.b POSNEG(%a6) # signed or unsigned? - beq.b ldspecialcases # use positive divide - -# save the sign of the divisor -# make divisor unsigned if it's negative - tst.l %d7 # chk sign of divisor - slt NDIVISOR(%a6) # save sign of divisor - bpl.b ldsgndividend - neg.l %d7 # complement negative divisor - -# save the sign of the dividend -# make dividend unsigned if it's negative -ldsgndividend: - tst.l %d5 # chk sign of hi(dividend) - slt NDIVIDEND(%a6) # save sign of dividend - bpl.b ldspecialcases - - mov.w &0x0, %cc # clear 'X' cc bit - negx.l %d6 # complement signed dividend - negx.l %d5 - -# extract some special cases: -# - is (dividend == 0) ? -# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div) -ldspecialcases: - tst.l %d5 # is (hi(dividend) == 0) - bne.b ldnormaldivide # no, so try it the long way - - tst.l %d6 # is (lo(dividend) == 0), too - beq.w lddone # yes, so (dividend == 0) - - cmp.l %d7,%d6 # is (divisor <= lo(dividend)) - bls.b ld32bitdivide # yes, so use 32 bit divide - - exg %d5,%d6 # q = 0, r = dividend - bra.w ldivfinish # can't divide, we're done. - -ld32bitdivide: - tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div! - - bra.b ldivfinish - -ldnormaldivide: -# last special case: -# - is hi(dividend) >= divisor ? if yes, then overflow - cmp.l %d7,%d5 - bls.b lddovf # answer won't fit in 32 bits - -# perform the divide algorithm: - bsr.l ldclassical # do int divide - -# separate into signed and unsigned finishes. -ldivfinish: - tst.b POSNEG(%a6) # do divs, divu separately - beq.b lddone # divu has no processing!!! - -# it was a divs.l, so ccode setting is a little more complicated... - tst.b NDIVIDEND(%a6) # remainder has same sign - beq.b ldcc # as dividend. - neg.l %d5 # sgn(rem) = sgn(dividend) -ldcc: - mov.b NDIVISOR(%a6), %d0 - eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative - beq.b ldqpos # branch to quot positive - -# 0x80000000 is the largest number representable as a 32-bit negative -# number. the negative of 0x80000000 is 0x80000000. - cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits? - bhi.b lddovf - - neg.l %d6 # make (-quot) 2's comp - - bra.b lddone - -ldqpos: - btst &0x1f, %d6 # will (+quot) fit in 32 bits? - bne.b lddovf - -lddone: -# if the register numbers are the same, only the quotient gets saved. -# so, if we always save the quotient second, we save ourselves a cmp&beq - andi.w &0x10,DIV64_CC(%a6) - mov.w DIV64_CC(%a6),%cc - tst.l %d6 # may set 'N' ccode bit - -# here, the result is in d1 and d0. the current strategy is to save -# the values at the location pointed to by a0. -# use movm here to not disturb the condition codes. -ldexit: - movm.l &0x0060,([0x14,%a6]) # save result - -# EPILOGUE BEGIN ######################################################## -# fmovm.l (%sp)+,&0x0 # restore no fpregs - movm.l (%sp)+,&0x00fc # restore d2-d7 - unlk %a6 -# EPILOGUE END ########################################################## - - rts - -# the result should be the unchanged dividend -lddovf: - mov.l 0xc(%a6), %d5 # get dividend hi - mov.l 0x10(%a6), %d6 # get dividend lo - - andi.w &0x1c,DIV64_CC(%a6) - ori.w &0x02,DIV64_CC(%a6) # set 'V' ccode bit - mov.w DIV64_CC(%a6),%cc - - bra.b ldexit - -ldiv64eq0: - mov.l 0xc(%a6),([0x14,%a6]) - mov.l 0x10(%a6),([0x14,%a6],0x4) - - mov.w DIV64_CC(%a6),%cc - -# EPILOGUE BEGIN ######################################################## -# fmovm.l (%sp)+,&0x0 # restore no fpregs - movm.l (%sp)+,&0x00fc # restore d2-d7 - unlk %a6 -# EPILOGUE END ########################################################## - - divu.w &0x0,%d0 # force a divbyzero exception - rts - -########################################################################### -######################################################################### -# This routine uses the 'classical' Algorithm D from Donald Knuth's # -# Art of Computer Programming, vol II, Seminumerical Algorithms. # -# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, # -# where U,V are words of the quadword dividend and longword divisor, # -# and U1, V1 are the most significant words. # -# # -# The most sig. longword of the 64 bit dividend must be in %d5, least # -# in %d6. The divisor must be in the variable ddivisor, and the # -# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). # -# The quotient is returned in %d6, remainder in %d5, unless the # -# v (overflow) bit is set in the saved %ccr. If overflow, the dividend # -# is unchanged. # -######################################################################### -ldclassical: -# if the divisor msw is 0, use simpler algorithm then the full blown -# one at ddknuth: - - cmpi.l %d7, &0xffff - bhi.b lddknuth # go use D. Knuth algorithm - -# Since the divisor is only a word (and larger than the mslw of the dividend), -# a simpler algorithm may be used : -# In the general case, four quotient words would be created by -# dividing the divisor word into each dividend word. In this case, -# the first two quotient words must be zero, or overflow would occur. -# Since we already checked this case above, we can treat the most significant -# longword of the dividend as (0) remainder (see Knuth) and merely complete -# the last two divisions to get a quotient longword and word remainder: - - clr.l %d1 - swap %d5 # same as r*b if previous step rqd - swap %d6 # get u3 to lsw position - mov.w %d6, %d5 # rb + u3 - - divu.w %d7, %d5 - - mov.w %d5, %d1 # first quotient word - swap %d6 # get u4 - mov.w %d6, %d5 # rb + u4 - - divu.w %d7, %d5 - - swap %d1 - mov.w %d5, %d1 # 2nd quotient 'digit' - clr.w %d5 - swap %d5 # now remainder - mov.l %d1, %d6 # and quotient - - rts - -lddknuth: -# In this algorithm, the divisor is treated as a 2 digit (word) number -# which is divided into a 3 digit (word) dividend to get one quotient -# digit (word). After subtraction, the dividend is shifted and the -# process repeated. Before beginning, the divisor and quotient are -# 'normalized' so that the process of estimating the quotient digit -# will yield verifiably correct results.. - - clr.l DDNORMAL(%a6) # count of shifts for normalization - clr.b DDSECOND(%a6) # clear flag for quotient digits - clr.l %d1 # %d1 will hold trial quotient -lddnchk: - btst &31, %d7 # must we normalize? first word of - bne.b lddnormalized # divisor (V1) must be >= 65536/2 - addq.l &0x1, DDNORMAL(%a6) # count normalization shifts - lsl.l &0x1, %d7 # shift the divisor - lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2 - roxl.l &0x1, %d5 # shift u1,u2 - bra.w lddnchk -lddnormalized: - -# Now calculate an estimate of the quotient words (msw first, then lsw). -# The comments use subscripts for the first quotient digit determination. - mov.l %d7, %d3 # divisor - mov.l %d5, %d2 # dividend mslw - swap %d2 - swap %d3 - cmp.w %d2, %d3 # V1 = U1 ? - bne.b lddqcalc1 - mov.w &0xffff, %d1 # use max trial quotient word - bra.b lddadj0 -lddqcalc1: - mov.l %d5, %d1 - - divu.w %d3, %d1 # use quotient of mslw/msw - - andi.l &0x0000ffff, %d1 # zero any remainder -lddadj0: - -# now test the trial quotient and adjust. This step plus the -# normalization assures (according to Knuth) that the trial -# quotient will be at worst 1 too large. - mov.l %d6, -(%sp) - clr.w %d6 # word u3 left - swap %d6 # in lsw position -lddadj1: mov.l %d7, %d3 - mov.l %d1, %d2 - mulu.w %d7, %d2 # V2q - swap %d3 - mulu.w %d1, %d3 # V1q - mov.l %d5, %d4 # U1U2 - sub.l %d3, %d4 # U1U2 - V1q - - swap %d4 - - mov.w %d4,%d0 - mov.w %d6,%d4 # insert lower word (U3) - - tst.w %d0 # is upper word set? - bne.w lddadjd1 - -# add.l %d6, %d4 # (U1U2 - V1q) + U3 - - cmp.l %d2, %d4 - bls.b lddadjd1 # is V2q > (U1U2-V1q) + U3 ? - subq.l &0x1, %d1 # yes, decrement and recheck - bra.b lddadj1 -lddadjd1: -# now test the word by multiplying it by the divisor (V1V2) and comparing -# the 3 digit (word) result with the current dividend words - mov.l %d5, -(%sp) # save %d5 (%d6 already saved) - mov.l %d1, %d6 - swap %d6 # shift answer to ms 3 words - mov.l %d7, %d5 - bsr.l ldmm2 - mov.l %d5, %d2 # now %d2,%d3 are trial*divisor - mov.l %d6, %d3 - mov.l (%sp)+, %d5 # restore dividend - mov.l (%sp)+, %d6 - sub.l %d3, %d6 - subx.l %d2, %d5 # subtract double precision - bcc ldd2nd # no carry, do next quotient digit - subq.l &0x1, %d1 # q is one too large -# need to add back divisor longword to current ms 3 digits of dividend -# - according to Knuth, this is done only 2 out of 65536 times for random -# divisor, dividend selection. - clr.l %d2 - mov.l %d7, %d3 - swap %d3 - clr.w %d3 # %d3 now ls word of divisor - add.l %d3, %d6 # aligned with 3rd word of dividend - addx.l %d2, %d5 - mov.l %d7, %d3 - clr.w %d3 # %d3 now ms word of divisor - swap %d3 # aligned with 2nd word of dividend - add.l %d3, %d5 -ldd2nd: - tst.b DDSECOND(%a6) # both q words done? - bne.b lddremain -# first quotient digit now correct. store digit and shift the -# (subtracted) dividend - mov.w %d1, DDQUOTIENT(%a6) - clr.l %d1 - swap %d5 - swap %d6 - mov.w %d6, %d5 - clr.w %d6 - st DDSECOND(%a6) # second digit - bra.w lddnormalized -lddremain: -# add 2nd word to quotient, get the remainder. - mov.w %d1, DDQUOTIENT+2(%a6) -# shift down one word/digit to renormalize remainder. - mov.w %d5, %d6 - swap %d6 - swap %d5 - mov.l DDNORMAL(%a6), %d7 # get norm shift count - beq.b lddrn - subq.l &0x1, %d7 # set for loop count -lddnlp: - lsr.l &0x1, %d5 # shift into %d6 - roxr.l &0x1, %d6 - dbf %d7, lddnlp -lddrn: - mov.l %d6, %d5 # remainder - mov.l DDQUOTIENT(%a6), %d6 # quotient - - rts -ldmm2: -# factors for the 32X32->64 multiplication are in %d5 and %d6. -# returns 64 bit result in %d5 (hi) %d6(lo). -# destroys %d2,%d3,%d4. - -# multiply hi,lo words of each factor to get 4 intermediate products - mov.l %d6, %d2 - mov.l %d6, %d3 - mov.l %d5, %d4 - swap %d3 - swap %d4 - mulu.w %d5, %d6 # %d6 <- lsw*lsw - mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source - mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest - mulu.w %d4, %d3 # %d3 <- msw*msw -# now use swap and addx to consolidate to two longwords - clr.l %d4 - swap %d6 - add.w %d5, %d6 # add msw of l*l to lsw of m*l product - addx.w %d4, %d3 # add any carry to m*m product - add.w %d2, %d6 # add in lsw of other m*l product - addx.w %d4, %d3 # add any carry to m*m product - swap %d6 # %d6 is low 32 bits of final product - clr.w %d5 - clr.w %d2 # lsw of two mixed products used, - swap %d5 # now use msws of longwords - swap %d2 - add.l %d2, %d5 - add.l %d3, %d5 # %d5 now ms 32 bits of final product - rts - -######################################################################### -# XDEF **************************************************************** # -# _060LSP__imulu64_(): Emulate 64-bit unsigned mul instruction # -# _060LSP__imuls64_(): Emulate 64-bit signed mul instruction. # -# # -# This is the library version which is accessed as a subroutine # -# and therefore does not work exactly like the 680X0 mul{s,u}.l # -# 64-bit multiply instruction. # -# # -# XREF **************************************************************** # -# None # -# # -# INPUT *************************************************************** # -# 0x4(sp) = multiplier # -# 0x8(sp) = multiplicand # -# 0xc(sp) = pointer to location to place 64-bit result # -# # -# OUTPUT ************************************************************** # -# 0xc(sp) = points to location of 64-bit result # -# # -# ALGORITHM *********************************************************** # -# Perform the multiply in pieces using 16x16->32 unsigned # -# multiplies and "add" instructions. # -# Set the condition codes as appropriate before performing an # -# "rts". # -# # -######################################################################### - -set MUL64_CC, -4 - - global _060LSP__imulu64_ -_060LSP__imulu64_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,MUL64_CC(%a6) # save incoming ccodes - - mov.l 0x8(%a6),%d0 # store multiplier in d0 - beq.w mulu64_zero # handle zero separately - - mov.l 0xc(%a6),%d1 # get multiplicand in d1 - beq.w mulu64_zero # handle zero separately - -######################################################################### -# 63 32 0 # -# ---------------------------- # -# | hi(mplier) * hi(mplicand)| # -# ---------------------------- # -# ----------------------------- # -# | hi(mplier) * lo(mplicand) | # -# ----------------------------- # -# ----------------------------- # -# | lo(mplier) * hi(mplicand) | # -# ----------------------------- # -# | ----------------------------- # -# --|-- | lo(mplier) * lo(mplicand) | # -# | ----------------------------- # -# ======================================================== # -# -------------------------------------------------------- # -# | hi(result) | lo(result) | # -# -------------------------------------------------------- # -######################################################################### -mulu64_alg: -# load temp registers with operands - mov.l %d0,%d2 # mr in d2 - mov.l %d0,%d3 # mr in d3 - mov.l %d1,%d4 # md in d4 - swap %d3 # hi(mr) in lo d3 - swap %d4 # hi(md) in lo d4 - -# complete necessary multiplies: - mulu.w %d1,%d0 # [1] lo(mr) * lo(md) - mulu.w %d3,%d1 # [2] hi(mr) * lo(md) - mulu.w %d4,%d2 # [3] lo(mr) * hi(md) - mulu.w %d4,%d3 # [4] hi(mr) * hi(md) - -# add lo portions of [2],[3] to hi portion of [1]. -# add carries produced from these adds to [4]. -# lo([1]) is the final lo 16 bits of the result. - clr.l %d4 # load d4 w/ zero value - swap %d0 # hi([1]) <==> lo([1]) - add.w %d1,%d0 # hi([1]) + lo([2]) - addx.l %d4,%d3 # [4] + carry - add.w %d2,%d0 # hi([1]) + lo([3]) - addx.l %d4,%d3 # [4] + carry - swap %d0 # lo([1]) <==> hi([1]) - -# lo portions of [2],[3] have been added in to final result. -# now, clear lo, put hi in lo reg, and add to [4] - clr.w %d1 # clear lo([2]) - clr.w %d2 # clear hi([3]) - swap %d1 # hi([2]) in lo d1 - swap %d2 # hi([3]) in lo d2 - add.l %d2,%d1 # [4] + hi([2]) - add.l %d3,%d1 # [4] + hi([3]) - -# now, grab the condition codes. only one that can be set is 'N'. -# 'N' CAN be set if the operation is unsigned if bit 63 is set. - mov.w MUL64_CC(%a6),%d4 - andi.b &0x10,%d4 # keep old 'X' bit - tst.l %d1 # may set 'N' bit - bpl.b mulu64_ddone - ori.b &0x8,%d4 # set 'N' bit -mulu64_ddone: - mov.w %d4,%cc - -# here, the result is in d1 and d0. the current strategy is to save -# the values at the location pointed to by a0. -# use movm here to not disturb the condition codes. -mulu64_end: - exg %d1,%d0 - movm.l &0x0003,([0x10,%a6]) # save result - -# EPILOGUE BEGIN ######################################################## -# fmovm.l (%sp)+,&0x0 # restore no fpregs - movm.l (%sp)+,&0x001c # restore d2-d4 - unlk %a6 -# EPILOGUE END ########################################################## - - rts - -# one or both of the operands is zero so the result is also zero. -# save the zero result to the register file and set the 'Z' ccode bit. -mulu64_zero: - clr.l %d0 - clr.l %d1 - - mov.w MUL64_CC(%a6),%d4 - andi.b &0x10,%d4 - ori.b &0x4,%d4 - mov.w %d4,%cc # set 'Z' ccode bit - - bra.b mulu64_end - -########## -# muls.l # -########## - global _060LSP__imuls64_ -_060LSP__imuls64_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3c00,-(%sp) # save d2-d5 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,MUL64_CC(%a6) # save incoming ccodes - - mov.l 0x8(%a6),%d0 # store multiplier in d0 - beq.b mulu64_zero # handle zero separately - - mov.l 0xc(%a6),%d1 # get multiplicand in d1 - beq.b mulu64_zero # handle zero separately - - clr.b %d5 # clear sign tag - tst.l %d0 # is multiplier negative? - bge.b muls64_chk_md_sgn # no - neg.l %d0 # make multiplier positive - - ori.b &0x1,%d5 # save multiplier sgn - -# the result sign is the exclusive or of the operand sign bits. -muls64_chk_md_sgn: - tst.l %d1 # is multiplicand negative? - bge.b muls64_alg # no - neg.l %d1 # make multiplicand positive - - eori.b &0x1,%d5 # calculate correct sign - -######################################################################### -# 63 32 0 # -# ---------------------------- # -# | hi(mplier) * hi(mplicand)| # -# ---------------------------- # -# ----------------------------- # -# | hi(mplier) * lo(mplicand) | # -# ----------------------------- # -# ----------------------------- # -# | lo(mplier) * hi(mplicand) | # -# ----------------------------- # -# | ----------------------------- # -# --|-- | lo(mplier) * lo(mplicand) | # -# | ----------------------------- # -# ======================================================== # -# -------------------------------------------------------- # -# | hi(result) | lo(result) | # -# -------------------------------------------------------- # -######################################################################### -muls64_alg: -# load temp registers with operands - mov.l %d0,%d2 # mr in d2 - mov.l %d0,%d3 # mr in d3 - mov.l %d1,%d4 # md in d4 - swap %d3 # hi(mr) in lo d3 - swap %d4 # hi(md) in lo d4 - -# complete necessary multiplies: - mulu.w %d1,%d0 # [1] lo(mr) * lo(md) - mulu.w %d3,%d1 # [2] hi(mr) * lo(md) - mulu.w %d4,%d2 # [3] lo(mr) * hi(md) - mulu.w %d4,%d3 # [4] hi(mr) * hi(md) - -# add lo portions of [2],[3] to hi portion of [1]. -# add carries produced from these adds to [4]. -# lo([1]) is the final lo 16 bits of the result. - clr.l %d4 # load d4 w/ zero value - swap %d0 # hi([1]) <==> lo([1]) - add.w %d1,%d0 # hi([1]) + lo([2]) - addx.l %d4,%d3 # [4] + carry - add.w %d2,%d0 # hi([1]) + lo([3]) - addx.l %d4,%d3 # [4] + carry - swap %d0 # lo([1]) <==> hi([1]) - -# lo portions of [2],[3] have been added in to final result. -# now, clear lo, put hi in lo reg, and add to [4] - clr.w %d1 # clear lo([2]) - clr.w %d2 # clear hi([3]) - swap %d1 # hi([2]) in lo d1 - swap %d2 # hi([3]) in lo d2 - add.l %d2,%d1 # [4] + hi([2]) - add.l %d3,%d1 # [4] + hi([3]) - - tst.b %d5 # should result be signed? - beq.b muls64_done # no - -# result should be a signed negative number. -# compute 2's complement of the unsigned number: -# -negate all bits and add 1 -muls64_neg: - not.l %d0 # negate lo(result) bits - not.l %d1 # negate hi(result) bits - addq.l &1,%d0 # add 1 to lo(result) - addx.l %d4,%d1 # add carry to hi(result) - -muls64_done: - mov.w MUL64_CC(%a6),%d4 - andi.b &0x10,%d4 # keep old 'X' bit - tst.l %d1 # may set 'N' bit - bpl.b muls64_ddone - ori.b &0x8,%d4 # set 'N' bit -muls64_ddone: - mov.w %d4,%cc - -# here, the result is in d1 and d0. the current strategy is to save -# the values at the location pointed to by a0. -# use movm here to not disturb the condition codes. -muls64_end: - exg %d1,%d0 - movm.l &0x0003,([0x10,%a6]) # save result at (a0) - -# EPILOGUE BEGIN ######################################################## -# fmovm.l (%sp)+,&0x0 # restore no fpregs - movm.l (%sp)+,&0x003c # restore d2-d5 - unlk %a6 -# EPILOGUE END ########################################################## - - rts - -# one or both of the operands is zero so the result is also zero. -# save the zero result to the register file and set the 'Z' ccode bit. -muls64_zero: - clr.l %d0 - clr.l %d1 - - mov.w MUL64_CC(%a6),%d4 - andi.b &0x10,%d4 - ori.b &0x4,%d4 - mov.w %d4,%cc # set 'Z' ccode bit - - bra.b muls64_end - -######################################################################### -# XDEF **************************************************************** # -# _060LSP__cmp2_Ab_(): Emulate "cmp2.b An,<ea>". # -# _060LSP__cmp2_Aw_(): Emulate "cmp2.w An,<ea>". # -# _060LSP__cmp2_Al_(): Emulate "cmp2.l An,<ea>". # -# _060LSP__cmp2_Db_(): Emulate "cmp2.b Dn,<ea>". # -# _060LSP__cmp2_Dw_(): Emulate "cmp2.w Dn,<ea>". # -# _060LSP__cmp2_Dl_(): Emulate "cmp2.l Dn,<ea>". # -# # -# This is the library version which is accessed as a subroutine # -# and therefore does not work exactly like the 680X0 "cmp2" # -# instruction. # -# # -# XREF **************************************************************** # -# None # -# # -# INPUT *************************************************************** # -# 0x4(sp) = Rn # -# 0x8(sp) = pointer to boundary pair # -# # -# OUTPUT ************************************************************** # -# cc = condition codes are set correctly # -# # -# ALGORITHM *********************************************************** # -# In the interest of simplicity, all operands are converted to # -# longword size whether the operation is byte, word, or long. The # -# bounds are sign extended accordingly. If Rn is a data regsiter, Rn is # -# also sign extended. If Rn is an address register, it need not be sign # -# extended since the full register is always used. # -# The condition codes are set correctly before the final "rts". # -# # -######################################################################### - -set CMP2_CC, -4 - - global _060LSP__cmp2_Ab_ -_060LSP__cmp2_Ab_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.b ([0xc,%a6],0x0),%d0 - mov.b ([0xc,%a6],0x1),%d1 - - extb.l %d0 # sign extend lo bnd - extb.l %d1 # sign extend hi bnd - bra.w l_cmp2_cmp # go do the compare emulation - - global _060LSP__cmp2_Aw_ -_060LSP__cmp2_Aw_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.w ([0xc,%a6],0x0),%d0 - mov.w ([0xc,%a6],0x2),%d1 - - ext.l %d0 # sign extend lo bnd - ext.l %d1 # sign extend hi bnd - bra.w l_cmp2_cmp # go do the compare emulation - - global _060LSP__cmp2_Al_ -_060LSP__cmp2_Al_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.l ([0xc,%a6],0x0),%d0 - mov.l ([0xc,%a6],0x4),%d1 - bra.w l_cmp2_cmp # go do the compare emulation - - global _060LSP__cmp2_Db_ -_060LSP__cmp2_Db_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.b ([0xc,%a6],0x0),%d0 - mov.b ([0xc,%a6],0x1),%d1 - - extb.l %d0 # sign extend lo bnd - extb.l %d1 # sign extend hi bnd - -# operation is a data register compare. -# sign extend byte to long so we can do simple longword compares. - extb.l %d2 # sign extend data byte - bra.w l_cmp2_cmp # go do the compare emulation - - global _060LSP__cmp2_Dw_ -_060LSP__cmp2_Dw_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.w ([0xc,%a6],0x0),%d0 - mov.w ([0xc,%a6],0x2),%d1 - - ext.l %d0 # sign extend lo bnd - ext.l %d1 # sign extend hi bnd - -# operation is a data register compare. -# sign extend word to long so we can do simple longword compares. - ext.l %d2 # sign extend data word - bra.w l_cmp2_cmp # go emulate compare - - global _060LSP__cmp2_Dl_ -_060LSP__cmp2_Dl_: - -# PROLOGUE BEGIN ######################################################## - link.w %a6,&-4 - movm.l &0x3800,-(%sp) # save d2-d4 -# fmovm.l &0x0,-(%sp) # save no fpregs -# PROLOGUE END ########################################################## - - mov.w %cc,CMP2_CC(%a6) - mov.l 0x8(%a6), %d2 # get regval - - mov.l ([0xc,%a6],0x0),%d0 - mov.l ([0xc,%a6],0x4),%d1 - -# -# To set the ccodes correctly: -# (1) save 'Z' bit from (Rn - lo) -# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi)) -# (3) keep 'X', 'N', and 'V' from before instruction -# (4) combine ccodes -# -l_cmp2_cmp: - sub.l %d0, %d2 # (Rn - lo) - mov.w %cc, %d3 # fetch resulting ccodes - andi.b &0x4, %d3 # keep 'Z' bit - sub.l %d0, %d1 # (hi - lo) - cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi)) - - mov.w %cc, %d4 # fetch resulting ccodes - or.b %d4, %d3 # combine w/ earlier ccodes - andi.b &0x5, %d3 # keep 'Z' and 'N' - - mov.w CMP2_CC(%a6), %d4 # fetch old ccodes - andi.b &0x1a, %d4 # keep 'X','N','V' bits - or.b %d3, %d4 # insert new ccodes - mov.w %d4,%cc # save new ccodes - -# EPILOGUE BEGIN ######################################################## -# fmovm.l (%sp)+,&0x0 # restore no fpregs - movm.l (%sp)+,&0x001c # restore d2-d4 - unlk %a6 -# EPILOGUE END ########################################################## - - rts |