strings.inc 12 KB

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