strings.inc 16 KB

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