memmove.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. void *memmove(void *d, const void *s, size_t count)
  12. {
  13. unsigned long dst, src;
  14. if (!count)
  15. return d;
  16. if (d < s) {
  17. dst = (unsigned long) d;
  18. src = (unsigned long) s;
  19. if ((count < 8) || ((dst ^ src) & 3))
  20. goto restup;
  21. if (dst & 1) {
  22. *(char *)dst++ = *(char *)src++;
  23. count--;
  24. }
  25. if (dst & 2) {
  26. *(short *)dst = *(short *)src;
  27. src += 2;
  28. dst += 2;
  29. count -= 2;
  30. }
  31. while (count > 3) {
  32. *(long *)dst = *(long *)src;
  33. src += 4;
  34. dst += 4;
  35. count -= 4;
  36. }
  37. restup:
  38. while (count--)
  39. *(char *)dst++ = *(char *)src++;
  40. } else {
  41. dst = (unsigned long) d + count;
  42. src = (unsigned long) s + count;
  43. if ((count < 8) || ((dst ^ src) & 3))
  44. goto restdown;
  45. if (dst & 1) {
  46. src--;
  47. dst--;
  48. count--;
  49. *(char *)dst = *(char *)src;
  50. }
  51. if (dst & 2) {
  52. src -= 2;
  53. dst -= 2;
  54. count -= 2;
  55. *(short *)dst = *(short *)src;
  56. }
  57. while (count > 3) {
  58. src -= 4;
  59. dst -= 4;
  60. count -= 4;
  61. *(long *)dst = *(long *)src;
  62. }
  63. restdown:
  64. while (count--) {
  65. src--;
  66. dst--;
  67. *(char *)dst = *(char *)src;
  68. }
  69. }
  70. return d;
  71. }