strings.inc 15 KB

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