csumpartialcopyuser.S 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * linux/arch/arm26/lib/csumpartialcopyuser.S
  3. *
  4. * Copyright (C) 1995-1998 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/config.h>
  11. #include <linux/linkage.h>
  12. #include <asm/assembler.h>
  13. #include <asm/errno.h>
  14. #include <asm/asm-offsets.h>
  15. .text
  16. .macro save_regs
  17. stmfd sp!, {r1 - r2, r4 - r9, fp, ip, lr, pc}
  18. mov r9, sp, lsr #13
  19. mov r9, r9, lsl #13
  20. ldr r9, [r9, #TSK_ADDR_LIMIT]
  21. mov r9, r9, lsr #24
  22. .endm
  23. .macro load_regs,flags
  24. ldm\flags fp, {r1, r2, r4-r9, fp, sp, pc}^
  25. .endm
  26. .macro load1b, reg1
  27. tst r9, #0x01
  28. 9999: ldreqbt \reg1, [r0], #1
  29. ldrneb \reg1, [r0], #1
  30. .section __ex_table, "a"
  31. .align 3
  32. .long 9999b, 6001f
  33. .previous
  34. .endm
  35. .macro load2b, reg1, reg2
  36. tst r9, #0x01
  37. 9999: ldreqbt \reg1, [r0], #1
  38. ldrneb \reg1, [r0], #1
  39. 9998: ldreqbt \reg2, [r0], #1
  40. ldrneb \reg2, [r0], #1
  41. .section __ex_table, "a"
  42. .long 9999b, 6001f
  43. .long 9998b, 6001f
  44. .previous
  45. .endm
  46. .macro load1l, reg1
  47. tst r9, #0x01
  48. 9999: ldreqt \reg1, [r0], #4
  49. ldrne \reg1, [r0], #4
  50. .section __ex_table, "a"
  51. .align 3
  52. .long 9999b, 6001f
  53. .previous
  54. .endm
  55. .macro load2l, reg1, reg2
  56. tst r9, #0x01
  57. ldmneia r0!, {\reg1, \reg2}
  58. 9999: ldreqt \reg1, [r0], #4
  59. 9998: ldreqt \reg2, [r0], #4
  60. .section __ex_table, "a"
  61. .long 9999b, 6001f
  62. .long 9998b, 6001f
  63. .previous
  64. .endm
  65. .macro load4l, reg1, reg2, reg3, reg4
  66. tst r9, #0x01
  67. ldmneia r0!, {\reg1, \reg2, \reg3, \reg4}
  68. 9999: ldreqt \reg1, [r0], #4
  69. 9998: ldreqt \reg2, [r0], #4
  70. 9997: ldreqt \reg3, [r0], #4
  71. 9996: ldreqt \reg4, [r0], #4
  72. .section __ex_table, "a"
  73. .long 9999b, 6001f
  74. .long 9998b, 6001f
  75. .long 9997b, 6001f
  76. .long 9996b, 6001f
  77. .previous
  78. .endm
  79. /*
  80. * unsigned int
  81. * csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr)
  82. * r0 = src, r1 = dst, r2 = len, r3 = sum, [sp] = *err_ptr
  83. * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
  84. */
  85. #define FN_ENTRY ENTRY(csum_partial_copy_from_user)
  86. #include "csumpartialcopygeneric.S"
  87. /*
  88. * FIXME: minor buglet here
  89. * We don't return the checksum for the data present in the buffer. To do
  90. * so properly, we would have to add in whatever registers were loaded before
  91. * the fault, which, with the current asm above is not predictable.
  92. */
  93. .align 4
  94. 6001: mov r4, #-EFAULT
  95. ldr r5, [fp, #4] @ *err_ptr
  96. str r4, [r5]
  97. ldmia sp, {r1, r2} @ retrieve dst, len
  98. add r2, r2, r1
  99. mov r0, #0 @ zero the buffer
  100. 6002: teq r2, r1
  101. strneb r0, [r1], #1
  102. bne 6002b
  103. load_regs ea