decode_arm.s 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // +build gc
  2. // +build !noasm
  3. #include "textflag.h"
  4. // Register allocation.
  5. #define dst R0
  6. #define dstorig R1
  7. #define src R2
  8. #define dstend R3
  9. #define srcend R4
  10. #define match R5 // Match address.
  11. #define token R6
  12. #define len R7 // Literal and match lengths.
  13. #define offset R5 // Match offset; overlaps with match.
  14. #define tmp1 R8
  15. #define tmp2 R9
  16. #define tmp3 R12
  17. #define minMatch $4
  18. // func decodeBlock(dst, src []byte) int
  19. TEXT ·decodeBlock(SB), NOFRAME|NOSPLIT, $-4-28
  20. MOVW dst_ptr+0(FP), dst
  21. MOVW dst_len+4(FP), dstend
  22. MOVW src_ptr+12(FP), src
  23. MOVW src_len+16(FP), srcend
  24. CMP $0, srcend
  25. BEQ shortSrc
  26. ADD dst, dstend
  27. ADD src, srcend
  28. MOVW dst, dstorig
  29. loop:
  30. CMP src, srcend
  31. BEQ end
  32. // Read token. Extract literal length.
  33. MOVBU.P 1(src), token
  34. MOVW token >> 4, len
  35. CMP $15, len
  36. BNE readLitlenDone
  37. readLitlenLoop:
  38. CMP src, srcend
  39. BEQ shortSrc
  40. MOVBU.P 1(src), tmp1
  41. ADD tmp1, len
  42. CMP $255, tmp1
  43. BEQ readLitlenLoop
  44. readLitlenDone:
  45. CMP $0, len
  46. BEQ copyLiteralDone
  47. // Bounds check dst+len and src+len.
  48. ADD dst, len, tmp1
  49. ADD src, len, tmp2
  50. CMP dstend, tmp1
  51. BHI shortDst
  52. CMP srcend, tmp2
  53. BHI shortSrc
  54. // Copy literal.
  55. CMP $4, len
  56. BLO copyLiteralFinish
  57. // Copy 0-3 bytes until src is aligned.
  58. TST $1, src
  59. MOVBU.NE.P 1(src), tmp1
  60. MOVB.NE.P tmp1, 1(dst)
  61. SUB.NE $1, len
  62. TST $2, src
  63. MOVHU.NE.P 2(src), tmp2
  64. MOVH.NE.P tmp2, 2(dst)
  65. SUB.NE $2, len
  66. CMP $4, len
  67. BLO copyLiteralFinish
  68. copyLiteralLoop:
  69. // Aligned load, unaligned write.
  70. SUB $4, len
  71. MOVW.P 4(src), tmp1
  72. MOVW tmp1 >> 8, tmp2
  73. MOVB tmp2, 1(dst)
  74. MOVW tmp1 >> 16, tmp3
  75. MOVB tmp3, 2(dst)
  76. MOVW tmp1 >> 24, tmp2
  77. MOVB tmp2, 3(dst)
  78. MOVB.P tmp1, 4(dst)
  79. CMP $4, len
  80. BHS copyLiteralLoop
  81. copyLiteralFinish:
  82. // Copy remaining 0-3 bytes.
  83. TST $2, len
  84. MOVHU.NE.P 2(src), tmp2
  85. MOVHU.NE.P tmp2, 2(dst)
  86. TST $1, len
  87. MOVBU.NE.P 1(src), tmp1
  88. MOVBU.NE.P tmp1, 1(dst)
  89. copyLiteralDone:
  90. CMP src, srcend
  91. BEQ end
  92. // Read offset.
  93. ADD $2, src
  94. CMP srcend, src
  95. BHI shortSrc
  96. MOVHU -2(src), offset
  97. CMP $0, offset
  98. BEQ corrupt
  99. // Read match length.
  100. AND $15, token, len
  101. CMP $15, len
  102. BNE readMatchlenDone
  103. readMatchlenLoop:
  104. CMP src, srcend
  105. BEQ shortSrc
  106. MOVBU.P 1(src), tmp1
  107. ADD tmp1, len
  108. CMP $255, tmp1
  109. BEQ readMatchlenLoop
  110. readMatchlenDone:
  111. ADD minMatch, len
  112. ADD dst, len, tmp1
  113. CMP dstend, tmp1
  114. BHI shortDst
  115. SUB offset, dst, match
  116. CMP dstorig, match
  117. BLO corrupt
  118. copyMatch:
  119. // Simple byte-at-a-time copy.
  120. SUB.S $1, len
  121. MOVBU.P 1(match), tmp2
  122. MOVB.P tmp2, 1(dst)
  123. BNE copyMatch
  124. B loop
  125. // The three error cases have distinct labels so we can put different
  126. // return codes here when debugging, or if the error returns need to
  127. // be changed.
  128. shortDst:
  129. shortSrc:
  130. corrupt:
  131. MOVW $-1, tmp1
  132. MOVW tmp1, ret+24(FP)
  133. RET
  134. end:
  135. SUB dstorig, dst, tmp1
  136. MOVW tmp1, ret+24(FP)
  137. RET