strings.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. Processor dependent part of strings.pp, that can be shared with
  6. sysutils unit.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$ASMMODE ATT}
  14. function strcopy(dest,source : pchar) : pchar;assembler;
  15. asm
  16. movl source,%edi
  17. testl %edi,%edi
  18. jz .LStrCopyDone
  19. leal 3(%edi),%ecx
  20. andl $-4,%ecx
  21. movl source,%esi
  22. subl %edi,%ecx
  23. movl dest,%edi
  24. jz .LStrCopyAligned
  25. .LStrCopyAlignLoop:
  26. movb (%esi),%al
  27. incl %edi
  28. incl %esi
  29. testb %al,%al
  30. movb %al,-1(%edi)
  31. jz .LStrCopyDone
  32. decl %ecx
  33. jnz .LStrCopyAlignLoop
  34. .balign 16
  35. .LStrCopyAligned:
  36. movl (%esi),%eax
  37. movl %eax,%edx
  38. leal 0x0fefefeff(%eax),%ecx
  39. notl %edx
  40. addl $4,%esi
  41. andl %edx,%ecx
  42. andl $0x080808080,%ecx
  43. jnz .LStrCopyEndFound
  44. movl %eax,(%edi)
  45. addl $4,%edi
  46. jmp .LStrCopyAligned
  47. .LStrCopyEndFound:
  48. testl $0x0ff,%eax
  49. jz .LStrCopyByte
  50. testl $0x0ff00,%eax
  51. jz .LStrCopyWord
  52. testl $0x0ff0000,%eax
  53. jz .LStrCopy3Bytes
  54. movl %eax,(%edi)
  55. jmp .LStrCopyDone
  56. .LStrCopy3Bytes:
  57. xorb %dl,%dl
  58. movw %ax,(%edi)
  59. movb %dl,2(%edi)
  60. jmp .LStrCopyDone
  61. .LStrCopyWord:
  62. movw %ax,(%edi)
  63. jmp .LStrCopyDone
  64. .LStrCopyByte:
  65. movb %al,(%edi)
  66. .LStrCopyDone:
  67. movl dest,%eax
  68. end ['EAX','EDX','ECX','ESI','EDI'];
  69. function strecopy(dest,source : pchar) : pchar;assembler;
  70. asm
  71. cld
  72. movl source,%edi
  73. movl $0xffffffff,%ecx
  74. xorl %eax,%eax
  75. repne
  76. scasb
  77. not %ecx
  78. movl dest,%edi
  79. movl source,%esi
  80. movl %ecx,%eax
  81. shrl $2,%ecx
  82. rep
  83. movsl
  84. movl %eax,%ecx
  85. andl $3,%ecx
  86. rep
  87. movsb
  88. movl dest,%eax
  89. decl %edi
  90. movl %edi,%eax
  91. end ['EAX','ECX','ESI','EDI'];
  92. function strlcopy(dest,source : pchar;maxlen : longint) : pchar;assembler;
  93. asm
  94. movl source,%esi
  95. movl maxlen,%ecx
  96. movl dest,%edi
  97. orl %ecx,%ecx
  98. jz .LSTRLCOPY2
  99. cld
  100. .LSTRLCOPY1:
  101. lodsb
  102. stosb
  103. decl %ecx // Lower maximum
  104. jz .LSTRLCOPY2 // 0 reached ends
  105. orb %al,%al
  106. jnz .LSTRLCOPY1
  107. jmp .LSTRLCOPY3
  108. .LSTRLCOPY2:
  109. xorb %al,%al // If cutted
  110. stosb // add a #0
  111. .LSTRLCOPY3:
  112. movl dest,%eax
  113. end ['EAX','ECX','ESI','EDI'];
  114. function strlen(p : pchar) : longint;assembler;
  115. {$i strlen.inc}
  116. function strend(p : pchar) : pchar;assembler;
  117. asm
  118. cld
  119. xorl %eax,%eax
  120. movl p,%edi
  121. orl %edi,%edi
  122. jz .LStrEndNil
  123. movl $0xffffffff,%ecx
  124. xorl %eax,%eax
  125. repne
  126. scasb
  127. movl %edi,%eax
  128. decl %eax
  129. .LStrEndNil:
  130. end ['EDI','ECX','EAX'];
  131. function strcomp(str1,str2 : pchar) : longint;assembler;
  132. asm
  133. movl str2,%edi
  134. movl $0xffffffff,%ecx
  135. cld
  136. xorl %eax,%eax
  137. repne
  138. scasb
  139. not %ecx
  140. movl str2,%edi
  141. movl str1,%esi
  142. repe
  143. cmpsb
  144. movb -1(%esi),%al
  145. movzbl -1(%edi),%ecx
  146. subl %ecx,%eax
  147. end ['EAX','ECX','ESI','EDI'];
  148. function strlcomp(str1,str2 : pchar;l : longint) : longint;assembler;
  149. asm
  150. movl str2,%edi
  151. movl $0xffffffff,%ecx
  152. cld
  153. xorl %eax,%eax
  154. repne
  155. scasb
  156. not %ecx
  157. cmpl l,%ecx
  158. jl .LSTRLCOMP1
  159. movl l,%ecx
  160. .LSTRLCOMP1:
  161. movl str2,%edi
  162. movl str1,%esi
  163. repe
  164. cmpsb
  165. movb -1(%esi),%al
  166. movzbl -1(%edi),%ecx
  167. subl %ecx,%eax
  168. end ['EAX','ECX','ESI','EDI'];
  169. function stricomp(str1,str2 : pchar) : longint;assembler;
  170. asm
  171. movl str2,%edi
  172. movl $0xffffffff,%ecx
  173. cld
  174. xorl %eax,%eax
  175. repne
  176. scasb
  177. not %ecx
  178. movl str2,%edi
  179. movl str1,%esi
  180. .LSTRICOMP2:
  181. repe
  182. cmpsb
  183. jz .LSTRICOMP3 // If last reached then exit
  184. movzbl -1(%esi),%eax
  185. movzbl -1(%edi),%ebx
  186. cmpb $97,%al
  187. jb .LSTRICOMP1
  188. cmpb $122,%al
  189. ja .LSTRICOMP1
  190. subb $0x20,%al
  191. .LSTRICOMP1:
  192. cmpb $97,%bl
  193. jb .LSTRICOMP4
  194. cmpb $122,%bl
  195. ja .LSTRICOMP4
  196. subb $0x20,%bl
  197. .LSTRICOMP4:
  198. subl %ebx,%eax
  199. jz .LSTRICOMP2 // If still equal, compare again
  200. .LSTRICOMP3:
  201. end ['EAX','EBX','ECX','ESI','EDI'];
  202. function strlicomp(str1,str2 : pchar;l : longint) : longint;assembler;
  203. asm
  204. movl str2,%edi
  205. movl $0xffffffff,%ecx
  206. cld
  207. xorl %eax,%eax
  208. repne
  209. scasb
  210. not %ecx
  211. cmpl l,%ecx
  212. jl .LSTRLICOMP5
  213. movl l,%ecx
  214. .LSTRLICOMP5:
  215. movl str2,%edi
  216. movl str1,%esi
  217. .LSTRLICOMP2:
  218. repe
  219. cmpsb
  220. jz .LSTRLICOMP3 // If last reached, exit
  221. movzbl -1(%esi),%eax
  222. movzbl -1(%edi),%ebx
  223. cmpb $97,%al
  224. jb .LSTRLICOMP1
  225. cmpb $122,%al
  226. ja .LSTRLICOMP1
  227. subb $0x20,%al
  228. .LSTRLICOMP1:
  229. cmpb $97,%bl
  230. jb .LSTRLICOMP4
  231. cmpb $122,%bl
  232. ja .LSTRLICOMP4
  233. subb $0x20,%bl
  234. .LSTRLICOMP4:
  235. subl %ebx,%eax
  236. jz .LSTRLICOMP2
  237. .LSTRLICOMP3:
  238. end ['EAX','EBX','ECX','ESI','EDI'];
  239. function strscan(p : pchar;c : char) : pchar;assembler;
  240. asm
  241. movl p,%eax
  242. xorl %ecx,%ecx
  243. testl %eax,%eax
  244. jz .LSTRSCAN
  245. // align
  246. movb c,%cl
  247. leal 3(%eax),%esi
  248. andl $-4,%esi
  249. movl p,%edi
  250. subl %eax,%esi
  251. jz .LSTRSCANALIGNED
  252. xorl %eax,%eax
  253. .LSTRSCANALIGNLOOP:
  254. movb (%edi),%al
  255. // at .LSTRSCANFOUND, one is substracted from edi to calculate the position,
  256. // so add 1 here already (not after .LSTRSCAN, because then the test/jz and
  257. // cmp/je can't be paired)
  258. incl %edi
  259. testb %al,%al
  260. jz .LSTRSCAN
  261. cmpb %cl,%al
  262. je .LSTRSCANFOUND
  263. decl %esi
  264. jnz .LSTRSCANALIGNLOOP
  265. .LSTRSCANALIGNED:
  266. // fill ecx with cccc
  267. movl %ecx,%eax
  268. shll $8,%eax
  269. orl %eax,%ecx
  270. movl %ecx,%eax
  271. shll $16,%eax
  272. orl %eax,%ecx
  273. .balign 16
  274. .LSTRSCANLOOP:
  275. // load new 4 bytes
  276. movl (%edi),%edx
  277. // in eax, we will check if "c" appear in the loaded dword
  278. movl %edx,%eax
  279. // esi will be used to calculate the mask
  280. movl %edx,%esi
  281. notl %esi
  282. // in edx we will check for the end of the string
  283. addl $0x0fefefeff,%edx
  284. xorl %ecx,%eax
  285. andl $0x080808080,%esi
  286. addl $4,%edi
  287. andl %esi,%edx
  288. movl %eax,%esi
  289. notl %esi
  290. jnz .LSTRSCANLONGCHECK
  291. addl $0x0fefefeff,%eax
  292. andl $0x080808080,%esi
  293. andl %esi,%eax
  294. jz .LSTRSCANLOOP
  295. // the position in %eax where the char was found is now $80, so keep on
  296. // shifting 8 bits out of %eax until we find a non-zero bit.
  297. // first char
  298. shrl $8,%eax
  299. jc .LSTRSCANFOUND1
  300. // second char
  301. shrl $8,%eax
  302. jc .LSTRSCANFOUND2
  303. // third char
  304. shrl $8,%eax
  305. jc .LSTRSCANFOUND3
  306. // fourth char
  307. jmp .LSTRSCANFOUND
  308. .LSTRSCANLONGCHECK:
  309. // there's a null somewhere, but we still have to check whether there isn't
  310. // a 'c' before it.
  311. addl $0x0fefefeff,%eax
  312. andl $0x080808080,%esi
  313. andl %esi,%eax
  314. // Now, in eax we have $80 on the positions where there were c-chars and in
  315. // edx we have $80 on the positions where there were #0's. On all other
  316. // positions, there is now #0
  317. // first char
  318. shrl $8,%eax
  319. jc .LSTRSCANFOUND1
  320. shrl $8,%edx
  321. jc .LSTRSCANNOTFOUND
  322. // second char
  323. shrl $8,%eax
  324. jc .LSTRSCANFOUND2
  325. shrl $8,%edx
  326. jc .LSTRSCANNOTFOUND
  327. // third char
  328. shrl $8,%eax
  329. jc .LSTRSCANFOUND3
  330. shrl $8,%edx
  331. jc .LSTRSCANNOTFOUND
  332. // we know the fourth char is now #0 (since we only jump to the long check if
  333. // there is a #0 char somewhere), but it's possible c = #0, and than we have
  334. // to return the end of the string and not nil!
  335. shrl $8,%eax
  336. jc .LSTRSCANFOUND
  337. jmp .LSTRSCANNOTFOUND
  338. .LSTRSCANFOUND3:
  339. leal -2(%edi),%eax
  340. jmp .LSTRSCAN
  341. .LSTRSCANFOUND2:
  342. leal -3(%edi),%eax
  343. jmp .LSTRSCAN
  344. .LSTRSCANFOUND1:
  345. leal -4(%edi),%eax
  346. jmp .LSTRSCAN
  347. .LSTRSCANFOUND:
  348. leal -1(%edi),%eax
  349. jmp .LSTRSCAN
  350. .LSTRSCANNOTFOUND:
  351. xorl %eax,%eax
  352. .LSTRSCAN:
  353. end ['EAX','ECX','ESI','EDI','EDX'];
  354. function strrscan(p : pchar;c : char) : pchar;assembler;
  355. asm
  356. xorl %eax,%eax
  357. movl p,%edi
  358. orl %edi,%edi
  359. jz .LSTRRSCAN
  360. movl $0xffffffff,%ecx
  361. cld
  362. xorb %al,%al
  363. repne
  364. scasb
  365. not %ecx
  366. movb c,%al
  367. movl p,%edi
  368. addl %ecx,%edi
  369. decl %edi
  370. std
  371. repne
  372. scasb
  373. cld
  374. movl $0,%eax
  375. jnz .LSTRRSCAN
  376. movl %edi,%eax
  377. incl %eax
  378. .LSTRRSCAN:
  379. end ['EAX','ECX','EDI'];
  380. function strupper(p : pchar) : pchar;assembler;
  381. asm
  382. movl p,%esi
  383. orl %esi,%esi
  384. jz .LStrUpperNil
  385. movl %esi,%edi
  386. .LSTRUPPER1:
  387. lodsb
  388. cmpb $97,%al
  389. jb .LSTRUPPER3
  390. cmpb $122,%al
  391. ja .LSTRUPPER3
  392. subb $0x20,%al
  393. .LSTRUPPER3:
  394. stosb
  395. orb %al,%al
  396. jnz .LSTRUPPER1
  397. .LStrUpperNil:
  398. movl p,%eax
  399. end ['EAX','ESI','EDI'];
  400. function strlower(p : pchar) : pchar;assembler;
  401. asm
  402. movl p,%esi
  403. orl %esi,%esi
  404. jz .LStrLowerNil
  405. movl %esi,%edi
  406. .LSTRLOWER1:
  407. lodsb
  408. cmpb $65,%al
  409. jb .LSTRLOWER3
  410. cmpb $90,%al
  411. ja .LSTRLOWER3
  412. addb $0x20,%al
  413. .LSTRLOWER3:
  414. stosb
  415. orb %al,%al
  416. jnz .LSTRLOWER1
  417. .LStrLowerNil:
  418. movl p,%eax
  419. end ['EAX','ESI','EDI'];
  420. {
  421. $Log$
  422. Revision 1.7 2002-09-07 16:01:19 peter
  423. * old logs removed and tabs fixed
  424. }