strings.inc 13 KB

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