1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun#include <linux/linkage.h> 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun/* 5*4882a593Smuzhiyun * Unsigned modulo operation for 32 bit integers. 6*4882a593Smuzhiyun * Input : op1 in Reg r5 7*4882a593Smuzhiyun * op2 in Reg r6 8*4882a593Smuzhiyun * Output: op1 mod op2 in Reg r3 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun .text 12*4882a593Smuzhiyun .globl __umodsi3 13*4882a593Smuzhiyun .type __umodsi3, @function 14*4882a593Smuzhiyun .ent __umodsi3 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun__umodsi3: 17*4882a593Smuzhiyun .frame r1, 0, r15 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun addik r1, r1, -12 20*4882a593Smuzhiyun swi r29, r1, 0 21*4882a593Smuzhiyun swi r30, r1, 4 22*4882a593Smuzhiyun swi r31, r1, 8 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun beqi r6, div_by_zero /* div_by_zero - division error */ 25*4882a593Smuzhiyun beqid r5, result_is_zero /* result is zero */ 26*4882a593Smuzhiyun addik r3, r0, 0 /* clear div */ 27*4882a593Smuzhiyun addik r30, r0, 0 /* clear mod */ 28*4882a593Smuzhiyun addik r29, r0, 32 /* initialize the loop count */ 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun/* check if r6 and r5 are equal /* if yes, return 0 */ 31*4882a593Smuzhiyun rsub r18, r5, r6 32*4882a593Smuzhiyun beqi r18, return_here 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */ 35*4882a593Smuzhiyun xor r18, r5, r6 36*4882a593Smuzhiyun bgeid r18, 16 37*4882a593Smuzhiyun addik r3, r5, 0 38*4882a593Smuzhiyun blti r6, return_here 39*4882a593Smuzhiyun bri $lcheckr6 40*4882a593Smuzhiyun rsub r18, r5, r6 /* microblazecmp */ 41*4882a593Smuzhiyun bgti r18, return_here 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun/* if r6 [bit 31] is set, then return result as r5-r6 */ 44*4882a593Smuzhiyun$lcheckr6: 45*4882a593Smuzhiyun bgtid r6, div0 46*4882a593Smuzhiyun addik r3, r0, 0 47*4882a593Smuzhiyun addik r18, r0, 0x7fffffff 48*4882a593Smuzhiyun and r5, r5, r18 49*4882a593Smuzhiyun and r6, r6, r18 50*4882a593Smuzhiyun brid return_here 51*4882a593Smuzhiyun rsub r3, r6, r5 52*4882a593Smuzhiyun/* first part: try to find the first '1' in the r5 */ 53*4882a593Smuzhiyundiv0: 54*4882a593Smuzhiyun blti r5, div2 55*4882a593Smuzhiyundiv1: 56*4882a593Smuzhiyun add r5, r5, r5 /* left shift logical r5 */ 57*4882a593Smuzhiyun bgeid r5, div1 58*4882a593Smuzhiyun addik r29, r29, -1 59*4882a593Smuzhiyundiv2: 60*4882a593Smuzhiyun /* left shift logical r5 get the '1' into the carry */ 61*4882a593Smuzhiyun add r5, r5, r5 62*4882a593Smuzhiyun addc r3, r3, r3 /* move that bit into the mod register */ 63*4882a593Smuzhiyun rsub r31, r6, r3 /* try to subtract (r3 a r6) */ 64*4882a593Smuzhiyun blti r31, mod_too_small 65*4882a593Smuzhiyun /* move the r31 to mod since the result was positive */ 66*4882a593Smuzhiyun or r3, r0, r31 67*4882a593Smuzhiyun addik r30, r30, 1 68*4882a593Smuzhiyunmod_too_small: 69*4882a593Smuzhiyun addik r29, r29, -1 70*4882a593Smuzhiyun beqi r29, loop_end 71*4882a593Smuzhiyun add r30, r30, r30 /* shift in the '1' into div */ 72*4882a593Smuzhiyun bri div2 /* div2 */ 73*4882a593Smuzhiyunloop_end: 74*4882a593Smuzhiyun bri return_here 75*4882a593Smuzhiyundiv_by_zero: 76*4882a593Smuzhiyunresult_is_zero: 77*4882a593Smuzhiyun or r3, r0, r0 /* set result to 0 */ 78*4882a593Smuzhiyunreturn_here: 79*4882a593Smuzhiyun/* restore values of csrs and that of r3 and the divisor and the dividend */ 80*4882a593Smuzhiyun lwi r29, r1, 0 81*4882a593Smuzhiyun lwi r30, r1, 4 82*4882a593Smuzhiyun lwi r31, r1, 8 83*4882a593Smuzhiyun rtsd r15, 8 84*4882a593Smuzhiyun addik r1, r1, 12 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun.size __umodsi3, . - __umodsi3 87*4882a593Smuzhiyun.end __umodsi3 88