18c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28c2ecf20Sopenharmony_ciMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 38c2ecf20Sopenharmony_ciM68000 Hi-Performance Microprocessor Division 48c2ecf20Sopenharmony_ciM68060 Software Package 58c2ecf20Sopenharmony_ciProduction Release P1.00 -- October 10, 1994 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciM68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciTHE SOFTWARE is provided on an "AS IS" basis and without warranty. 108c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law, 118c2ecf20Sopenharmony_ciMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 128c2ecf20Sopenharmony_ciINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 138c2ecf20Sopenharmony_ciand any warranty against infringement with regard to the SOFTWARE 148c2ecf20Sopenharmony_ci(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law, 178c2ecf20Sopenharmony_ciIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 188c2ecf20Sopenharmony_ci(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 198c2ecf20Sopenharmony_ciBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) 208c2ecf20Sopenharmony_ciARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 218c2ecf20Sopenharmony_ciMotorola assumes no responsibility for the maintenance and support of the SOFTWARE. 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE 248c2ecf20Sopenharmony_ciso long as this entire notice is retained without alteration in any modified and/or 258c2ecf20Sopenharmony_ciredistributed versions, and that such modified versions are clearly identified as such. 268c2ecf20Sopenharmony_ciNo licenses are granted by implication, estoppel or otherwise under any patents 278c2ecf20Sopenharmony_cior trademarks of Motorola, Inc. 288c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 298c2ecf20Sopenharmony_ci# litop.s: 308c2ecf20Sopenharmony_ci# This file is appended to the top of the 060FPLSP package 318c2ecf20Sopenharmony_ci# and contains the entry points into the package. The user, in 328c2ecf20Sopenharmony_ci# effect, branches to one of the branch table entries located here. 338c2ecf20Sopenharmony_ci# 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci bra.l _060LSP__idivs64_ 368c2ecf20Sopenharmony_ci short 0x0000 378c2ecf20Sopenharmony_ci bra.l _060LSP__idivu64_ 388c2ecf20Sopenharmony_ci short 0x0000 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci bra.l _060LSP__imuls64_ 418c2ecf20Sopenharmony_ci short 0x0000 428c2ecf20Sopenharmony_ci bra.l _060LSP__imulu64_ 438c2ecf20Sopenharmony_ci short 0x0000 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Ab_ 468c2ecf20Sopenharmony_ci short 0x0000 478c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Aw_ 488c2ecf20Sopenharmony_ci short 0x0000 498c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Al_ 508c2ecf20Sopenharmony_ci short 0x0000 518c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Db_ 528c2ecf20Sopenharmony_ci short 0x0000 538c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Dw_ 548c2ecf20Sopenharmony_ci short 0x0000 558c2ecf20Sopenharmony_ci bra.l _060LSP__cmp2_Dl_ 568c2ecf20Sopenharmony_ci short 0x0000 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci# leave room for future possible aditions. 598c2ecf20Sopenharmony_ci align 0x200 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci######################################################################### 628c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 638c2ecf20Sopenharmony_ci# _060LSP__idivu64_(): Emulate 64-bit unsigned div instruction. # 648c2ecf20Sopenharmony_ci# _060LSP__idivs64_(): Emulate 64-bit signed div instruction. # 658c2ecf20Sopenharmony_ci# # 668c2ecf20Sopenharmony_ci# This is the library version which is accessed as a subroutine # 678c2ecf20Sopenharmony_ci# and therefore does not work exactly like the 680X0 div{s,u}.l # 688c2ecf20Sopenharmony_ci# 64-bit divide instruction. # 698c2ecf20Sopenharmony_ci# # 708c2ecf20Sopenharmony_ci# XREF **************************************************************** # 718c2ecf20Sopenharmony_ci# None. # 728c2ecf20Sopenharmony_ci# # 738c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 748c2ecf20Sopenharmony_ci# 0x4(sp) = divisor # 758c2ecf20Sopenharmony_ci# 0x8(sp) = hi(dividend) # 768c2ecf20Sopenharmony_ci# 0xc(sp) = lo(dividend) # 778c2ecf20Sopenharmony_ci# 0x10(sp) = pointer to location to place quotient/remainder # 788c2ecf20Sopenharmony_ci# # 798c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 808c2ecf20Sopenharmony_ci# 0x10(sp) = points to location of remainder/quotient. # 818c2ecf20Sopenharmony_ci# remainder is in first longword, quotient is in 2nd. # 828c2ecf20Sopenharmony_ci# # 838c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 848c2ecf20Sopenharmony_ci# If the operands are signed, make them unsigned and save the # 858c2ecf20Sopenharmony_ci# sign info for later. Separate out special cases like divide-by-zero # 868c2ecf20Sopenharmony_ci# or 32-bit divides if possible. Else, use a special math algorithm # 878c2ecf20Sopenharmony_ci# to calculate the result. # 888c2ecf20Sopenharmony_ci# Restore sign info if signed instruction. Set the condition # 898c2ecf20Sopenharmony_ci# codes before performing the final "rts". If the divisor was equal to # 908c2ecf20Sopenharmony_ci# zero, then perform a divide-by-zero using a 16-bit implemented # 918c2ecf20Sopenharmony_ci# divide instruction. This way, the operating system can record that # 928c2ecf20Sopenharmony_ci# the event occurred even though it may not point to the correct place. # 938c2ecf20Sopenharmony_ci# # 948c2ecf20Sopenharmony_ci######################################################################### 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ciset POSNEG, -1 978c2ecf20Sopenharmony_ciset NDIVISOR, -2 988c2ecf20Sopenharmony_ciset NDIVIDEND, -3 998c2ecf20Sopenharmony_ciset DDSECOND, -4 1008c2ecf20Sopenharmony_ciset DDNORMAL, -8 1018c2ecf20Sopenharmony_ciset DDQUOTIENT, -12 1028c2ecf20Sopenharmony_ciset DIV64_CC, -16 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci########## 1058c2ecf20Sopenharmony_ci# divs.l # 1068c2ecf20Sopenharmony_ci########## 1078c2ecf20Sopenharmony_ci global _060LSP__idivs64_ 1088c2ecf20Sopenharmony_ci_060LSP__idivs64_: 1098c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 1108c2ecf20Sopenharmony_ci link.w %a6,&-16 1118c2ecf20Sopenharmony_ci movm.l &0x3f00,-(%sp) # save d2-d7 1128c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 1138c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci mov.w %cc,DIV64_CC(%a6) 1168c2ecf20Sopenharmony_ci st POSNEG(%a6) # signed operation 1178c2ecf20Sopenharmony_ci bra.b ldiv64_cont 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci########## 1208c2ecf20Sopenharmony_ci# divu.l # 1218c2ecf20Sopenharmony_ci########## 1228c2ecf20Sopenharmony_ci global _060LSP__idivu64_ 1238c2ecf20Sopenharmony_ci_060LSP__idivu64_: 1248c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 1258c2ecf20Sopenharmony_ci link.w %a6,&-16 1268c2ecf20Sopenharmony_ci movm.l &0x3f00,-(%sp) # save d2-d7 1278c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 1288c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci mov.w %cc,DIV64_CC(%a6) 1318c2ecf20Sopenharmony_ci sf POSNEG(%a6) # unsigned operation 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cildiv64_cont: 1348c2ecf20Sopenharmony_ci mov.l 0x8(%a6),%d7 # fetch divisor 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci beq.w ldiv64eq0 # divisor is = 0!!! 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci mov.l 0xc(%a6), %d5 # get dividend hi 1398c2ecf20Sopenharmony_ci mov.l 0x10(%a6), %d6 # get dividend lo 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci# separate signed and unsigned divide 1428c2ecf20Sopenharmony_ci tst.b POSNEG(%a6) # signed or unsigned? 1438c2ecf20Sopenharmony_ci beq.b ldspecialcases # use positive divide 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci# save the sign of the divisor 1468c2ecf20Sopenharmony_ci# make divisor unsigned if it's negative 1478c2ecf20Sopenharmony_ci tst.l %d7 # chk sign of divisor 1488c2ecf20Sopenharmony_ci slt NDIVISOR(%a6) # save sign of divisor 1498c2ecf20Sopenharmony_ci bpl.b ldsgndividend 1508c2ecf20Sopenharmony_ci neg.l %d7 # complement negative divisor 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci# save the sign of the dividend 1538c2ecf20Sopenharmony_ci# make dividend unsigned if it's negative 1548c2ecf20Sopenharmony_cildsgndividend: 1558c2ecf20Sopenharmony_ci tst.l %d5 # chk sign of hi(dividend) 1568c2ecf20Sopenharmony_ci slt NDIVIDEND(%a6) # save sign of dividend 1578c2ecf20Sopenharmony_ci bpl.b ldspecialcases 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci mov.w &0x0, %cc # clear 'X' cc bit 1608c2ecf20Sopenharmony_ci negx.l %d6 # complement signed dividend 1618c2ecf20Sopenharmony_ci negx.l %d5 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci# extract some special cases: 1648c2ecf20Sopenharmony_ci# - is (dividend == 0) ? 1658c2ecf20Sopenharmony_ci# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div) 1668c2ecf20Sopenharmony_cildspecialcases: 1678c2ecf20Sopenharmony_ci tst.l %d5 # is (hi(dividend) == 0) 1688c2ecf20Sopenharmony_ci bne.b ldnormaldivide # no, so try it the long way 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci tst.l %d6 # is (lo(dividend) == 0), too 1718c2ecf20Sopenharmony_ci beq.w lddone # yes, so (dividend == 0) 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci cmp.l %d7,%d6 # is (divisor <= lo(dividend)) 1748c2ecf20Sopenharmony_ci bls.b ld32bitdivide # yes, so use 32 bit divide 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci exg %d5,%d6 # q = 0, r = dividend 1778c2ecf20Sopenharmony_ci bra.w ldivfinish # can't divide, we're done. 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cild32bitdivide: 1808c2ecf20Sopenharmony_ci tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div! 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci bra.b ldivfinish 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cildnormaldivide: 1858c2ecf20Sopenharmony_ci# last special case: 1868c2ecf20Sopenharmony_ci# - is hi(dividend) >= divisor ? if yes, then overflow 1878c2ecf20Sopenharmony_ci cmp.l %d7,%d5 1888c2ecf20Sopenharmony_ci bls.b lddovf # answer won't fit in 32 bits 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci# perform the divide algorithm: 1918c2ecf20Sopenharmony_ci bsr.l ldclassical # do int divide 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci# separate into signed and unsigned finishes. 1948c2ecf20Sopenharmony_cildivfinish: 1958c2ecf20Sopenharmony_ci tst.b POSNEG(%a6) # do divs, divu separately 1968c2ecf20Sopenharmony_ci beq.b lddone # divu has no processing!!! 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci# it was a divs.l, so ccode setting is a little more complicated... 1998c2ecf20Sopenharmony_ci tst.b NDIVIDEND(%a6) # remainder has same sign 2008c2ecf20Sopenharmony_ci beq.b ldcc # as dividend. 2018c2ecf20Sopenharmony_ci neg.l %d5 # sgn(rem) = sgn(dividend) 2028c2ecf20Sopenharmony_cildcc: 2038c2ecf20Sopenharmony_ci mov.b NDIVISOR(%a6), %d0 2048c2ecf20Sopenharmony_ci eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative 2058c2ecf20Sopenharmony_ci beq.b ldqpos # branch to quot positive 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci# 0x80000000 is the largest number representable as a 32-bit negative 2088c2ecf20Sopenharmony_ci# number. the negative of 0x80000000 is 0x80000000. 2098c2ecf20Sopenharmony_ci cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits? 2108c2ecf20Sopenharmony_ci bhi.b lddovf 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci neg.l %d6 # make (-quot) 2's comp 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci bra.b lddone 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cildqpos: 2178c2ecf20Sopenharmony_ci btst &0x1f, %d6 # will (+quot) fit in 32 bits? 2188c2ecf20Sopenharmony_ci bne.b lddovf 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cilddone: 2218c2ecf20Sopenharmony_ci# if the register numbers are the same, only the quotient gets saved. 2228c2ecf20Sopenharmony_ci# so, if we always save the quotient second, we save ourselves a cmp&beq 2238c2ecf20Sopenharmony_ci andi.w &0x10,DIV64_CC(%a6) 2248c2ecf20Sopenharmony_ci mov.w DIV64_CC(%a6),%cc 2258c2ecf20Sopenharmony_ci tst.l %d6 # may set 'N' ccode bit 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci# here, the result is in d1 and d0. the current strategy is to save 2288c2ecf20Sopenharmony_ci# the values at the location pointed to by a0. 2298c2ecf20Sopenharmony_ci# use movm here to not disturb the condition codes. 2308c2ecf20Sopenharmony_cildexit: 2318c2ecf20Sopenharmony_ci movm.l &0x0060,([0x14,%a6]) # save result 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci# EPILOGUE BEGIN ######################################################## 2348c2ecf20Sopenharmony_ci# fmovm.l (%sp)+,&0x0 # restore no fpregs 2358c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x00fc # restore d2-d7 2368c2ecf20Sopenharmony_ci unlk %a6 2378c2ecf20Sopenharmony_ci# EPILOGUE END ########################################################## 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci rts 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci# the result should be the unchanged dividend 2428c2ecf20Sopenharmony_cilddovf: 2438c2ecf20Sopenharmony_ci mov.l 0xc(%a6), %d5 # get dividend hi 2448c2ecf20Sopenharmony_ci mov.l 0x10(%a6), %d6 # get dividend lo 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci andi.w &0x1c,DIV64_CC(%a6) 2478c2ecf20Sopenharmony_ci ori.w &0x02,DIV64_CC(%a6) # set 'V' ccode bit 2488c2ecf20Sopenharmony_ci mov.w DIV64_CC(%a6),%cc 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci bra.b ldexit 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cildiv64eq0: 2538c2ecf20Sopenharmony_ci mov.l 0xc(%a6),([0x14,%a6]) 2548c2ecf20Sopenharmony_ci mov.l 0x10(%a6),([0x14,%a6],0x4) 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci mov.w DIV64_CC(%a6),%cc 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci# EPILOGUE BEGIN ######################################################## 2598c2ecf20Sopenharmony_ci# fmovm.l (%sp)+,&0x0 # restore no fpregs 2608c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x00fc # restore d2-d7 2618c2ecf20Sopenharmony_ci unlk %a6 2628c2ecf20Sopenharmony_ci# EPILOGUE END ########################################################## 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci divu.w &0x0,%d0 # force a divbyzero exception 2658c2ecf20Sopenharmony_ci rts 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci########################################################################### 2688c2ecf20Sopenharmony_ci######################################################################### 2698c2ecf20Sopenharmony_ci# This routine uses the 'classical' Algorithm D from Donald Knuth's # 2708c2ecf20Sopenharmony_ci# Art of Computer Programming, vol II, Seminumerical Algorithms. # 2718c2ecf20Sopenharmony_ci# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, # 2728c2ecf20Sopenharmony_ci# where U,V are words of the quadword dividend and longword divisor, # 2738c2ecf20Sopenharmony_ci# and U1, V1 are the most significant words. # 2748c2ecf20Sopenharmony_ci# # 2758c2ecf20Sopenharmony_ci# The most sig. longword of the 64 bit dividend must be in %d5, least # 2768c2ecf20Sopenharmony_ci# in %d6. The divisor must be in the variable ddivisor, and the # 2778c2ecf20Sopenharmony_ci# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). # 2788c2ecf20Sopenharmony_ci# The quotient is returned in %d6, remainder in %d5, unless the # 2798c2ecf20Sopenharmony_ci# v (overflow) bit is set in the saved %ccr. If overflow, the dividend # 2808c2ecf20Sopenharmony_ci# is unchanged. # 2818c2ecf20Sopenharmony_ci######################################################################### 2828c2ecf20Sopenharmony_cildclassical: 2838c2ecf20Sopenharmony_ci# if the divisor msw is 0, use simpler algorithm then the full blown 2848c2ecf20Sopenharmony_ci# one at ddknuth: 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci cmpi.l %d7, &0xffff 2878c2ecf20Sopenharmony_ci bhi.b lddknuth # go use D. Knuth algorithm 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci# Since the divisor is only a word (and larger than the mslw of the dividend), 2908c2ecf20Sopenharmony_ci# a simpler algorithm may be used : 2918c2ecf20Sopenharmony_ci# In the general case, four quotient words would be created by 2928c2ecf20Sopenharmony_ci# dividing the divisor word into each dividend word. In this case, 2938c2ecf20Sopenharmony_ci# the first two quotient words must be zero, or overflow would occur. 2948c2ecf20Sopenharmony_ci# Since we already checked this case above, we can treat the most significant 2958c2ecf20Sopenharmony_ci# longword of the dividend as (0) remainder (see Knuth) and merely complete 2968c2ecf20Sopenharmony_ci# the last two divisions to get a quotient longword and word remainder: 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci clr.l %d1 2998c2ecf20Sopenharmony_ci swap %d5 # same as r*b if previous step rqd 3008c2ecf20Sopenharmony_ci swap %d6 # get u3 to lsw position 3018c2ecf20Sopenharmony_ci mov.w %d6, %d5 # rb + u3 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci divu.w %d7, %d5 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci mov.w %d5, %d1 # first quotient word 3068c2ecf20Sopenharmony_ci swap %d6 # get u4 3078c2ecf20Sopenharmony_ci mov.w %d6, %d5 # rb + u4 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci divu.w %d7, %d5 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci swap %d1 3128c2ecf20Sopenharmony_ci mov.w %d5, %d1 # 2nd quotient 'digit' 3138c2ecf20Sopenharmony_ci clr.w %d5 3148c2ecf20Sopenharmony_ci swap %d5 # now remainder 3158c2ecf20Sopenharmony_ci mov.l %d1, %d6 # and quotient 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci rts 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cilddknuth: 3208c2ecf20Sopenharmony_ci# In this algorithm, the divisor is treated as a 2 digit (word) number 3218c2ecf20Sopenharmony_ci# which is divided into a 3 digit (word) dividend to get one quotient 3228c2ecf20Sopenharmony_ci# digit (word). After subtraction, the dividend is shifted and the 3238c2ecf20Sopenharmony_ci# process repeated. Before beginning, the divisor and quotient are 3248c2ecf20Sopenharmony_ci# 'normalized' so that the process of estimating the quotient digit 3258c2ecf20Sopenharmony_ci# will yield verifiably correct results.. 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci clr.l DDNORMAL(%a6) # count of shifts for normalization 3288c2ecf20Sopenharmony_ci clr.b DDSECOND(%a6) # clear flag for quotient digits 3298c2ecf20Sopenharmony_ci clr.l %d1 # %d1 will hold trial quotient 3308c2ecf20Sopenharmony_cilddnchk: 3318c2ecf20Sopenharmony_ci btst &31, %d7 # must we normalize? first word of 3328c2ecf20Sopenharmony_ci bne.b lddnormalized # divisor (V1) must be >= 65536/2 3338c2ecf20Sopenharmony_ci addq.l &0x1, DDNORMAL(%a6) # count normalization shifts 3348c2ecf20Sopenharmony_ci lsl.l &0x1, %d7 # shift the divisor 3358c2ecf20Sopenharmony_ci lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2 3368c2ecf20Sopenharmony_ci roxl.l &0x1, %d5 # shift u1,u2 3378c2ecf20Sopenharmony_ci bra.w lddnchk 3388c2ecf20Sopenharmony_cilddnormalized: 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci# Now calculate an estimate of the quotient words (msw first, then lsw). 3418c2ecf20Sopenharmony_ci# The comments use subscripts for the first quotient digit determination. 3428c2ecf20Sopenharmony_ci mov.l %d7, %d3 # divisor 3438c2ecf20Sopenharmony_ci mov.l %d5, %d2 # dividend mslw 3448c2ecf20Sopenharmony_ci swap %d2 3458c2ecf20Sopenharmony_ci swap %d3 3468c2ecf20Sopenharmony_ci cmp.w %d2, %d3 # V1 = U1 ? 3478c2ecf20Sopenharmony_ci bne.b lddqcalc1 3488c2ecf20Sopenharmony_ci mov.w &0xffff, %d1 # use max trial quotient word 3498c2ecf20Sopenharmony_ci bra.b lddadj0 3508c2ecf20Sopenharmony_cilddqcalc1: 3518c2ecf20Sopenharmony_ci mov.l %d5, %d1 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci divu.w %d3, %d1 # use quotient of mslw/msw 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci andi.l &0x0000ffff, %d1 # zero any remainder 3568c2ecf20Sopenharmony_cilddadj0: 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci# now test the trial quotient and adjust. This step plus the 3598c2ecf20Sopenharmony_ci# normalization assures (according to Knuth) that the trial 3608c2ecf20Sopenharmony_ci# quotient will be at worst 1 too large. 3618c2ecf20Sopenharmony_ci mov.l %d6, -(%sp) 3628c2ecf20Sopenharmony_ci clr.w %d6 # word u3 left 3638c2ecf20Sopenharmony_ci swap %d6 # in lsw position 3648c2ecf20Sopenharmony_cilddadj1: mov.l %d7, %d3 3658c2ecf20Sopenharmony_ci mov.l %d1, %d2 3668c2ecf20Sopenharmony_ci mulu.w %d7, %d2 # V2q 3678c2ecf20Sopenharmony_ci swap %d3 3688c2ecf20Sopenharmony_ci mulu.w %d1, %d3 # V1q 3698c2ecf20Sopenharmony_ci mov.l %d5, %d4 # U1U2 3708c2ecf20Sopenharmony_ci sub.l %d3, %d4 # U1U2 - V1q 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci swap %d4 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci mov.w %d4,%d0 3758c2ecf20Sopenharmony_ci mov.w %d6,%d4 # insert lower word (U3) 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci tst.w %d0 # is upper word set? 3788c2ecf20Sopenharmony_ci bne.w lddadjd1 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci# add.l %d6, %d4 # (U1U2 - V1q) + U3 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci cmp.l %d2, %d4 3838c2ecf20Sopenharmony_ci bls.b lddadjd1 # is V2q > (U1U2-V1q) + U3 ? 3848c2ecf20Sopenharmony_ci subq.l &0x1, %d1 # yes, decrement and recheck 3858c2ecf20Sopenharmony_ci bra.b lddadj1 3868c2ecf20Sopenharmony_cilddadjd1: 3878c2ecf20Sopenharmony_ci# now test the word by multiplying it by the divisor (V1V2) and comparing 3888c2ecf20Sopenharmony_ci# the 3 digit (word) result with the current dividend words 3898c2ecf20Sopenharmony_ci mov.l %d5, -(%sp) # save %d5 (%d6 already saved) 3908c2ecf20Sopenharmony_ci mov.l %d1, %d6 3918c2ecf20Sopenharmony_ci swap %d6 # shift answer to ms 3 words 3928c2ecf20Sopenharmony_ci mov.l %d7, %d5 3938c2ecf20Sopenharmony_ci bsr.l ldmm2 3948c2ecf20Sopenharmony_ci mov.l %d5, %d2 # now %d2,%d3 are trial*divisor 3958c2ecf20Sopenharmony_ci mov.l %d6, %d3 3968c2ecf20Sopenharmony_ci mov.l (%sp)+, %d5 # restore dividend 3978c2ecf20Sopenharmony_ci mov.l (%sp)+, %d6 3988c2ecf20Sopenharmony_ci sub.l %d3, %d6 3998c2ecf20Sopenharmony_ci subx.l %d2, %d5 # subtract double precision 4008c2ecf20Sopenharmony_ci bcc ldd2nd # no carry, do next quotient digit 4018c2ecf20Sopenharmony_ci subq.l &0x1, %d1 # q is one too large 4028c2ecf20Sopenharmony_ci# need to add back divisor longword to current ms 3 digits of dividend 4038c2ecf20Sopenharmony_ci# - according to Knuth, this is done only 2 out of 65536 times for random 4048c2ecf20Sopenharmony_ci# divisor, dividend selection. 4058c2ecf20Sopenharmony_ci clr.l %d2 4068c2ecf20Sopenharmony_ci mov.l %d7, %d3 4078c2ecf20Sopenharmony_ci swap %d3 4088c2ecf20Sopenharmony_ci clr.w %d3 # %d3 now ls word of divisor 4098c2ecf20Sopenharmony_ci add.l %d3, %d6 # aligned with 3rd word of dividend 4108c2ecf20Sopenharmony_ci addx.l %d2, %d5 4118c2ecf20Sopenharmony_ci mov.l %d7, %d3 4128c2ecf20Sopenharmony_ci clr.w %d3 # %d3 now ms word of divisor 4138c2ecf20Sopenharmony_ci swap %d3 # aligned with 2nd word of dividend 4148c2ecf20Sopenharmony_ci add.l %d3, %d5 4158c2ecf20Sopenharmony_cildd2nd: 4168c2ecf20Sopenharmony_ci tst.b DDSECOND(%a6) # both q words done? 4178c2ecf20Sopenharmony_ci bne.b lddremain 4188c2ecf20Sopenharmony_ci# first quotient digit now correct. store digit and shift the 4198c2ecf20Sopenharmony_ci# (subtracted) dividend 4208c2ecf20Sopenharmony_ci mov.w %d1, DDQUOTIENT(%a6) 4218c2ecf20Sopenharmony_ci clr.l %d1 4228c2ecf20Sopenharmony_ci swap %d5 4238c2ecf20Sopenharmony_ci swap %d6 4248c2ecf20Sopenharmony_ci mov.w %d6, %d5 4258c2ecf20Sopenharmony_ci clr.w %d6 4268c2ecf20Sopenharmony_ci st DDSECOND(%a6) # second digit 4278c2ecf20Sopenharmony_ci bra.w lddnormalized 4288c2ecf20Sopenharmony_cilddremain: 4298c2ecf20Sopenharmony_ci# add 2nd word to quotient, get the remainder. 4308c2ecf20Sopenharmony_ci mov.w %d1, DDQUOTIENT+2(%a6) 4318c2ecf20Sopenharmony_ci# shift down one word/digit to renormalize remainder. 4328c2ecf20Sopenharmony_ci mov.w %d5, %d6 4338c2ecf20Sopenharmony_ci swap %d6 4348c2ecf20Sopenharmony_ci swap %d5 4358c2ecf20Sopenharmony_ci mov.l DDNORMAL(%a6), %d7 # get norm shift count 4368c2ecf20Sopenharmony_ci beq.b lddrn 4378c2ecf20Sopenharmony_ci subq.l &0x1, %d7 # set for loop count 4388c2ecf20Sopenharmony_cilddnlp: 4398c2ecf20Sopenharmony_ci lsr.l &0x1, %d5 # shift into %d6 4408c2ecf20Sopenharmony_ci roxr.l &0x1, %d6 4418c2ecf20Sopenharmony_ci dbf %d7, lddnlp 4428c2ecf20Sopenharmony_cilddrn: 4438c2ecf20Sopenharmony_ci mov.l %d6, %d5 # remainder 4448c2ecf20Sopenharmony_ci mov.l DDQUOTIENT(%a6), %d6 # quotient 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci rts 4478c2ecf20Sopenharmony_cildmm2: 4488c2ecf20Sopenharmony_ci# factors for the 32X32->64 multiplication are in %d5 and %d6. 4498c2ecf20Sopenharmony_ci# returns 64 bit result in %d5 (hi) %d6(lo). 4508c2ecf20Sopenharmony_ci# destroys %d2,%d3,%d4. 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci# multiply hi,lo words of each factor to get 4 intermediate products 4538c2ecf20Sopenharmony_ci mov.l %d6, %d2 4548c2ecf20Sopenharmony_ci mov.l %d6, %d3 4558c2ecf20Sopenharmony_ci mov.l %d5, %d4 4568c2ecf20Sopenharmony_ci swap %d3 4578c2ecf20Sopenharmony_ci swap %d4 4588c2ecf20Sopenharmony_ci mulu.w %d5, %d6 # %d6 <- lsw*lsw 4598c2ecf20Sopenharmony_ci mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source 4608c2ecf20Sopenharmony_ci mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest 4618c2ecf20Sopenharmony_ci mulu.w %d4, %d3 # %d3 <- msw*msw 4628c2ecf20Sopenharmony_ci# now use swap and addx to consolidate to two longwords 4638c2ecf20Sopenharmony_ci clr.l %d4 4648c2ecf20Sopenharmony_ci swap %d6 4658c2ecf20Sopenharmony_ci add.w %d5, %d6 # add msw of l*l to lsw of m*l product 4668c2ecf20Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 4678c2ecf20Sopenharmony_ci add.w %d2, %d6 # add in lsw of other m*l product 4688c2ecf20Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 4698c2ecf20Sopenharmony_ci swap %d6 # %d6 is low 32 bits of final product 4708c2ecf20Sopenharmony_ci clr.w %d5 4718c2ecf20Sopenharmony_ci clr.w %d2 # lsw of two mixed products used, 4728c2ecf20Sopenharmony_ci swap %d5 # now use msws of longwords 4738c2ecf20Sopenharmony_ci swap %d2 4748c2ecf20Sopenharmony_ci add.l %d2, %d5 4758c2ecf20Sopenharmony_ci add.l %d3, %d5 # %d5 now ms 32 bits of final product 4768c2ecf20Sopenharmony_ci rts 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci######################################################################### 4798c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 4808c2ecf20Sopenharmony_ci# _060LSP__imulu64_(): Emulate 64-bit unsigned mul instruction # 4818c2ecf20Sopenharmony_ci# _060LSP__imuls64_(): Emulate 64-bit signed mul instruction. # 4828c2ecf20Sopenharmony_ci# # 4838c2ecf20Sopenharmony_ci# This is the library version which is accessed as a subroutine # 4848c2ecf20Sopenharmony_ci# and therefore does not work exactly like the 680X0 mul{s,u}.l # 4858c2ecf20Sopenharmony_ci# 64-bit multiply instruction. # 4868c2ecf20Sopenharmony_ci# # 4878c2ecf20Sopenharmony_ci# XREF **************************************************************** # 4888c2ecf20Sopenharmony_ci# None # 4898c2ecf20Sopenharmony_ci# # 4908c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 4918c2ecf20Sopenharmony_ci# 0x4(sp) = multiplier # 4928c2ecf20Sopenharmony_ci# 0x8(sp) = multiplicand # 4938c2ecf20Sopenharmony_ci# 0xc(sp) = pointer to location to place 64-bit result # 4948c2ecf20Sopenharmony_ci# # 4958c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 4968c2ecf20Sopenharmony_ci# 0xc(sp) = points to location of 64-bit result # 4978c2ecf20Sopenharmony_ci# # 4988c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 4998c2ecf20Sopenharmony_ci# Perform the multiply in pieces using 16x16->32 unsigned # 5008c2ecf20Sopenharmony_ci# multiplies and "add" instructions. # 5018c2ecf20Sopenharmony_ci# Set the condition codes as appropriate before performing an # 5028c2ecf20Sopenharmony_ci# "rts". # 5038c2ecf20Sopenharmony_ci# # 5048c2ecf20Sopenharmony_ci######################################################################### 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ciset MUL64_CC, -4 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci global _060LSP__imulu64_ 5098c2ecf20Sopenharmony_ci_060LSP__imulu64_: 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 5128c2ecf20Sopenharmony_ci link.w %a6,&-4 5138c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 5148c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 5158c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci mov.w %cc,MUL64_CC(%a6) # save incoming ccodes 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci mov.l 0x8(%a6),%d0 # store multiplier in d0 5208c2ecf20Sopenharmony_ci beq.w mulu64_zero # handle zero separately 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci mov.l 0xc(%a6),%d1 # get multiplicand in d1 5238c2ecf20Sopenharmony_ci beq.w mulu64_zero # handle zero separately 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci######################################################################### 5268c2ecf20Sopenharmony_ci# 63 32 0 # 5278c2ecf20Sopenharmony_ci# ---------------------------- # 5288c2ecf20Sopenharmony_ci# | hi(mplier) * hi(mplicand)| # 5298c2ecf20Sopenharmony_ci# ---------------------------- # 5308c2ecf20Sopenharmony_ci# ----------------------------- # 5318c2ecf20Sopenharmony_ci# | hi(mplier) * lo(mplicand) | # 5328c2ecf20Sopenharmony_ci# ----------------------------- # 5338c2ecf20Sopenharmony_ci# ----------------------------- # 5348c2ecf20Sopenharmony_ci# | lo(mplier) * hi(mplicand) | # 5358c2ecf20Sopenharmony_ci# ----------------------------- # 5368c2ecf20Sopenharmony_ci# | ----------------------------- # 5378c2ecf20Sopenharmony_ci# --|-- | lo(mplier) * lo(mplicand) | # 5388c2ecf20Sopenharmony_ci# | ----------------------------- # 5398c2ecf20Sopenharmony_ci# ======================================================== # 5408c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 5418c2ecf20Sopenharmony_ci# | hi(result) | lo(result) | # 5428c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 5438c2ecf20Sopenharmony_ci######################################################################### 5448c2ecf20Sopenharmony_cimulu64_alg: 5458c2ecf20Sopenharmony_ci# load temp registers with operands 5468c2ecf20Sopenharmony_ci mov.l %d0,%d2 # mr in d2 5478c2ecf20Sopenharmony_ci mov.l %d0,%d3 # mr in d3 5488c2ecf20Sopenharmony_ci mov.l %d1,%d4 # md in d4 5498c2ecf20Sopenharmony_ci swap %d3 # hi(mr) in lo d3 5508c2ecf20Sopenharmony_ci swap %d4 # hi(md) in lo d4 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci# complete necessary multiplies: 5538c2ecf20Sopenharmony_ci mulu.w %d1,%d0 # [1] lo(mr) * lo(md) 5548c2ecf20Sopenharmony_ci mulu.w %d3,%d1 # [2] hi(mr) * lo(md) 5558c2ecf20Sopenharmony_ci mulu.w %d4,%d2 # [3] lo(mr) * hi(md) 5568c2ecf20Sopenharmony_ci mulu.w %d4,%d3 # [4] hi(mr) * hi(md) 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1]. 5598c2ecf20Sopenharmony_ci# add carries produced from these adds to [4]. 5608c2ecf20Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result. 5618c2ecf20Sopenharmony_ci clr.l %d4 # load d4 w/ zero value 5628c2ecf20Sopenharmony_ci swap %d0 # hi([1]) <==> lo([1]) 5638c2ecf20Sopenharmony_ci add.w %d1,%d0 # hi([1]) + lo([2]) 5648c2ecf20Sopenharmony_ci addx.l %d4,%d3 # [4] + carry 5658c2ecf20Sopenharmony_ci add.w %d2,%d0 # hi([1]) + lo([3]) 5668c2ecf20Sopenharmony_ci addx.l %d4,%d3 # [4] + carry 5678c2ecf20Sopenharmony_ci swap %d0 # lo([1]) <==> hi([1]) 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci# lo portions of [2],[3] have been added in to final result. 5708c2ecf20Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4] 5718c2ecf20Sopenharmony_ci clr.w %d1 # clear lo([2]) 5728c2ecf20Sopenharmony_ci clr.w %d2 # clear hi([3]) 5738c2ecf20Sopenharmony_ci swap %d1 # hi([2]) in lo d1 5748c2ecf20Sopenharmony_ci swap %d2 # hi([3]) in lo d2 5758c2ecf20Sopenharmony_ci add.l %d2,%d1 # [4] + hi([2]) 5768c2ecf20Sopenharmony_ci add.l %d3,%d1 # [4] + hi([3]) 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci# now, grab the condition codes. only one that can be set is 'N'. 5798c2ecf20Sopenharmony_ci# 'N' CAN be set if the operation is unsigned if bit 63 is set. 5808c2ecf20Sopenharmony_ci mov.w MUL64_CC(%a6),%d4 5818c2ecf20Sopenharmony_ci andi.b &0x10,%d4 # keep old 'X' bit 5828c2ecf20Sopenharmony_ci tst.l %d1 # may set 'N' bit 5838c2ecf20Sopenharmony_ci bpl.b mulu64_ddone 5848c2ecf20Sopenharmony_ci ori.b &0x8,%d4 # set 'N' bit 5858c2ecf20Sopenharmony_cimulu64_ddone: 5868c2ecf20Sopenharmony_ci mov.w %d4,%cc 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci# here, the result is in d1 and d0. the current strategy is to save 5898c2ecf20Sopenharmony_ci# the values at the location pointed to by a0. 5908c2ecf20Sopenharmony_ci# use movm here to not disturb the condition codes. 5918c2ecf20Sopenharmony_cimulu64_end: 5928c2ecf20Sopenharmony_ci exg %d1,%d0 5938c2ecf20Sopenharmony_ci movm.l &0x0003,([0x10,%a6]) # save result 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci# EPILOGUE BEGIN ######################################################## 5968c2ecf20Sopenharmony_ci# fmovm.l (%sp)+,&0x0 # restore no fpregs 5978c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x001c # restore d2-d4 5988c2ecf20Sopenharmony_ci unlk %a6 5998c2ecf20Sopenharmony_ci# EPILOGUE END ########################################################## 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci rts 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci# one or both of the operands is zero so the result is also zero. 6048c2ecf20Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit. 6058c2ecf20Sopenharmony_cimulu64_zero: 6068c2ecf20Sopenharmony_ci clr.l %d0 6078c2ecf20Sopenharmony_ci clr.l %d1 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci mov.w MUL64_CC(%a6),%d4 6108c2ecf20Sopenharmony_ci andi.b &0x10,%d4 6118c2ecf20Sopenharmony_ci ori.b &0x4,%d4 6128c2ecf20Sopenharmony_ci mov.w %d4,%cc # set 'Z' ccode bit 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci bra.b mulu64_end 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci########## 6178c2ecf20Sopenharmony_ci# muls.l # 6188c2ecf20Sopenharmony_ci########## 6198c2ecf20Sopenharmony_ci global _060LSP__imuls64_ 6208c2ecf20Sopenharmony_ci_060LSP__imuls64_: 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 6238c2ecf20Sopenharmony_ci link.w %a6,&-4 6248c2ecf20Sopenharmony_ci movm.l &0x3c00,-(%sp) # save d2-d5 6258c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 6268c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci mov.w %cc,MUL64_CC(%a6) # save incoming ccodes 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci mov.l 0x8(%a6),%d0 # store multiplier in d0 6318c2ecf20Sopenharmony_ci beq.b mulu64_zero # handle zero separately 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci mov.l 0xc(%a6),%d1 # get multiplicand in d1 6348c2ecf20Sopenharmony_ci beq.b mulu64_zero # handle zero separately 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci clr.b %d5 # clear sign tag 6378c2ecf20Sopenharmony_ci tst.l %d0 # is multiplier negative? 6388c2ecf20Sopenharmony_ci bge.b muls64_chk_md_sgn # no 6398c2ecf20Sopenharmony_ci neg.l %d0 # make multiplier positive 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci ori.b &0x1,%d5 # save multiplier sgn 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci# the result sign is the exclusive or of the operand sign bits. 6448c2ecf20Sopenharmony_cimuls64_chk_md_sgn: 6458c2ecf20Sopenharmony_ci tst.l %d1 # is multiplicand negative? 6468c2ecf20Sopenharmony_ci bge.b muls64_alg # no 6478c2ecf20Sopenharmony_ci neg.l %d1 # make multiplicand positive 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci eori.b &0x1,%d5 # calculate correct sign 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci######################################################################### 6528c2ecf20Sopenharmony_ci# 63 32 0 # 6538c2ecf20Sopenharmony_ci# ---------------------------- # 6548c2ecf20Sopenharmony_ci# | hi(mplier) * hi(mplicand)| # 6558c2ecf20Sopenharmony_ci# ---------------------------- # 6568c2ecf20Sopenharmony_ci# ----------------------------- # 6578c2ecf20Sopenharmony_ci# | hi(mplier) * lo(mplicand) | # 6588c2ecf20Sopenharmony_ci# ----------------------------- # 6598c2ecf20Sopenharmony_ci# ----------------------------- # 6608c2ecf20Sopenharmony_ci# | lo(mplier) * hi(mplicand) | # 6618c2ecf20Sopenharmony_ci# ----------------------------- # 6628c2ecf20Sopenharmony_ci# | ----------------------------- # 6638c2ecf20Sopenharmony_ci# --|-- | lo(mplier) * lo(mplicand) | # 6648c2ecf20Sopenharmony_ci# | ----------------------------- # 6658c2ecf20Sopenharmony_ci# ======================================================== # 6668c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 6678c2ecf20Sopenharmony_ci# | hi(result) | lo(result) | # 6688c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 6698c2ecf20Sopenharmony_ci######################################################################### 6708c2ecf20Sopenharmony_cimuls64_alg: 6718c2ecf20Sopenharmony_ci# load temp registers with operands 6728c2ecf20Sopenharmony_ci mov.l %d0,%d2 # mr in d2 6738c2ecf20Sopenharmony_ci mov.l %d0,%d3 # mr in d3 6748c2ecf20Sopenharmony_ci mov.l %d1,%d4 # md in d4 6758c2ecf20Sopenharmony_ci swap %d3 # hi(mr) in lo d3 6768c2ecf20Sopenharmony_ci swap %d4 # hi(md) in lo d4 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci# complete necessary multiplies: 6798c2ecf20Sopenharmony_ci mulu.w %d1,%d0 # [1] lo(mr) * lo(md) 6808c2ecf20Sopenharmony_ci mulu.w %d3,%d1 # [2] hi(mr) * lo(md) 6818c2ecf20Sopenharmony_ci mulu.w %d4,%d2 # [3] lo(mr) * hi(md) 6828c2ecf20Sopenharmony_ci mulu.w %d4,%d3 # [4] hi(mr) * hi(md) 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1]. 6858c2ecf20Sopenharmony_ci# add carries produced from these adds to [4]. 6868c2ecf20Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result. 6878c2ecf20Sopenharmony_ci clr.l %d4 # load d4 w/ zero value 6888c2ecf20Sopenharmony_ci swap %d0 # hi([1]) <==> lo([1]) 6898c2ecf20Sopenharmony_ci add.w %d1,%d0 # hi([1]) + lo([2]) 6908c2ecf20Sopenharmony_ci addx.l %d4,%d3 # [4] + carry 6918c2ecf20Sopenharmony_ci add.w %d2,%d0 # hi([1]) + lo([3]) 6928c2ecf20Sopenharmony_ci addx.l %d4,%d3 # [4] + carry 6938c2ecf20Sopenharmony_ci swap %d0 # lo([1]) <==> hi([1]) 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci# lo portions of [2],[3] have been added in to final result. 6968c2ecf20Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4] 6978c2ecf20Sopenharmony_ci clr.w %d1 # clear lo([2]) 6988c2ecf20Sopenharmony_ci clr.w %d2 # clear hi([3]) 6998c2ecf20Sopenharmony_ci swap %d1 # hi([2]) in lo d1 7008c2ecf20Sopenharmony_ci swap %d2 # hi([3]) in lo d2 7018c2ecf20Sopenharmony_ci add.l %d2,%d1 # [4] + hi([2]) 7028c2ecf20Sopenharmony_ci add.l %d3,%d1 # [4] + hi([3]) 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci tst.b %d5 # should result be signed? 7058c2ecf20Sopenharmony_ci beq.b muls64_done # no 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci# result should be a signed negative number. 7088c2ecf20Sopenharmony_ci# compute 2's complement of the unsigned number: 7098c2ecf20Sopenharmony_ci# -negate all bits and add 1 7108c2ecf20Sopenharmony_cimuls64_neg: 7118c2ecf20Sopenharmony_ci not.l %d0 # negate lo(result) bits 7128c2ecf20Sopenharmony_ci not.l %d1 # negate hi(result) bits 7138c2ecf20Sopenharmony_ci addq.l &1,%d0 # add 1 to lo(result) 7148c2ecf20Sopenharmony_ci addx.l %d4,%d1 # add carry to hi(result) 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cimuls64_done: 7178c2ecf20Sopenharmony_ci mov.w MUL64_CC(%a6),%d4 7188c2ecf20Sopenharmony_ci andi.b &0x10,%d4 # keep old 'X' bit 7198c2ecf20Sopenharmony_ci tst.l %d1 # may set 'N' bit 7208c2ecf20Sopenharmony_ci bpl.b muls64_ddone 7218c2ecf20Sopenharmony_ci ori.b &0x8,%d4 # set 'N' bit 7228c2ecf20Sopenharmony_cimuls64_ddone: 7238c2ecf20Sopenharmony_ci mov.w %d4,%cc 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci# here, the result is in d1 and d0. the current strategy is to save 7268c2ecf20Sopenharmony_ci# the values at the location pointed to by a0. 7278c2ecf20Sopenharmony_ci# use movm here to not disturb the condition codes. 7288c2ecf20Sopenharmony_cimuls64_end: 7298c2ecf20Sopenharmony_ci exg %d1,%d0 7308c2ecf20Sopenharmony_ci movm.l &0x0003,([0x10,%a6]) # save result at (a0) 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci# EPILOGUE BEGIN ######################################################## 7338c2ecf20Sopenharmony_ci# fmovm.l (%sp)+,&0x0 # restore no fpregs 7348c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x003c # restore d2-d5 7358c2ecf20Sopenharmony_ci unlk %a6 7368c2ecf20Sopenharmony_ci# EPILOGUE END ########################################################## 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci rts 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci# one or both of the operands is zero so the result is also zero. 7418c2ecf20Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit. 7428c2ecf20Sopenharmony_cimuls64_zero: 7438c2ecf20Sopenharmony_ci clr.l %d0 7448c2ecf20Sopenharmony_ci clr.l %d1 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci mov.w MUL64_CC(%a6),%d4 7478c2ecf20Sopenharmony_ci andi.b &0x10,%d4 7488c2ecf20Sopenharmony_ci ori.b &0x4,%d4 7498c2ecf20Sopenharmony_ci mov.w %d4,%cc # set 'Z' ccode bit 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci bra.b muls64_end 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci######################################################################### 7548c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 7558c2ecf20Sopenharmony_ci# _060LSP__cmp2_Ab_(): Emulate "cmp2.b An,<ea>". # 7568c2ecf20Sopenharmony_ci# _060LSP__cmp2_Aw_(): Emulate "cmp2.w An,<ea>". # 7578c2ecf20Sopenharmony_ci# _060LSP__cmp2_Al_(): Emulate "cmp2.l An,<ea>". # 7588c2ecf20Sopenharmony_ci# _060LSP__cmp2_Db_(): Emulate "cmp2.b Dn,<ea>". # 7598c2ecf20Sopenharmony_ci# _060LSP__cmp2_Dw_(): Emulate "cmp2.w Dn,<ea>". # 7608c2ecf20Sopenharmony_ci# _060LSP__cmp2_Dl_(): Emulate "cmp2.l Dn,<ea>". # 7618c2ecf20Sopenharmony_ci# # 7628c2ecf20Sopenharmony_ci# This is the library version which is accessed as a subroutine # 7638c2ecf20Sopenharmony_ci# and therefore does not work exactly like the 680X0 "cmp2" # 7648c2ecf20Sopenharmony_ci# instruction. # 7658c2ecf20Sopenharmony_ci# # 7668c2ecf20Sopenharmony_ci# XREF **************************************************************** # 7678c2ecf20Sopenharmony_ci# None # 7688c2ecf20Sopenharmony_ci# # 7698c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 7708c2ecf20Sopenharmony_ci# 0x4(sp) = Rn # 7718c2ecf20Sopenharmony_ci# 0x8(sp) = pointer to boundary pair # 7728c2ecf20Sopenharmony_ci# # 7738c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 7748c2ecf20Sopenharmony_ci# cc = condition codes are set correctly # 7758c2ecf20Sopenharmony_ci# # 7768c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 7778c2ecf20Sopenharmony_ci# In the interest of simplicity, all operands are converted to # 7788c2ecf20Sopenharmony_ci# longword size whether the operation is byte, word, or long. The # 7798c2ecf20Sopenharmony_ci# bounds are sign extended accordingly. If Rn is a data register, Rn is # 7808c2ecf20Sopenharmony_ci# also sign extended. If Rn is an address register, it need not be sign # 7818c2ecf20Sopenharmony_ci# extended since the full register is always used. # 7828c2ecf20Sopenharmony_ci# The condition codes are set correctly before the final "rts". # 7838c2ecf20Sopenharmony_ci# # 7848c2ecf20Sopenharmony_ci######################################################################### 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ciset CMP2_CC, -4 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci global _060LSP__cmp2_Ab_ 7898c2ecf20Sopenharmony_ci_060LSP__cmp2_Ab_: 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 7928c2ecf20Sopenharmony_ci link.w %a6,&-4 7938c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 7948c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 7958c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 7988c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci mov.b ([0xc,%a6],0x0),%d0 8018c2ecf20Sopenharmony_ci mov.b ([0xc,%a6],0x1),%d1 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci extb.l %d0 # sign extend lo bnd 8048c2ecf20Sopenharmony_ci extb.l %d1 # sign extend hi bnd 8058c2ecf20Sopenharmony_ci bra.w l_cmp2_cmp # go do the compare emulation 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci global _060LSP__cmp2_Aw_ 8088c2ecf20Sopenharmony_ci_060LSP__cmp2_Aw_: 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 8118c2ecf20Sopenharmony_ci link.w %a6,&-4 8128c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 8138c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 8148c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 8178c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci mov.w ([0xc,%a6],0x0),%d0 8208c2ecf20Sopenharmony_ci mov.w ([0xc,%a6],0x2),%d1 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci ext.l %d0 # sign extend lo bnd 8238c2ecf20Sopenharmony_ci ext.l %d1 # sign extend hi bnd 8248c2ecf20Sopenharmony_ci bra.w l_cmp2_cmp # go do the compare emulation 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci global _060LSP__cmp2_Al_ 8278c2ecf20Sopenharmony_ci_060LSP__cmp2_Al_: 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 8308c2ecf20Sopenharmony_ci link.w %a6,&-4 8318c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 8328c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 8338c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 8368c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci mov.l ([0xc,%a6],0x0),%d0 8398c2ecf20Sopenharmony_ci mov.l ([0xc,%a6],0x4),%d1 8408c2ecf20Sopenharmony_ci bra.w l_cmp2_cmp # go do the compare emulation 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci global _060LSP__cmp2_Db_ 8438c2ecf20Sopenharmony_ci_060LSP__cmp2_Db_: 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 8468c2ecf20Sopenharmony_ci link.w %a6,&-4 8478c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 8488c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 8498c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 8528c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci mov.b ([0xc,%a6],0x0),%d0 8558c2ecf20Sopenharmony_ci mov.b ([0xc,%a6],0x1),%d1 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci extb.l %d0 # sign extend lo bnd 8588c2ecf20Sopenharmony_ci extb.l %d1 # sign extend hi bnd 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci# operation is a data register compare. 8618c2ecf20Sopenharmony_ci# sign extend byte to long so we can do simple longword compares. 8628c2ecf20Sopenharmony_ci extb.l %d2 # sign extend data byte 8638c2ecf20Sopenharmony_ci bra.w l_cmp2_cmp # go do the compare emulation 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci global _060LSP__cmp2_Dw_ 8668c2ecf20Sopenharmony_ci_060LSP__cmp2_Dw_: 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 8698c2ecf20Sopenharmony_ci link.w %a6,&-4 8708c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 8718c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 8728c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 8758c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci mov.w ([0xc,%a6],0x0),%d0 8788c2ecf20Sopenharmony_ci mov.w ([0xc,%a6],0x2),%d1 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci ext.l %d0 # sign extend lo bnd 8818c2ecf20Sopenharmony_ci ext.l %d1 # sign extend hi bnd 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci# operation is a data register compare. 8848c2ecf20Sopenharmony_ci# sign extend word to long so we can do simple longword compares. 8858c2ecf20Sopenharmony_ci ext.l %d2 # sign extend data word 8868c2ecf20Sopenharmony_ci bra.w l_cmp2_cmp # go emulate compare 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci global _060LSP__cmp2_Dl_ 8898c2ecf20Sopenharmony_ci_060LSP__cmp2_Dl_: 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci# PROLOGUE BEGIN ######################################################## 8928c2ecf20Sopenharmony_ci link.w %a6,&-4 8938c2ecf20Sopenharmony_ci movm.l &0x3800,-(%sp) # save d2-d4 8948c2ecf20Sopenharmony_ci# fmovm.l &0x0,-(%sp) # save no fpregs 8958c2ecf20Sopenharmony_ci# PROLOGUE END ########################################################## 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci mov.w %cc,CMP2_CC(%a6) 8988c2ecf20Sopenharmony_ci mov.l 0x8(%a6), %d2 # get regval 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci mov.l ([0xc,%a6],0x0),%d0 9018c2ecf20Sopenharmony_ci mov.l ([0xc,%a6],0x4),%d1 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci# 9048c2ecf20Sopenharmony_ci# To set the ccodes correctly: 9058c2ecf20Sopenharmony_ci# (1) save 'Z' bit from (Rn - lo) 9068c2ecf20Sopenharmony_ci# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi)) 9078c2ecf20Sopenharmony_ci# (3) keep 'X', 'N', and 'V' from before instruction 9088c2ecf20Sopenharmony_ci# (4) combine ccodes 9098c2ecf20Sopenharmony_ci# 9108c2ecf20Sopenharmony_cil_cmp2_cmp: 9118c2ecf20Sopenharmony_ci sub.l %d0, %d2 # (Rn - lo) 9128c2ecf20Sopenharmony_ci mov.w %cc, %d3 # fetch resulting ccodes 9138c2ecf20Sopenharmony_ci andi.b &0x4, %d3 # keep 'Z' bit 9148c2ecf20Sopenharmony_ci sub.l %d0, %d1 # (hi - lo) 9158c2ecf20Sopenharmony_ci cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi)) 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci mov.w %cc, %d4 # fetch resulting ccodes 9188c2ecf20Sopenharmony_ci or.b %d4, %d3 # combine w/ earlier ccodes 9198c2ecf20Sopenharmony_ci andi.b &0x5, %d3 # keep 'Z' and 'N' 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci mov.w CMP2_CC(%a6), %d4 # fetch old ccodes 9228c2ecf20Sopenharmony_ci andi.b &0x1a, %d4 # keep 'X','N','V' bits 9238c2ecf20Sopenharmony_ci or.b %d3, %d4 # insert new ccodes 9248c2ecf20Sopenharmony_ci mov.w %d4,%cc # save new ccodes 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci# EPILOGUE BEGIN ######################################################## 9278c2ecf20Sopenharmony_ci# fmovm.l (%sp)+,&0x0 # restore no fpregs 9288c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x001c # restore d2-d4 9298c2ecf20Sopenharmony_ci unlk %a6 9308c2ecf20Sopenharmony_ci# EPILOGUE END ########################################################## 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci rts 933