umodsi3.S 2.0 KB

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