strings.inc 14 KB

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