1/* SPDX-License-Identifier: ISC OR GPL-2.0-only */ 2 3/* 4 * ldivmod.S: signed 64 bit division (quotient and remainder) 5 * 6 * Taken from CrOS EC: third_party/libaeabi-cortexm0/core/cortex-m0/ldivmod.S 7 */ 8 9#include <arch/asm.h> 10 11 12@ {long long quotient, long long remainder} 13@ __aeabi_ldivmod(long long numerator, long long denominator) 14@ 15@ Divide r1:r0 by r3:r2 and return the quotient in r1:r0 and the remainder in 16@ r3:r2 (all signed) 17@ 18 19ENTRY(__aeabi_ldivmod) 20 21 cmp r1, #0 22 bge L_num_pos 23 24 push {r4, lr} 25 movs r4, #0 @ num = -num 26 rsbs r0, r0, #0 27 sbcs r4, r1 28 mov r1, r4 29 30 cmp r3, #0 31 bge L_neg_both 32 33 movs r4, #0 @ den = -den 34 rsbs r2, r2, #0 35 sbcs r4, r3 36 mov r3, r4 37 bl __aeabi_uldivmod 38 movs r4, #0 @ rem = -rem 39 rsbs r2, r2, #0 40 sbcs r4, r3 41 mov r3, r4 42 pop {r4, pc} 43 44L_neg_both: 45 bl __aeabi_uldivmod 46 movs r4, #0 @ quot = -quot 47 rsbs r0, r0, #0 48 sbcs r4, r1 49 mov r1, r4 50 movs r4, #0 @ rem = -rem 51 rsbs r2, r2, #0 52 sbcs r4, r3 53 mov r3, r4 54 pop {r4, pc} 55 56L_num_pos: 57 cmp r3, #0 58 blt L_den_neg 59 push {r4, lr} 60 bl __aeabi_uldivmod @ offset too big for b / bge 61 pop {r4, pc} 62 63L_den_neg: 64 push {r4, lr} 65 movs r4, #0 @ den = -den 66 rsbs r2, r2, #0 67 sbcs r4, r3 68 mov r3, r4 69 bl __aeabi_uldivmod 70 movs r4, #0 @ quot = -quot 71 rsbs r0, r0, #0 72 sbcs r4, r1 73 mov r1, r4 74 pop {r4, pc} 75