root/arch/microblaze/lib/udivsi3.S

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

/* [<][>][^][v][top][bottom][index][help] */