strings.inc 15 KB

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