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