strings.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  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. repne
  163. scasb
  164. movl %edi,%eax
  165. decl %eax
  166. .LStrEndNil:
  167. movl saveedi,%edi
  168. end;
  169. {$endif FPC_UNIT_HAS_STREND}
  170. {$ifndef FPC_UNIT_HAS_STRCOMP}
  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. movl %eax,saveeax
  179. movl %edx,saveedx
  180. movl str2,%edi
  181. movl $0xffffffff,%ecx
  182. {$ifdef FPC_ENABLED_CLD}
  183. cld
  184. {$endif FPC_ENABLED_CLD}
  185. xorl %eax,%eax
  186. repne
  187. scasb
  188. not %ecx
  189. movl saveedx,%edi
  190. movl saveeax,%esi
  191. repe
  192. cmpsb
  193. movb -1(%esi),%al
  194. movzbl -1(%edi),%ecx
  195. subl %ecx,%eax
  196. movl saveedi,%edi
  197. movl saveesi,%esi
  198. end;
  199. {$endif FPC_UNIT_HAS_STRCOMP}
  200. {$ifndef FPC_UNIT_HAS_STRLCOMP}
  201. {$define FPC_UNIT_HAS_STRLCOMP}
  202. function strlcomp(str1,str2 : pchar;l : sizeint) : longint;assembler;
  203. var
  204. saveeax,saveedx,saveecx,saveesi,saveedi : longint;
  205. asm
  206. movl %edi,saveedi
  207. movl %esi,saveesi
  208. movl %eax,saveeax
  209. movl %edx,saveedx
  210. movl %ecx,saveecx
  211. movl str2,%edi
  212. movl $0xffffffff,%ecx
  213. {$ifdef FPC_ENABLED_CLD}
  214. cld
  215. {$endif FPC_ENABLED_CLD}
  216. xorl %eax,%eax
  217. repne
  218. scasb
  219. not %ecx
  220. cmpl saveecx,%ecx
  221. jl .LSTRLCOMP1
  222. movl saveecx,%ecx
  223. .LSTRLCOMP1:
  224. movl saveedx,%edi
  225. movl saveeax,%esi
  226. repe
  227. cmpsb
  228. movb -1(%esi),%al
  229. movzbl -1(%edi),%ecx
  230. subl %ecx,%eax
  231. movl saveedi,%edi
  232. movl saveesi,%esi
  233. end;
  234. {$endif FPC_UNIT_HAS_STRLCOMP}
  235. {$ifndef FPC_UNIT_HAS_STRICOMP}
  236. {$define FPC_UNIT_HAS_STRICOMP}
  237. function stricomp(str1,str2 : pchar) : longint;assembler;
  238. var
  239. saveeax,saveedx,saveesi,saveedi : longint;
  240. asm
  241. movl %edi,saveedi
  242. movl %esi,saveesi
  243. movl %eax,saveeax
  244. movl %edx,saveedx
  245. movl str2,%edi
  246. movl $0xffffffff,%ecx
  247. {$ifdef FPC_ENABLED_CLD}
  248. cld
  249. {$endif FPC_ENABLED_CLD}
  250. xorl %eax,%eax
  251. repne
  252. scasb
  253. not %ecx
  254. movl saveedx,%edi
  255. movl saveeax,%esi
  256. .LSTRICOMP2:
  257. repe
  258. cmpsb
  259. jz .LSTRICOMP3 // If last reached then exit
  260. movzbl -1(%esi),%eax
  261. movzbl -1(%edi),%edx
  262. cmpb $97,%al
  263. jb .LSTRICOMP1
  264. cmpb $122,%al
  265. ja .LSTRICOMP1
  266. subb $0x20,%al
  267. .LSTRICOMP1:
  268. cmpb $97,%dl
  269. jb .LSTRICOMP4
  270. cmpb $122,%dl
  271. ja .LSTRICOMP4
  272. subb $0x20,%dl
  273. .LSTRICOMP4:
  274. subl %edx,%eax
  275. jz .LSTRICOMP2 // If still equal, compare again
  276. .LSTRICOMP3:
  277. movl saveedi,%edi
  278. movl saveesi,%esi
  279. end;
  280. {$endif FPC_UNIT_HAS_STRICOMP}
  281. {$ifndef FPC_UNIT_HAS_STRLICOMP}
  282. {$define FPC_UNIT_HAS_STRLICOMP}
  283. function strlicomp(str1,str2 : pchar;l : sizeint) : longint;assembler;
  284. var
  285. saveeax,saveedx,saveecx,saveesi,saveedi : longint;
  286. asm
  287. movl %edi,saveedi
  288. movl %esi,saveesi
  289. movl %eax,saveeax
  290. movl %edx,saveedx
  291. movl %ecx,saveecx
  292. movl str2,%edi
  293. movl $0xffffffff,%ecx
  294. {$ifdef FPC_ENABLED_CLD}
  295. cld
  296. {$endif FPC_ENABLED_CLD}
  297. xorl %eax,%eax
  298. repne
  299. scasb
  300. not %ecx
  301. cmpl saveecx,%ecx
  302. jl .LSTRLICOMP5
  303. movl saveecx,%ecx
  304. .LSTRLICOMP5:
  305. movl saveedx,%edi
  306. movl saveeax,%esi
  307. .LSTRLICOMP2:
  308. repe
  309. cmpsb
  310. jz .LSTRLICOMP3 // If last reached, exit
  311. movzbl -1(%esi),%eax
  312. movzbl -1(%edi),%edx
  313. cmpb $97,%al
  314. jb .LSTRLICOMP1
  315. cmpb $122,%al
  316. ja .LSTRLICOMP1
  317. subb $0x20,%al
  318. .LSTRLICOMP1:
  319. cmpb $97,%dl
  320. jb .LSTRLICOMP4
  321. cmpb $122,%dl
  322. ja .LSTRLICOMP4
  323. subb $0x20,%dl
  324. .LSTRLICOMP4:
  325. subl %edx,%eax
  326. jz .LSTRLICOMP2
  327. .LSTRLICOMP3:
  328. movl saveedi,%edi
  329. movl saveesi,%esi
  330. end;
  331. {$endif FPC_UNIT_HAS_STRLICOMP}
  332. {$ifndef FPC_UNIT_HAS_STRSCAN}
  333. {$define FPC_UNIT_HAS_STRSCAN}
  334. function strscan(p : pchar;c : char) : pchar;assembler;
  335. var
  336. saveesi,saveedi : longint;
  337. asm
  338. movl %edi,saveedi
  339. movl %esi,saveesi
  340. xorl %ecx,%ecx
  341. testl %eax,%eax
  342. jz .LSTRSCAN
  343. // align
  344. movb c,%cl
  345. leal 3(%eax),%esi
  346. andl $-4,%esi
  347. movl %eax,%edi
  348. subl %eax,%esi
  349. jz .LSTRSCANALIGNED
  350. xorl %eax,%eax
  351. .LSTRSCANALIGNLOOP:
  352. movb (%edi),%al
  353. // at .LSTRSCANFOUND, one is substracted from edi to calculate the position,
  354. // so add 1 here already (not after .LSTRSCAN, because then the test/jz and
  355. // cmp/je can't be paired)
  356. incl %edi
  357. testb %al,%al
  358. jz .LSTRSCAN
  359. cmpb %cl,%al
  360. je .LSTRSCANFOUND
  361. decl %esi
  362. jnz .LSTRSCANALIGNLOOP
  363. .LSTRSCANALIGNED:
  364. // fill ecx with cccc
  365. movl %ecx,%eax
  366. shll $8,%eax
  367. orl %eax,%ecx
  368. movl %ecx,%eax
  369. shll $16,%eax
  370. orl %eax,%ecx
  371. .balign 16
  372. .LSTRSCANLOOP:
  373. // load new 4 bytes
  374. movl (%edi),%edx
  375. // in eax, we will check if "c" appear in the loaded dword
  376. movl %edx,%eax
  377. // esi will be used to calculate the mask
  378. movl %edx,%esi
  379. notl %esi
  380. // in edx we will check for the end of the string
  381. addl $0x0fefefeff,%edx
  382. xorl %ecx,%eax
  383. andl $0x080808080,%esi
  384. addl $4,%edi
  385. andl %esi,%edx
  386. movl %eax,%esi
  387. notl %esi
  388. jnz .LSTRSCANLONGCHECK
  389. addl $0x0fefefeff,%eax
  390. andl $0x080808080,%esi
  391. andl %esi,%eax
  392. jz .LSTRSCANLOOP
  393. // the position in %eax where the char was found is now $80, so keep on
  394. // shifting 8 bits out of %eax until we find a non-zero bit.
  395. // first char
  396. shrl $8,%eax
  397. jc .LSTRSCANFOUND1
  398. // second char
  399. shrl $8,%eax
  400. jc .LSTRSCANFOUND2
  401. // third char
  402. shrl $8,%eax
  403. jc .LSTRSCANFOUND3
  404. // fourth char
  405. jmp .LSTRSCANFOUND
  406. .LSTRSCANLONGCHECK:
  407. // there's a null somewhere, but we still have to check whether there isn't
  408. // a 'c' before it.
  409. addl $0x0fefefeff,%eax
  410. andl $0x080808080,%esi
  411. andl %esi,%eax
  412. // Now, in eax we have $80 on the positions where there were c-chars and in
  413. // edx we have $80 on the positions where there were #0's. On all other
  414. // positions, there is now #0
  415. // first char
  416. shrl $8,%eax
  417. jc .LSTRSCANFOUND1
  418. shrl $8,%edx
  419. jc .LSTRSCANNOTFOUND
  420. // second char
  421. shrl $8,%eax
  422. jc .LSTRSCANFOUND2
  423. shrl $8,%edx
  424. jc .LSTRSCANNOTFOUND
  425. // third char
  426. shrl $8,%eax
  427. jc .LSTRSCANFOUND3
  428. shrl $8,%edx
  429. jc .LSTRSCANNOTFOUND
  430. // we know the fourth char is now #0 (since we only jump to the long check if
  431. // there is a #0 char somewhere), but it's possible c = #0, and than we have
  432. // to return the end of the string and not nil!
  433. shrl $8,%eax
  434. jc .LSTRSCANFOUND
  435. jmp .LSTRSCANNOTFOUND
  436. .LSTRSCANFOUND3:
  437. leal -2(%edi),%eax
  438. jmp .LSTRSCAN
  439. .LSTRSCANFOUND2:
  440. leal -3(%edi),%eax
  441. jmp .LSTRSCAN
  442. .LSTRSCANFOUND1:
  443. leal -4(%edi),%eax
  444. jmp .LSTRSCAN
  445. .LSTRSCANFOUND:
  446. leal -1(%edi),%eax
  447. jmp .LSTRSCAN
  448. .LSTRSCANNOTFOUND:
  449. xorl %eax,%eax
  450. .LSTRSCAN:
  451. movl saveedi,%edi
  452. movl saveesi,%esi
  453. end;
  454. {$endif FPC_UNIT_HAS_STRSCAN}
  455. {$ifndef FPC_UNIT_HAS_STRRSCAN}
  456. {$define FPC_UNIT_HAS_STRRSCAN}
  457. function strrscan(p : pchar;c : char) : pchar;assembler;
  458. var
  459. saveeax,
  460. saveedi : longint;
  461. asm
  462. movl %edi,saveedi
  463. movl %eax,saveeax
  464. movl p,%edi
  465. xorl %eax,%eax
  466. orl %edi,%edi
  467. jz .LSTRRSCAN
  468. movl $0xffffffff,%ecx
  469. {$ifdef FPC_ENABLED_CLD}
  470. cld
  471. {$endif FPC_ENABLED_CLD}
  472. xorb %al,%al
  473. repne
  474. scasb
  475. not %ecx
  476. movb c,%al
  477. movl saveeax,%edi
  478. addl %ecx,%edi
  479. decl %edi
  480. std
  481. repne
  482. scasb
  483. cld
  484. movl $0,%eax
  485. jnz .LSTRRSCAN
  486. movl %edi,%eax
  487. incl %eax
  488. .LSTRRSCAN:
  489. movl saveedi,%edi
  490. end;
  491. {$endif FPC_UNIT_HAS_STRRSCAN}
  492. {$ifndef FPC_UNIT_HAS_STRUPPER}
  493. {$define FPC_UNIT_HAS_STRUPPER}
  494. function strupper(p : pchar) : pchar;assembler;
  495. var
  496. saveeax,saveesi,saveedi : longint;
  497. asm
  498. movl %edi,saveedi
  499. movl %esi,saveesi
  500. movl %eax,saveeax
  501. movl p,%esi
  502. orl %esi,%esi
  503. jz .LStrUpperNil
  504. {$ifdef FPC_ENABLED_CLD}
  505. cld
  506. {$endif FPC_ENABLED_CLD}
  507. movl %esi,%edi
  508. .LSTRUPPER1:
  509. lodsb
  510. cmpb $97,%al
  511. jb .LSTRUPPER3
  512. cmpb $122,%al
  513. ja .LSTRUPPER3
  514. subb $0x20,%al
  515. .LSTRUPPER3:
  516. stosb
  517. orb %al,%al
  518. jnz .LSTRUPPER1
  519. .LStrUpperNil:
  520. movl saveeax,%eax
  521. movl saveedi,%edi
  522. movl saveesi,%esi
  523. end;
  524. {$endif FPC_UNIT_HAS_STRUPPER}
  525. {$ifndef FPC_UNIT_HAS_STRLOWER}
  526. {$define FPC_UNIT_HAS_STRLOWER}
  527. function strlower(p : pchar) : pchar;assembler;
  528. var
  529. saveeax,saveesi,saveedi : longint;
  530. asm
  531. movl %esi,saveesi
  532. movl %edi,saveedi
  533. movl %eax,saveeax
  534. movl p,%esi
  535. orl %esi,%esi
  536. jz .LStrLowerNil
  537. {$ifdef FPC_ENABLED_CLD}
  538. cld
  539. {$endif FPC_ENABLED_CLD}
  540. movl %esi,%edi
  541. .LSTRLOWER1:
  542. lodsb
  543. cmpb $65,%al
  544. jb .LSTRLOWER3
  545. cmpb $90,%al
  546. ja .LSTRLOWER3
  547. addb $0x20,%al
  548. .LSTRLOWER3:
  549. stosb
  550. orb %al,%al
  551. jnz .LSTRLOWER1
  552. .LStrLowerNil:
  553. movl saveeax,%eax
  554. movl saveedi,%edi
  555. movl saveesi,%esi
  556. end;
  557. {$endif FPC_UNIT_HAS_STRLOWER}