strings.inc 14 KB

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