162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#include <linux/linkage.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/* 562306a36Sopenharmony_ci * Unsigned modulo operation for 32 bit integers. 662306a36Sopenharmony_ci * Input : op1 in Reg r5 762306a36Sopenharmony_ci * op2 in Reg r6 862306a36Sopenharmony_ci * Output: op1 mod op2 in Reg r3 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci .text 1262306a36Sopenharmony_ci .globl __umodsi3 1362306a36Sopenharmony_ci .type __umodsi3, @function 1462306a36Sopenharmony_ci .ent __umodsi3 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci__umodsi3: 1762306a36Sopenharmony_ci .frame r1, 0, r15 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci addik r1, r1, -12 2062306a36Sopenharmony_ci swi r29, r1, 0 2162306a36Sopenharmony_ci swi r30, r1, 4 2262306a36Sopenharmony_ci swi r31, r1, 8 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci beqi r6, div_by_zero /* div_by_zero - division error */ 2562306a36Sopenharmony_ci beqid r5, result_is_zero /* result is zero */ 2662306a36Sopenharmony_ci addik r3, r0, 0 /* clear div */ 2762306a36Sopenharmony_ci addik r30, r0, 0 /* clear mod */ 2862306a36Sopenharmony_ci addik r29, r0, 32 /* initialize the loop count */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* check if r6 and r5 are equal /* if yes, return 0 */ 3162306a36Sopenharmony_ci rsub r18, r5, r6 3262306a36Sopenharmony_ci beqi r18, return_here 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */ 3562306a36Sopenharmony_ci xor r18, r5, r6 3662306a36Sopenharmony_ci bgeid r18, 16 3762306a36Sopenharmony_ci addik r3, r5, 0 3862306a36Sopenharmony_ci blti r6, return_here 3962306a36Sopenharmony_ci bri $lcheckr6 4062306a36Sopenharmony_ci rsub r18, r5, r6 /* microblazecmp */ 4162306a36Sopenharmony_ci bgti r18, return_here 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* if r6 [bit 31] is set, then return result as r5-r6 */ 4462306a36Sopenharmony_ci$lcheckr6: 4562306a36Sopenharmony_ci bgtid r6, div0 4662306a36Sopenharmony_ci addik r3, r0, 0 4762306a36Sopenharmony_ci addik r18, r0, 0x7fffffff 4862306a36Sopenharmony_ci and r5, r5, r18 4962306a36Sopenharmony_ci and r6, r6, r18 5062306a36Sopenharmony_ci brid return_here 5162306a36Sopenharmony_ci rsub r3, r6, r5 5262306a36Sopenharmony_ci/* first part: try to find the first '1' in the r5 */ 5362306a36Sopenharmony_cidiv0: 5462306a36Sopenharmony_ci blti r5, div2 5562306a36Sopenharmony_cidiv1: 5662306a36Sopenharmony_ci add r5, r5, r5 /* left shift logical r5 */ 5762306a36Sopenharmony_ci bgeid r5, div1 5862306a36Sopenharmony_ci addik r29, r29, -1 5962306a36Sopenharmony_cidiv2: 6062306a36Sopenharmony_ci /* left shift logical r5 get the '1' into the carry */ 6162306a36Sopenharmony_ci add r5, r5, r5 6262306a36Sopenharmony_ci addc r3, r3, r3 /* move that bit into the mod register */ 6362306a36Sopenharmony_ci rsub r31, r6, r3 /* try to subtract (r3 a r6) */ 6462306a36Sopenharmony_ci blti r31, mod_too_small 6562306a36Sopenharmony_ci /* move the r31 to mod since the result was positive */ 6662306a36Sopenharmony_ci or r3, r0, r31 6762306a36Sopenharmony_ci addik r30, r30, 1 6862306a36Sopenharmony_cimod_too_small: 6962306a36Sopenharmony_ci addik r29, r29, -1 7062306a36Sopenharmony_ci beqi r29, loop_end 7162306a36Sopenharmony_ci add r30, r30, r30 /* shift in the '1' into div */ 7262306a36Sopenharmony_ci bri div2 /* div2 */ 7362306a36Sopenharmony_ciloop_end: 7462306a36Sopenharmony_ci bri return_here 7562306a36Sopenharmony_cidiv_by_zero: 7662306a36Sopenharmony_ciresult_is_zero: 7762306a36Sopenharmony_ci or r3, r0, r0 /* set result to 0 */ 7862306a36Sopenharmony_cireturn_here: 7962306a36Sopenharmony_ci/* restore values of csrs and that of r3 and the divisor and the dividend */ 8062306a36Sopenharmony_ci lwi r29, r1, 0 8162306a36Sopenharmony_ci lwi r30, r1, 4 8262306a36Sopenharmony_ci lwi r31, r1, 8 8362306a36Sopenharmony_ci rtsd r15, 8 8462306a36Sopenharmony_ci addik r1, r1, 12 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci.size __umodsi3, . - __umodsi3 8762306a36Sopenharmony_ci.end __umodsi3 88