2
0

bufferiszero.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Simple C functions to supplement the C library
  3. *
  4. * Copyright (c) 2006 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qemu/cutils.h"
  26. #include "qemu/bswap.h"
  27. #include "host/cpuinfo.h"
  28. typedef bool (*biz_accel_fn)(const void *, size_t);
  29. static bool buffer_is_zero_int_lt256(const void *buf, size_t len)
  30. {
  31. uint64_t t;
  32. const uint64_t *p, *e;
  33. /*
  34. * Use unaligned memory access functions to handle
  35. * the beginning and end of the buffer.
  36. */
  37. if (unlikely(len <= 8)) {
  38. return (ldl_he_p(buf) | ldl_he_p(buf + len - 4)) == 0;
  39. }
  40. t = ldq_he_p(buf) | ldq_he_p(buf + len - 8);
  41. p = QEMU_ALIGN_PTR_DOWN(buf + 8, 8);
  42. e = QEMU_ALIGN_PTR_DOWN(buf + len - 1, 8);
  43. /* Read 0 to 31 aligned words from the middle. */
  44. while (p < e) {
  45. t |= *p++;
  46. }
  47. return t == 0;
  48. }
  49. static bool buffer_is_zero_int_ge256(const void *buf, size_t len)
  50. {
  51. /*
  52. * Use unaligned memory access functions to handle
  53. * the beginning and end of the buffer.
  54. */
  55. uint64_t t = ldq_he_p(buf) | ldq_he_p(buf + len - 8);
  56. const uint64_t *p = QEMU_ALIGN_PTR_DOWN(buf + 8, 8);
  57. const uint64_t *e = QEMU_ALIGN_PTR_DOWN(buf + len - 1, 8);
  58. /* Collect a partial block at the tail end. */
  59. t |= e[-7] | e[-6] | e[-5] | e[-4] | e[-3] | e[-2] | e[-1];
  60. /*
  61. * Loop over 64 byte blocks.
  62. * With the head and tail removed, e - p >= 30,
  63. * so the loop must iterate at least 3 times.
  64. */
  65. do {
  66. if (t) {
  67. return false;
  68. }
  69. t = p[0] | p[1] | p[2] | p[3] | p[4] | p[5] | p[6] | p[7];
  70. p += 8;
  71. } while (p < e - 7);
  72. return t == 0;
  73. }
  74. #include "host/bufferiszero.c.inc"
  75. static biz_accel_fn buffer_is_zero_accel;
  76. static unsigned accel_index;
  77. bool buffer_is_zero_ool(const void *buf, size_t len)
  78. {
  79. if (unlikely(len == 0)) {
  80. return true;
  81. }
  82. if (!buffer_is_zero_sample3(buf, len)) {
  83. return false;
  84. }
  85. /* All bytes are covered for any len <= 3. */
  86. if (unlikely(len <= 3)) {
  87. return true;
  88. }
  89. if (likely(len >= 256)) {
  90. return buffer_is_zero_accel(buf, len);
  91. }
  92. return buffer_is_zero_int_lt256(buf, len);
  93. }
  94. bool buffer_is_zero_ge256(const void *buf, size_t len)
  95. {
  96. return buffer_is_zero_accel(buf, len);
  97. }
  98. bool test_buffer_is_zero_next_accel(void)
  99. {
  100. if (accel_index != 0) {
  101. buffer_is_zero_accel = accel_table[--accel_index];
  102. return true;
  103. }
  104. return false;
  105. }
  106. static void __attribute__((constructor)) init_accel(void)
  107. {
  108. accel_index = best_accel();
  109. buffer_is_zero_accel = accel_table[accel_index];
  110. }