18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Author: Nicolas Pitre <nico@fluxnic.net> 58c2ecf20Sopenharmony_ci * - contributed to gcc-3.4 on Sep 30, 2003 68c2ecf20Sopenharmony_ci * - adapted for the Linux kernel on Oct 2, 2003 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ciThis file is free software; you can redistribute it and/or modify it 128c2ecf20Sopenharmony_ciunder the terms of the GNU General Public License as published by the 138c2ecf20Sopenharmony_ciFree Software Foundation; either version 2, or (at your option) any 148c2ecf20Sopenharmony_cilater version. 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciIn addition to the permissions in the GNU General Public License, the 178c2ecf20Sopenharmony_ciFree Software Foundation gives you unlimited permission to link the 188c2ecf20Sopenharmony_cicompiled version of this file into combinations with other programs, 198c2ecf20Sopenharmony_ciand to distribute those combinations without any restriction coming 208c2ecf20Sopenharmony_cifrom the use of this file. (The General Public License restrictions 218c2ecf20Sopenharmony_cido apply in other respects; for example, they cover modification of 228c2ecf20Sopenharmony_cithe file, and distribution when not linked into a combine 238c2ecf20Sopenharmony_ciexecutable.) 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciThis file is distributed in the hope that it will be useful, but 268c2ecf20Sopenharmony_ciWITHOUT ANY WARRANTY; without even the implied warranty of 278c2ecf20Sopenharmony_ciMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 288c2ecf20Sopenharmony_ciGeneral Public License for more details. 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciYou should have received a copy of the GNU General Public License 318c2ecf20Sopenharmony_cialong with this program; see the file COPYING. If not, write to 328c2ecf20Sopenharmony_cithe Free Software Foundation, 59 Temple Place - Suite 330, 338c2ecf20Sopenharmony_ciBoston, MA 02111-1307, USA. */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/linkage.h> 378c2ecf20Sopenharmony_ci#include <asm/assembler.h> 388c2ecf20Sopenharmony_ci#include <asm/unwind.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci.macro ARM_DIV_BODY dividend, divisor, result, curbit 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci clz \curbit, \divisor 458c2ecf20Sopenharmony_ci clz \result, \dividend 468c2ecf20Sopenharmony_ci sub \result, \curbit, \result 478c2ecf20Sopenharmony_ci mov \curbit, #1 488c2ecf20Sopenharmony_ci mov \divisor, \divisor, lsl \result 498c2ecf20Sopenharmony_ci mov \curbit, \curbit, lsl \result 508c2ecf20Sopenharmony_ci mov \result, #0 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#else 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci @ Initially shift the divisor left 3 bits if possible, 558c2ecf20Sopenharmony_ci @ set curbit accordingly. This allows for curbit to be located 568c2ecf20Sopenharmony_ci @ at the left end of each 4 bit nibbles in the division loop 578c2ecf20Sopenharmony_ci @ to save one loop in most cases. 588c2ecf20Sopenharmony_ci tst \divisor, #0xe0000000 598c2ecf20Sopenharmony_ci moveq \divisor, \divisor, lsl #3 608c2ecf20Sopenharmony_ci moveq \curbit, #8 618c2ecf20Sopenharmony_ci movne \curbit, #1 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci @ Unless the divisor is very big, shift it up in multiples of 648c2ecf20Sopenharmony_ci @ four bits, since this is the amount of unwinding in the main 658c2ecf20Sopenharmony_ci @ division loop. Continue shifting until the divisor is 668c2ecf20Sopenharmony_ci @ larger than the dividend. 678c2ecf20Sopenharmony_ci1: cmp \divisor, #0x10000000 688c2ecf20Sopenharmony_ci cmplo \divisor, \dividend 698c2ecf20Sopenharmony_ci movlo \divisor, \divisor, lsl #4 708c2ecf20Sopenharmony_ci movlo \curbit, \curbit, lsl #4 718c2ecf20Sopenharmony_ci blo 1b 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci @ For very big divisors, we must shift it a bit at a time, or 748c2ecf20Sopenharmony_ci @ we will be in danger of overflowing. 758c2ecf20Sopenharmony_ci1: cmp \divisor, #0x80000000 768c2ecf20Sopenharmony_ci cmplo \divisor, \dividend 778c2ecf20Sopenharmony_ci movlo \divisor, \divisor, lsl #1 788c2ecf20Sopenharmony_ci movlo \curbit, \curbit, lsl #1 798c2ecf20Sopenharmony_ci blo 1b 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci mov \result, #0 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#endif 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci @ Division loop 868c2ecf20Sopenharmony_ci1: cmp \dividend, \divisor 878c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor 888c2ecf20Sopenharmony_ci orrhs \result, \result, \curbit 898c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #1 908c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #1 918c2ecf20Sopenharmony_ci orrhs \result, \result, \curbit, lsr #1 928c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #2 938c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #2 948c2ecf20Sopenharmony_ci orrhs \result, \result, \curbit, lsr #2 958c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #3 968c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #3 978c2ecf20Sopenharmony_ci orrhs \result, \result, \curbit, lsr #3 988c2ecf20Sopenharmony_ci cmp \dividend, #0 @ Early termination? 998c2ecf20Sopenharmony_ci movsne \curbit, \curbit, lsr #4 @ No, any more bits to do? 1008c2ecf20Sopenharmony_ci movne \divisor, \divisor, lsr #4 1018c2ecf20Sopenharmony_ci bne 1b 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci.endm 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci.macro ARM_DIV2_ORDER divisor, order 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci clz \order, \divisor 1118c2ecf20Sopenharmony_ci rsb \order, \order, #31 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#else 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci cmp \divisor, #(1 << 16) 1168c2ecf20Sopenharmony_ci movhs \divisor, \divisor, lsr #16 1178c2ecf20Sopenharmony_ci movhs \order, #16 1188c2ecf20Sopenharmony_ci movlo \order, #0 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci cmp \divisor, #(1 << 8) 1218c2ecf20Sopenharmony_ci movhs \divisor, \divisor, lsr #8 1228c2ecf20Sopenharmony_ci addhs \order, \order, #8 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci cmp \divisor, #(1 << 4) 1258c2ecf20Sopenharmony_ci movhs \divisor, \divisor, lsr #4 1268c2ecf20Sopenharmony_ci addhs \order, \order, #4 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci cmp \divisor, #(1 << 2) 1298c2ecf20Sopenharmony_ci addhi \order, \order, #3 1308c2ecf20Sopenharmony_ci addls \order, \order, \divisor, lsr #1 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#endif 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci.endm 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci.macro ARM_MOD_BODY dividend, divisor, order, spare 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci clz \order, \divisor 1428c2ecf20Sopenharmony_ci clz \spare, \dividend 1438c2ecf20Sopenharmony_ci sub \order, \order, \spare 1448c2ecf20Sopenharmony_ci mov \divisor, \divisor, lsl \order 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#else 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci mov \order, #0 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci @ Unless the divisor is very big, shift it up in multiples of 1518c2ecf20Sopenharmony_ci @ four bits, since this is the amount of unwinding in the main 1528c2ecf20Sopenharmony_ci @ division loop. Continue shifting until the divisor is 1538c2ecf20Sopenharmony_ci @ larger than the dividend. 1548c2ecf20Sopenharmony_ci1: cmp \divisor, #0x10000000 1558c2ecf20Sopenharmony_ci cmplo \divisor, \dividend 1568c2ecf20Sopenharmony_ci movlo \divisor, \divisor, lsl #4 1578c2ecf20Sopenharmony_ci addlo \order, \order, #4 1588c2ecf20Sopenharmony_ci blo 1b 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci @ For very big divisors, we must shift it a bit at a time, or 1618c2ecf20Sopenharmony_ci @ we will be in danger of overflowing. 1628c2ecf20Sopenharmony_ci1: cmp \divisor, #0x80000000 1638c2ecf20Sopenharmony_ci cmplo \divisor, \dividend 1648c2ecf20Sopenharmony_ci movlo \divisor, \divisor, lsl #1 1658c2ecf20Sopenharmony_ci addlo \order, \order, #1 1668c2ecf20Sopenharmony_ci blo 1b 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#endif 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci @ Perform all needed subtractions to keep only the reminder. 1718c2ecf20Sopenharmony_ci @ Do comparisons in batch of 4 first. 1728c2ecf20Sopenharmony_ci subs \order, \order, #3 @ yes, 3 is intended here 1738c2ecf20Sopenharmony_ci blt 2f 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci1: cmp \dividend, \divisor 1768c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor 1778c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #1 1788c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #1 1798c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #2 1808c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #2 1818c2ecf20Sopenharmony_ci cmp \dividend, \divisor, lsr #3 1828c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor, lsr #3 1838c2ecf20Sopenharmony_ci cmp \dividend, #1 1848c2ecf20Sopenharmony_ci mov \divisor, \divisor, lsr #4 1858c2ecf20Sopenharmony_ci subsge \order, \order, #4 1868c2ecf20Sopenharmony_ci bge 1b 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci tst \order, #3 1898c2ecf20Sopenharmony_ci teqne \dividend, #0 1908c2ecf20Sopenharmony_ci beq 5f 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci @ Either 1, 2 or 3 comparison/subtractions are left. 1938c2ecf20Sopenharmony_ci2: cmn \order, #2 1948c2ecf20Sopenharmony_ci blt 4f 1958c2ecf20Sopenharmony_ci beq 3f 1968c2ecf20Sopenharmony_ci cmp \dividend, \divisor 1978c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor 1988c2ecf20Sopenharmony_ci mov \divisor, \divisor, lsr #1 1998c2ecf20Sopenharmony_ci3: cmp \dividend, \divisor 2008c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor 2018c2ecf20Sopenharmony_ci mov \divisor, \divisor, lsr #1 2028c2ecf20Sopenharmony_ci4: cmp \dividend, \divisor 2038c2ecf20Sopenharmony_ci subhs \dividend, \dividend, \divisor 2048c2ecf20Sopenharmony_ci5: 2058c2ecf20Sopenharmony_ci.endm 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_PATCH_IDIV 2098c2ecf20Sopenharmony_ci .align 3 2108c2ecf20Sopenharmony_ci#endif 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ciENTRY(__udivsi3) 2138c2ecf20Sopenharmony_ciENTRY(__aeabi_uidiv) 2148c2ecf20Sopenharmony_ciUNWIND(.fnstart) 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci subs r2, r1, #1 2178c2ecf20Sopenharmony_ci reteq lr 2188c2ecf20Sopenharmony_ci bcc Ldiv0 2198c2ecf20Sopenharmony_ci cmp r0, r1 2208c2ecf20Sopenharmony_ci bls 11f 2218c2ecf20Sopenharmony_ci tst r1, r2 2228c2ecf20Sopenharmony_ci beq 12f 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci ARM_DIV_BODY r0, r1, r2, r3 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci mov r0, r2 2278c2ecf20Sopenharmony_ci ret lr 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci11: moveq r0, #1 2308c2ecf20Sopenharmony_ci movne r0, #0 2318c2ecf20Sopenharmony_ci ret lr 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci12: ARM_DIV2_ORDER r1, r2 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci mov r0, r0, lsr r2 2368c2ecf20Sopenharmony_ci ret lr 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciUNWIND(.fnend) 2398c2ecf20Sopenharmony_ciENDPROC(__udivsi3) 2408c2ecf20Sopenharmony_ciENDPROC(__aeabi_uidiv) 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciENTRY(__umodsi3) 2438c2ecf20Sopenharmony_ciUNWIND(.fnstart) 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci subs r2, r1, #1 @ compare divisor with 1 2468c2ecf20Sopenharmony_ci bcc Ldiv0 2478c2ecf20Sopenharmony_ci cmpne r0, r1 @ compare dividend with divisor 2488c2ecf20Sopenharmony_ci moveq r0, #0 2498c2ecf20Sopenharmony_ci tsthi r1, r2 @ see if divisor is power of 2 2508c2ecf20Sopenharmony_ci andeq r0, r0, r2 2518c2ecf20Sopenharmony_ci retls lr 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci ARM_MOD_BODY r0, r1, r2, r3 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci ret lr 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ciUNWIND(.fnend) 2588c2ecf20Sopenharmony_ciENDPROC(__umodsi3) 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_PATCH_IDIV 2618c2ecf20Sopenharmony_ci .align 3 2628c2ecf20Sopenharmony_ci#endif 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ciENTRY(__divsi3) 2658c2ecf20Sopenharmony_ciENTRY(__aeabi_idiv) 2668c2ecf20Sopenharmony_ciUNWIND(.fnstart) 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci cmp r1, #0 2698c2ecf20Sopenharmony_ci eor ip, r0, r1 @ save the sign of the result. 2708c2ecf20Sopenharmony_ci beq Ldiv0 2718c2ecf20Sopenharmony_ci rsbmi r1, r1, #0 @ loops below use unsigned. 2728c2ecf20Sopenharmony_ci subs r2, r1, #1 @ division by 1 or -1 ? 2738c2ecf20Sopenharmony_ci beq 10f 2748c2ecf20Sopenharmony_ci movs r3, r0 2758c2ecf20Sopenharmony_ci rsbmi r3, r0, #0 @ positive dividend value 2768c2ecf20Sopenharmony_ci cmp r3, r1 2778c2ecf20Sopenharmony_ci bls 11f 2788c2ecf20Sopenharmony_ci tst r1, r2 @ divisor is power of 2 ? 2798c2ecf20Sopenharmony_ci beq 12f 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci ARM_DIV_BODY r3, r1, r0, r2 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci cmp ip, #0 2848c2ecf20Sopenharmony_ci rsbmi r0, r0, #0 2858c2ecf20Sopenharmony_ci ret lr 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci10: teq ip, r0 @ same sign ? 2888c2ecf20Sopenharmony_ci rsbmi r0, r0, #0 2898c2ecf20Sopenharmony_ci ret lr 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci11: movlo r0, #0 2928c2ecf20Sopenharmony_ci moveq r0, ip, asr #31 2938c2ecf20Sopenharmony_ci orreq r0, r0, #1 2948c2ecf20Sopenharmony_ci ret lr 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci12: ARM_DIV2_ORDER r1, r2 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci cmp ip, #0 2998c2ecf20Sopenharmony_ci mov r0, r3, lsr r2 3008c2ecf20Sopenharmony_ci rsbmi r0, r0, #0 3018c2ecf20Sopenharmony_ci ret lr 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ciUNWIND(.fnend) 3048c2ecf20Sopenharmony_ciENDPROC(__divsi3) 3058c2ecf20Sopenharmony_ciENDPROC(__aeabi_idiv) 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ciENTRY(__modsi3) 3088c2ecf20Sopenharmony_ciUNWIND(.fnstart) 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci cmp r1, #0 3118c2ecf20Sopenharmony_ci beq Ldiv0 3128c2ecf20Sopenharmony_ci rsbmi r1, r1, #0 @ loops below use unsigned. 3138c2ecf20Sopenharmony_ci movs ip, r0 @ preserve sign of dividend 3148c2ecf20Sopenharmony_ci rsbmi r0, r0, #0 @ if negative make positive 3158c2ecf20Sopenharmony_ci subs r2, r1, #1 @ compare divisor with 1 3168c2ecf20Sopenharmony_ci cmpne r0, r1 @ compare dividend with divisor 3178c2ecf20Sopenharmony_ci moveq r0, #0 3188c2ecf20Sopenharmony_ci tsthi r1, r2 @ see if divisor is power of 2 3198c2ecf20Sopenharmony_ci andeq r0, r0, r2 3208c2ecf20Sopenharmony_ci bls 10f 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci ARM_MOD_BODY r0, r1, r2, r3 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci10: cmp ip, #0 3258c2ecf20Sopenharmony_ci rsbmi r0, r0, #0 3268c2ecf20Sopenharmony_ci ret lr 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ciUNWIND(.fnend) 3298c2ecf20Sopenharmony_ciENDPROC(__modsi3) 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#ifdef CONFIG_AEABI 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ciENTRY(__aeabi_uidivmod) 3348c2ecf20Sopenharmony_ciUNWIND(.fnstart) 3358c2ecf20Sopenharmony_ciUNWIND(.save {r0, r1, ip, lr} ) 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci stmfd sp!, {r0, r1, ip, lr} 3388c2ecf20Sopenharmony_ci bl __aeabi_uidiv 3398c2ecf20Sopenharmony_ci ldmfd sp!, {r1, r2, ip, lr} 3408c2ecf20Sopenharmony_ci mul r3, r0, r2 3418c2ecf20Sopenharmony_ci sub r1, r1, r3 3428c2ecf20Sopenharmony_ci ret lr 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ciUNWIND(.fnend) 3458c2ecf20Sopenharmony_ciENDPROC(__aeabi_uidivmod) 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ciENTRY(__aeabi_idivmod) 3488c2ecf20Sopenharmony_ciUNWIND(.fnstart) 3498c2ecf20Sopenharmony_ciUNWIND(.save {r0, r1, ip, lr} ) 3508c2ecf20Sopenharmony_ci stmfd sp!, {r0, r1, ip, lr} 3518c2ecf20Sopenharmony_ci bl __aeabi_idiv 3528c2ecf20Sopenharmony_ci ldmfd sp!, {r1, r2, ip, lr} 3538c2ecf20Sopenharmony_ci mul r3, r0, r2 3548c2ecf20Sopenharmony_ci sub r1, r1, r3 3558c2ecf20Sopenharmony_ci ret lr 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ciUNWIND(.fnend) 3588c2ecf20Sopenharmony_ciENDPROC(__aeabi_idivmod) 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci#endif 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ciLdiv0: 3638c2ecf20Sopenharmony_ciUNWIND(.fnstart) 3648c2ecf20Sopenharmony_ciUNWIND(.pad #4) 3658c2ecf20Sopenharmony_ciUNWIND(.save {lr}) 3668c2ecf20Sopenharmony_ci str lr, [sp, #-8]! 3678c2ecf20Sopenharmony_ci bl __div0 3688c2ecf20Sopenharmony_ci mov r0, #0 @ About as wrong as it could be. 3698c2ecf20Sopenharmony_ci ldr pc, [sp], #8 3708c2ecf20Sopenharmony_ciUNWIND(.fnend) 3718c2ecf20Sopenharmony_ciENDPROC(Ldiv0) 372