strings.inc 16 KB

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