strings.inc 14 KB

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