div64.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * This file is copied from the coreboot repository as part of
  3. * the libpayload project:
  4. *
  5. * Copyright 2014 Google Inc.
  6. *
  7. * SPDX-License-Identifier: BSD-3-Clause
  8. */
  9. #include <common.h>
  10. union overlay64 {
  11. u64 longw;
  12. struct {
  13. u32 lower;
  14. u32 higher;
  15. } words;
  16. };
  17. u64 __ashldi3(u64 num, unsigned int shift)
  18. {
  19. union overlay64 output;
  20. output.longw = num;
  21. if (shift >= 32) {
  22. output.words.higher = output.words.lower << (shift - 32);
  23. output.words.lower = 0;
  24. } else {
  25. if (!shift)
  26. return num;
  27. output.words.higher = (output.words.higher << shift) |
  28. (output.words.lower >> (32 - shift));
  29. output.words.lower = output.words.lower << shift;
  30. }
  31. return output.longw;
  32. }
  33. u64 __lshrdi3(u64 num, unsigned int shift)
  34. {
  35. union overlay64 output;
  36. output.longw = num;
  37. if (shift >= 32) {
  38. output.words.lower = output.words.higher >> (shift - 32);
  39. output.words.higher = 0;
  40. } else {
  41. if (!shift)
  42. return num;
  43. output.words.lower = output.words.lower >> shift |
  44. (output.words.higher << (32 - shift));
  45. output.words.higher = output.words.higher >> shift;
  46. }
  47. return output.longw;
  48. }
  49. #define MAX_32BIT_UINT ((((u64)1) << 32) - 1)
  50. static u64 _64bit_divide(u64 dividend, u64 divider, u64 *rem_p)
  51. {
  52. u64 result = 0;
  53. /*
  54. * If divider is zero - let the rest of the system care about the
  55. * exception.
  56. */
  57. if (!divider)
  58. return 1 / (u32)divider;
  59. /* As an optimization, let's not use 64 bit division unless we must. */
  60. if (dividend <= MAX_32BIT_UINT) {
  61. if (divider > MAX_32BIT_UINT) {
  62. result = 0;
  63. if (rem_p)
  64. *rem_p = divider;
  65. } else {
  66. result = (u32)dividend / (u32)divider;
  67. if (rem_p)
  68. *rem_p = (u32)dividend % (u32)divider;
  69. }
  70. return result;
  71. }
  72. while (divider <= dividend) {
  73. u64 locald = divider;
  74. u64 limit = __lshrdi3(dividend, 1);
  75. int shifts = 0;
  76. while (locald <= limit) {
  77. shifts++;
  78. locald = locald + locald;
  79. }
  80. result |= __ashldi3(1, shifts);
  81. dividend -= locald;
  82. }
  83. if (rem_p)
  84. *rem_p = dividend;
  85. return result;
  86. }
  87. u64 __udivdi3(u64 num, u64 den)
  88. {
  89. return _64bit_divide(num, den, NULL);
  90. }
  91. u64 __umoddi3(u64 num, u64 den)
  92. {
  93. u64 v = 0;
  94. _64bit_divide(num, den, &v);
  95. return v;
  96. }