memmove.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
  3. * Copyright (C) 2004 Microtronix Datacom Ltd
  4. *
  5. * This file is subject to the terms and conditions of the GNU General Public
  6. * License. See the file "COPYING" in the main directory of this archive
  7. * for more details.
  8. */
  9. #include <linux/types.h>
  10. #include <linux/string.h>
  11. #ifdef __HAVE_ARCH_MEMMOVE
  12. void *memmove(void *d, const void *s, size_t count)
  13. {
  14. unsigned long dst, src;
  15. if (!count)
  16. return d;
  17. if (d < s) {
  18. dst = (unsigned long) d;
  19. src = (unsigned long) s;
  20. if ((count < 8) || ((dst ^ src) & 3))
  21. goto restup;
  22. if (dst & 1) {
  23. *(char *)dst++ = *(char *)src++;
  24. count--;
  25. }
  26. if (dst & 2) {
  27. *(short *)dst = *(short *)src;
  28. src += 2;
  29. dst += 2;
  30. count -= 2;
  31. }
  32. while (count > 3) {
  33. *(long *)dst = *(long *)src;
  34. src += 4;
  35. dst += 4;
  36. count -= 4;
  37. }
  38. restup:
  39. while (count--)
  40. *(char *)dst++ = *(char *)src++;
  41. } else {
  42. dst = (unsigned long) d + count;
  43. src = (unsigned long) s + count;
  44. if ((count < 8) || ((dst ^ src) & 3))
  45. goto restdown;
  46. if (dst & 1) {
  47. src--;
  48. dst--;
  49. count--;
  50. *(char *)dst = *(char *)src;
  51. }
  52. if (dst & 2) {
  53. src -= 2;
  54. dst -= 2;
  55. count -= 2;
  56. *(short *)dst = *(short *)src;
  57. }
  58. while (count > 3) {
  59. src -= 4;
  60. dst -= 4;
  61. count -= 4;
  62. *(long *)dst = *(long *)src;
  63. }
  64. restdown:
  65. while (count--) {
  66. src--;
  67. dst--;
  68. *(char *)dst = *(char *)src;
  69. }
  70. }
  71. return d;
  72. }
  73. #endif /* __HAVE_ARCH_MEMMOVE */