copy_user.S 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * arch/alpha/lib/copy_user.S
  3. *
  4. * Copy to/from user space, handling exceptions as we go.. This
  5. * isn't exactly pretty.
  6. *
  7. * This is essentially the same as "memcpy()", but with a few twists.
  8. * Notably, we have to make sure that $0 is always up-to-date and
  9. * contains the right "bytes left to copy" value (and that it is updated
  10. * only _after_ a successful copy). There is also some rather minor
  11. * exception setup stuff..
  12. *
  13. * NOTE! This is not directly C-callable, because the calling semantics are
  14. * different:
  15. *
  16. * Inputs:
  17. * length in $0
  18. * destination address in $6
  19. * source address in $7
  20. * return address in $28
  21. *
  22. * Outputs:
  23. * bytes left to copy in $0
  24. *
  25. * Clobbers:
  26. * $1,$2,$3,$4,$5,$6,$7
  27. */
  28. #include <asm/export.h>
  29. /* Allow an exception for an insn; exit if we get one. */
  30. #define EXI(x,y...) \
  31. 99: x,##y; \
  32. .section __ex_table,"a"; \
  33. .long 99b - .; \
  34. lda $31, $exitin-99b($31); \
  35. .previous
  36. #define EXO(x,y...) \
  37. 99: x,##y; \
  38. .section __ex_table,"a"; \
  39. .long 99b - .; \
  40. lda $31, $exitout-99b($31); \
  41. .previous
  42. .set noat
  43. .align 4
  44. .globl __copy_user
  45. .ent __copy_user
  46. __copy_user:
  47. .prologue 0
  48. and $6,7,$3
  49. beq $0,$35
  50. beq $3,$36
  51. subq $3,8,$3
  52. .align 4
  53. $37:
  54. EXI( ldq_u $1,0($7) )
  55. EXO( ldq_u $2,0($6) )
  56. extbl $1,$7,$1
  57. mskbl $2,$6,$2
  58. insbl $1,$6,$1
  59. addq $3,1,$3
  60. bis $1,$2,$1
  61. EXO( stq_u $1,0($6) )
  62. subq $0,1,$0
  63. addq $6,1,$6
  64. addq $7,1,$7
  65. beq $0,$41
  66. bne $3,$37
  67. $36:
  68. and $7,7,$1
  69. bic $0,7,$4
  70. beq $1,$43
  71. beq $4,$48
  72. EXI( ldq_u $3,0($7) )
  73. .align 4
  74. $50:
  75. EXI( ldq_u $2,8($7) )
  76. subq $4,8,$4
  77. extql $3,$7,$3
  78. extqh $2,$7,$1
  79. bis $3,$1,$1
  80. EXO( stq $1,0($6) )
  81. addq $7,8,$7
  82. subq $0,8,$0
  83. addq $6,8,$6
  84. bis $2,$2,$3
  85. bne $4,$50
  86. $48:
  87. beq $0,$41
  88. .align 4
  89. $57:
  90. EXI( ldq_u $1,0($7) )
  91. EXO( ldq_u $2,0($6) )
  92. extbl $1,$7,$1
  93. mskbl $2,$6,$2
  94. insbl $1,$6,$1
  95. bis $1,$2,$1
  96. EXO( stq_u $1,0($6) )
  97. subq $0,1,$0
  98. addq $6,1,$6
  99. addq $7,1,$7
  100. bne $0,$57
  101. br $31,$41
  102. .align 4
  103. $43:
  104. beq $4,$65
  105. .align 4
  106. $66:
  107. EXI( ldq $1,0($7) )
  108. subq $4,8,$4
  109. EXO( stq $1,0($6) )
  110. addq $7,8,$7
  111. subq $0,8,$0
  112. addq $6,8,$6
  113. bne $4,$66
  114. $65:
  115. beq $0,$41
  116. EXI( ldq $2,0($7) )
  117. EXO( ldq $1,0($6) )
  118. mskql $2,$0,$2
  119. mskqh $1,$0,$1
  120. bis $2,$1,$2
  121. EXO( stq $2,0($6) )
  122. bis $31,$31,$0
  123. $41:
  124. $35:
  125. $exitin:
  126. $exitout:
  127. ret $31,($28),1
  128. .end __copy_user
  129. EXPORT_SYMBOL(__copy_user)