strings.inc 16 KB

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