18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#include "libgcc.h" 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci ;; This function also computes the remainder and stores it in er3. 58c2ecf20Sopenharmony_ci .global __udivsi3 68c2ecf20Sopenharmony_ci__udivsi3: 78c2ecf20Sopenharmony_ci mov.w A1E,A1E ; denominator top word 0? 88c2ecf20Sopenharmony_ci bne DenHighNonZero 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci ; do it the easy way, see page 107 in manual 118c2ecf20Sopenharmony_ci mov.w A0E,A2 128c2ecf20Sopenharmony_ci extu.l A2P 138c2ecf20Sopenharmony_ci divxu.w A1,A2P 148c2ecf20Sopenharmony_ci mov.w A2E,A0E 158c2ecf20Sopenharmony_ci divxu.w A1,A0P 168c2ecf20Sopenharmony_ci mov.w A0E,A3 178c2ecf20Sopenharmony_ci mov.w A2,A0E 188c2ecf20Sopenharmony_ci extu.l A3P 198c2ecf20Sopenharmony_ci rts 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci ; er0 = er0 / er1 228c2ecf20Sopenharmony_ci ; er3 = er0 % er1 238c2ecf20Sopenharmony_ci ; trashes er1 er2 248c2ecf20Sopenharmony_ci ; expects er1 >= 2^16 258c2ecf20Sopenharmony_ciDenHighNonZero: 268c2ecf20Sopenharmony_ci mov.l er0,er3 278c2ecf20Sopenharmony_ci mov.l er1,er2 288c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_H8300H 298c2ecf20Sopenharmony_cidivmod_L21: 308c2ecf20Sopenharmony_ci shlr.l er0 318c2ecf20Sopenharmony_ci shlr.l er2 ; make divisor < 2^16 328c2ecf20Sopenharmony_ci mov.w e2,e2 338c2ecf20Sopenharmony_ci bne divmod_L21 348c2ecf20Sopenharmony_ci#else 358c2ecf20Sopenharmony_ci shlr.l #2,er2 ; make divisor < 2^16 368c2ecf20Sopenharmony_ci mov.w e2,e2 378c2ecf20Sopenharmony_ci beq divmod_L22A 388c2ecf20Sopenharmony_cidivmod_L21: 398c2ecf20Sopenharmony_ci shlr.l #2,er0 408c2ecf20Sopenharmony_cidivmod_L22: 418c2ecf20Sopenharmony_ci shlr.l #2,er2 ; make divisor < 2^16 428c2ecf20Sopenharmony_ci mov.w e2,e2 438c2ecf20Sopenharmony_ci bne divmod_L21 448c2ecf20Sopenharmony_cidivmod_L22A: 458c2ecf20Sopenharmony_ci rotxl.w r2 468c2ecf20Sopenharmony_ci bcs divmod_L23 478c2ecf20Sopenharmony_ci shlr.l er0 488c2ecf20Sopenharmony_ci bra divmod_L24 498c2ecf20Sopenharmony_cidivmod_L23: 508c2ecf20Sopenharmony_ci rotxr.w r2 518c2ecf20Sopenharmony_ci shlr.l #2,er0 528c2ecf20Sopenharmony_cidivmod_L24: 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci ;; At this point, 558c2ecf20Sopenharmony_ci ;; er0 contains shifted dividend 568c2ecf20Sopenharmony_ci ;; er1 contains divisor 578c2ecf20Sopenharmony_ci ;; er2 contains shifted divisor 588c2ecf20Sopenharmony_ci ;; er3 contains dividend, later remainder 598c2ecf20Sopenharmony_ci divxu.w r2,er0 ; r0 now contains the approximate quotient (AQ) 608c2ecf20Sopenharmony_ci extu.l er0 618c2ecf20Sopenharmony_ci beq divmod_L25 628c2ecf20Sopenharmony_ci subs #1,er0 ; er0 = AQ - 1 638c2ecf20Sopenharmony_ci mov.w e1,r2 648c2ecf20Sopenharmony_ci mulxu.w r0,er2 ; er2 = upper (AQ - 1) * divisor 658c2ecf20Sopenharmony_ci sub.w r2,e3 ; dividend - 65536 * er2 668c2ecf20Sopenharmony_ci mov.w r1,r2 678c2ecf20Sopenharmony_ci mulxu.w r0,er2 ; compute er3 = remainder (tentative) 688c2ecf20Sopenharmony_ci sub.l er2,er3 ; er3 = dividend - (AQ - 1) * divisor 698c2ecf20Sopenharmony_cidivmod_L25: 708c2ecf20Sopenharmony_ci cmp.l er1,er3 ; is divisor < remainder? 718c2ecf20Sopenharmony_ci blo divmod_L26 728c2ecf20Sopenharmony_ci adds #1,er0 738c2ecf20Sopenharmony_ci sub.l er1,er3 ; correct the remainder 748c2ecf20Sopenharmony_cidivmod_L26: 758c2ecf20Sopenharmony_ci rts 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci .end 78