strlen_user.S 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * arch/alpha/lib/strlen_user.S
  3. *
  4. * Return the length of the string including the NUL terminator
  5. * (strlen+1) or zero if an error occurred.
  6. *
  7. * In places where it is critical to limit the processing time,
  8. * and the data is not trusted, strnlen_user() should be used.
  9. * It will return a value greater than its second argument if
  10. * that limit would be exceeded. This implementation is allowed
  11. * to access memory beyond the limit, but will not cross a page
  12. * boundary when doing so.
  13. */
  14. #include <asm/regdef.h>
  15. /* Allow an exception for an insn; exit if we get one. */
  16. #define EX(x,y...) \
  17. 99: x,##y; \
  18. .section __ex_table,"a"; \
  19. .long 99b - .; \
  20. lda v0, $exception-99b(zero); \
  21. .previous
  22. .set noreorder
  23. .set noat
  24. .text
  25. .globl __strlen_user
  26. .ent __strlen_user
  27. .frame sp, 0, ra
  28. .align 3
  29. __strlen_user:
  30. ldah a1, 32767(zero) # do not use plain strlen_user() for strings
  31. # that might be almost 2 GB long; you should
  32. # be using strnlen_user() instead
  33. .globl __strnlen_user
  34. .align 3
  35. __strnlen_user:
  36. .prologue 0
  37. EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned)
  38. lda t1, -1(zero)
  39. insqh t1, a0, t1
  40. andnot a0, 7, v0
  41. or t1, t0, t0
  42. subq a0, 1, a0 # get our +1 for the return
  43. cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
  44. subq a1, 7, t2
  45. subq a0, v0, t0
  46. bne t1, $found
  47. addq t2, t0, t2
  48. addq a1, 1, a1
  49. .align 3
  50. $loop: ble t2, $limit
  51. EX( ldq t0, 8(v0) )
  52. subq t2, 8, t2
  53. addq v0, 8, v0 # addr += 8
  54. cmpbge zero, t0, t1
  55. beq t1, $loop
  56. $found: negq t1, t2 # clear all but least set bit
  57. and t1, t2, t1
  58. and t1, 0xf0, t2 # binary search for that set bit
  59. and t1, 0xcc, t3
  60. and t1, 0xaa, t4
  61. cmovne t2, 4, t2
  62. cmovne t3, 2, t3
  63. cmovne t4, 1, t4
  64. addq t2, t3, t2
  65. addq v0, t4, v0
  66. addq v0, t2, v0
  67. nop # dual issue next two on ev4 and ev5
  68. subq v0, a0, v0
  69. $exception:
  70. ret
  71. .align 3 # currently redundant
  72. $limit:
  73. subq a1, t2, v0
  74. ret
  75. .end __strlen_user