umodsi3.S 1.9 KB

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