set.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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. Include file with set operations called by the compiler
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { the following code is exactly big endian set-related, but specific to the old
  12. scheme whereby sets were either 4 or 32 bytes. I've left the routines here
  13. so if someone wants to, they can create equivalents of the new varset helpers
  14. from rtl/inc/genset.inc
  15. }
  16. {$ifdef FPC_OLD_BIGENDIAN_SETS}
  17. {$define FPC_SYSTEM_HAS_FPC_SET_LOAD_SMALL}
  18. function fpc_set_load_small(l: fpc_small_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_LOAD_SMALL']; compilerproc;
  19. {
  20. load a normal set p from a smallset l
  21. }
  22. var
  23. saveedi : longint;
  24. asm
  25. movl %edi,saveedi
  26. movl __RESULT,%edi
  27. movl l,%eax
  28. {$ifdef FPC_ENABLED_CLD}
  29. cld
  30. {$endif FPC_ENABLED_CLD}
  31. stosl
  32. xorl %eax,%eax
  33. movl $7,%ecx
  34. rep
  35. stosl
  36. movl saveedi,%edi
  37. end;
  38. {$define FPC_SYSTEM_HAS_FPC_SET_CREATE_ELEMENT}
  39. function fpc_set_create_element(b : byte): fpc_normal_set;assembler;[public,alias:'FPC_SET_CREATE_ELEMENT']; compilerproc;
  40. {
  41. create a new set in p from an element b
  42. }
  43. var
  44. saveedi : longint;
  45. asm
  46. movl %edi,saveedi
  47. movl __RESULT,%edi
  48. movzbl b,%edx
  49. xorl %eax,%eax
  50. movl $8,%ecx
  51. {$ifdef FPC_ENABLED_CLD}
  52. cld
  53. {$endif FPC_ENABLED_CLD}
  54. rep
  55. stosl
  56. leal -32(%edi),%eax
  57. btsl %edx,(%eax)
  58. movl saveedi,%edi
  59. end;
  60. {$define FPC_SYSTEM_HAS_FPC_SET_SET_BYTE}
  61. function fpc_set_set_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  62. {
  63. add the element b to the set pointed by source
  64. }
  65. var
  66. saveesi,saveedi : longint;
  67. asm
  68. movl %edi,saveedi
  69. movl %esi,saveesi
  70. movl source,%esi
  71. movl __RESULT,%edi
  72. movzbl b,%edx
  73. movl $8,%ecx
  74. {$ifdef FPC_ENABLED_CLD}
  75. cld
  76. {$endif FPC_ENABLED_CLD}
  77. rep
  78. movsl
  79. leal -32(%edi),%eax
  80. btsl %edx,(%eax)
  81. movl saveedi,%edi
  82. movl saveesi,%esi
  83. end;
  84. {$define FPC_SYSTEM_HAS_FPC_SET_UNSET_BYTE}
  85. function fpc_set_unset_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  86. {
  87. add the element b to the set pointed by source
  88. }
  89. var
  90. saveesi,saveedi : longint;
  91. asm
  92. movl %edi,saveedi
  93. movl %esi,saveesi
  94. movl source,%esi
  95. movl __RESULT,%edi
  96. movzbl b,%edx
  97. movl $8,%ecx
  98. {$ifdef FPC_ENABLED_CLD}
  99. cld
  100. {$endif FPC_ENABLED_CLD}
  101. rep
  102. movsl
  103. leal -32(%edi),%eax
  104. btrl %edx,(%eax)
  105. movl saveedi,%edi
  106. movl saveesi,%esi
  107. end;
  108. {$define FPC_SYSTEM_HAS_FPC_SET_SET_RANGE}
  109. function fpc_set_set_range(const orgset: fpc_normal_set; l,h : byte): fpc_normal_set;assembler; compilerproc;
  110. {
  111. adds the range [l..h] to the set pointed to by p
  112. }
  113. var
  114. saveh : byte;
  115. saveesi,saveedi,saveebx : longint;
  116. asm
  117. movl %edi,saveedi
  118. movl %esi,saveesi
  119. movl %ebx,saveebx
  120. movl __RESULT,%edi // target set address in edi
  121. movl orgset, %esi // source set address in esi
  122. movzbl l,%eax // lowest bit to be set in eax
  123. movzbl h,%ebx // highest in ebx
  124. movb %bl,saveh
  125. movl $8,%ecx // we have to copy 32 bytes
  126. cmpl %eax,%ebx // high < low?
  127. {$ifdef FPC_ENABLED_CLD}
  128. cld
  129. {$endif FPC_ENABLED_CLD}
  130. rep // copy source to dest (it's possible to do the range
  131. movsl // setting and copying simultanuously of course, but
  132. // that would result in many more jumps and code)
  133. movl %eax,%ecx // lowest also in ecx
  134. jb .Lset_range_done // if high > low, then dest := source
  135. shrl $3,%eax // divide by 8 to get starting and ending byte
  136. shrl $3,%ebx // address
  137. andb $31,%cl // low five bits of lo determine start of bit mask
  138. andl $0x0fffffffc,%eax // clear two lowest bits to get start/end longint
  139. subl $32,%edi // get back to start of dest
  140. andl $0x0fffffffc,%ebx // address * 4
  141. movl $0x0ffffffff,%edx // edx = bitmask to be inserted
  142. shll %cl,%edx // shift bitmask to clear bits below lo
  143. addl %eax,%edi // go to starting pos in set
  144. subl %eax,%ebx // are bit lo and hi in the same longint?
  145. jz .Lset_range_hi // yes, keep current mask and adjust for hi bit
  146. orl %edx,(%edi) // no, store current mask
  147. movl $0x0ffffffff,%edx // new mask
  148. addl $4,%edi // next longint of set
  149. subl $4,%ebx // bit hi in this longint?
  150. jz .Lset_range_hi // yes, keep full mask and adjust for hi bit
  151. .Lset_range_loop:
  152. movl %edx,(%edi) // no, fill longints in between with full mask
  153. addl $4,%edi
  154. subl $4,%ebx
  155. jnz .Lset_range_loop
  156. .Lset_range_hi:
  157. movb saveh,%cl // this is ok, h is on the stack
  158. movl %edx,%ebx // save current bitmask
  159. andb $31,%cl
  160. subb $31,%cl // cl := (31 - (hi and 31)) = shift count to
  161. negb %cl // adjust bitmask for hi bit
  162. shrl %cl,%edx // shift bitmask to clear bits higher than hi
  163. andl %edx,%ebx // combine both bitmasks
  164. orl %ebx,(%edi) // store to set
  165. .Lset_range_done:
  166. movl saveedi,%edi
  167. movl saveesi,%esi
  168. movl saveebx,%ebx
  169. end;
  170. {$define FPC_SYSTEM_HAS_FPC_SET_IN_BYTE}
  171. function fpc_set_in_byte(const p: fpc_normal_set; b: byte): boolean; assembler; [public,alias:'FPC_SET_IN_BYTE']; compilerproc;
  172. {
  173. tests if the element b is in the set p the carryflag is set if it present
  174. }
  175. asm
  176. {$ifdef REGCALL}
  177. xchgl %edx,%eax
  178. andl $0xff,%eax
  179. {$else}
  180. movl p,%edx
  181. movzbl b,%eax
  182. {$endif}
  183. btl %eax,(%edx)
  184. end;
  185. {$define FPC_SYSTEM_HAS_FPC_SET_ADD_SETS}
  186. function fpc_set_add_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_ADD_SETS']; compilerproc;
  187. {
  188. adds set1 and set2 into set dest
  189. }
  190. var
  191. saveesi,saveedi : longint;
  192. asm
  193. movl %edi,saveedi
  194. movl %esi,saveesi
  195. {$ifdef REGCALL}
  196. movl set1,%esi
  197. movl __RESULT,%edi
  198. movl set2,%edx
  199. {$else}
  200. movl set1,%esi
  201. movl set2,%edx
  202. movl __RESULT,%edi
  203. {$endif}
  204. {$ifdef FPC_ENABLED_CLD}
  205. cld
  206. {$endif FPC_ENABLED_CLD}
  207. movl $8,%ecx
  208. .LMADDSETS1:
  209. lodsl
  210. orl (%edx),%eax
  211. stosl
  212. addl $4,%edx
  213. decl %ecx
  214. jnz .LMADDSETS1
  215. movl saveedi,%edi
  216. movl saveesi,%esi
  217. end;
  218. {$define FPC_SYSTEM_HAS_FPC_SET_MUL_SETS}
  219. function fpc_set_mul_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_MUL_SETS']; compilerproc;
  220. {
  221. multiplies (takes common elements of) set1 and set2 result put in dest
  222. }
  223. var
  224. saveesi,saveedi : longint;
  225. asm
  226. movl %edi,saveedi
  227. movl %esi,saveesi
  228. {$ifdef REGCALL}
  229. movl set1,%esi
  230. movl __RESULT,%edi
  231. movl set2,%edx
  232. {$else}
  233. movl set1,%esi
  234. movl set2,%edx
  235. movl __RESULT,%edi
  236. {$endif}
  237. {$ifdef FPC_ENABLED_CLD}
  238. cld
  239. {$endif FPC_ENABLED_CLD}
  240. movl $8,%ecx
  241. .LMMULSETS1:
  242. lodsl
  243. andl (%edx),%eax
  244. stosl
  245. addl $4,%edx
  246. decl %ecx
  247. jnz .LMMULSETS1
  248. movl saveedi,%edi
  249. movl saveesi,%esi
  250. end;
  251. {$define FPC_SYSTEM_HAS_FPC_SET_SUB_SETS}
  252. function fpc_set_sub_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SUB_SETS']; compilerproc;
  253. {
  254. computes the diff from set1 to set2 result in dest
  255. }
  256. var
  257. saveesi,saveedi,saveebx : longint;
  258. asm
  259. movl %edi,saveedi
  260. movl %esi,saveesi
  261. movl %ebx,saveebx
  262. {$ifdef REGCALL}
  263. movl set1,%esi
  264. movl __RESULT,%edi
  265. movl set2,%ebx
  266. {$else}
  267. movl set1,%esi
  268. movl set2,%ebx
  269. movl __RESULT,%edi
  270. {$endif}
  271. {$ifdef FPC_ENABLED_CLD}
  272. cld
  273. {$endif FPC_ENABLED_CLD}
  274. movl $8,%ecx
  275. .LMSUBSETS1:
  276. lodsl
  277. movl (%ebx),%edx
  278. notl %edx
  279. andl %edx,%eax
  280. stosl
  281. addl $4,%ebx
  282. decl %ecx
  283. jnz .LMSUBSETS1
  284. movl saveedi,%edi
  285. movl saveesi,%esi
  286. movl saveebx,%ebx
  287. end;
  288. {$define FPC_SYSTEM_HAS_FPC_SET_SYMDIF_SETS}
  289. function fpc_set_symdif_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SYMDIF_SETS']; compilerproc;
  290. {
  291. computes the symetric diff from set1 to set2 result in dest
  292. }
  293. var
  294. saveesi,saveedi : longint;
  295. asm
  296. movl %edi,saveedi
  297. movl %esi,saveesi
  298. {$ifdef REGCALL}
  299. movl set1,%esi
  300. movl __RESULT,%edi
  301. movl set2,%edx
  302. {$else}
  303. movl set1,%esi
  304. movl set2,%edx
  305. movl __RESULT,%edi
  306. {$endif}
  307. {$ifdef FPC_ENABLED_CLD}
  308. cld
  309. {$endif FPC_ENABLED_CLD}
  310. movl $8,%ecx
  311. .LMSYMDIFSETS1:
  312. lodsl
  313. xorl (%edx),%eax
  314. stosl
  315. addl $4,%edx
  316. decl %ecx
  317. jnz .LMSYMDIFSETS1
  318. movl saveedi,%edi
  319. movl saveesi,%esi
  320. end;
  321. {$define FPC_SYSTEM_HAS_FPC_SET_COMP_SETS}
  322. function fpc_set_comp_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_COMP_SETS']; compilerproc;
  323. {
  324. compares set1 and set2 zeroflag is set if they are equal
  325. }
  326. var
  327. saveesi,saveedi : longint;
  328. asm
  329. movl %edi,saveedi
  330. movl %esi,saveesi
  331. movl set1,%esi
  332. movl set2,%edi
  333. movl $8,%ecx
  334. .LMCOMPSETS1:
  335. movl (%esi),%eax
  336. movl (%edi),%edx
  337. cmpl %edx,%eax
  338. jne .LMCOMPSETEND
  339. addl $4,%esi
  340. addl $4,%edi
  341. decl %ecx
  342. jnz .LMCOMPSETS1
  343. { we are here only if the two sets are equal
  344. we have zero flag set, and that what is expected }
  345. .LMCOMPSETEND:
  346. seteb %al
  347. movl saveedi,%edi
  348. movl saveesi,%esi
  349. end;
  350. {$define FPC_SYSTEM_HAS_FPC_SET_CONTAINS_SET}
  351. function fpc_set_contains_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_CONTAINS_SETS']; compilerproc;
  352. {
  353. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  354. }
  355. var
  356. saveesi,saveedi : longint;
  357. asm
  358. movl %edi,saveedi
  359. movl %esi,saveesi
  360. movl set1,%esi
  361. movl set2,%edi
  362. movl $8,%ecx
  363. .LMCONTAINSSETS1:
  364. movl (%esi),%eax
  365. movl (%edi),%edx
  366. andl %eax,%edx
  367. cmpl %edx,%eax {set1 and set2 = set1?}
  368. jne .LMCONTAINSSETEND
  369. addl $4,%esi
  370. addl $4,%edi
  371. decl %ecx
  372. jnz .LMCONTAINSSETS1
  373. { we are here only if set2 contains set1
  374. we have zero flag set, and that what is expected }
  375. .LMCONTAINSSETEND:
  376. seteb %al
  377. movl saveedi,%edi
  378. movl saveesi,%esi
  379. end;
  380. {$ifdef LARGESETS}
  381. {$error Needs to be fixed for register calling first!}
  382. procedure fpc_largeset_set_word(p : pointer;b : word);assembler;[public,alias:'FPC_LARGESET_SET_WORD']; compilerproc;
  383. {
  384. sets the element b in set p works for sets larger than 256 elements
  385. not yet use by the compiler so
  386. }
  387. asm
  388. pushl %eax
  389. movl p,%edi
  390. movw b,%ax
  391. andl $0xfff8,%eax
  392. shrl $3,%eax
  393. addl %eax,%edi
  394. movb 12(%ebp),%al
  395. andl $7,%eax
  396. btsl %eax,(%edi)
  397. popl %eax
  398. end;
  399. procedure fpc_largeset_in_word(p : pointer;b : word);assembler;[public,alias:'FPC_LARGESET_IN_WORD']; compilerproc;
  400. {
  401. tests if the element b is in the set p the carryflag is set if it present
  402. works for sets larger than 256 elements
  403. }
  404. asm
  405. pushl %eax
  406. movl p,%edi
  407. movw b,%ax
  408. andl $0xfff8,%eax
  409. shrl $3,%eax
  410. addl %eax,%edi
  411. movb 12(%ebp),%al
  412. andl $7,%eax
  413. btl %eax,(%edi)
  414. popl %eax
  415. end;
  416. procedure fpc_largeset_add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_ADD_SETS']; compilerproc;
  417. {
  418. adds set1 and set2 into set dest size is the number of bytes in the set
  419. }
  420. asm
  421. movl set1,%esi
  422. movl set2,%ebx
  423. movl dest,%edi
  424. movl size,%ecx
  425. {$ifdef FPC_ENABLED_CLD}
  426. cld
  427. {$endif FPC_ENABLED_CLD}
  428. .LMADDSETSIZES1:
  429. lodsl
  430. orl (%ebx),%eax
  431. stosl
  432. addl $4,%ebx
  433. decl %ecx
  434. jnz .LMADDSETSIZES1
  435. end;
  436. procedure fpc_largeset_mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_MUL_SETS']; compilerproc;
  437. {
  438. multiplies (i.E. takes common elements of) set1 and set2 result put in
  439. dest size is the number of bytes in the set
  440. }
  441. asm
  442. movl set1,%esi
  443. movl set2,%ebx
  444. movl dest,%edi
  445. movl size,%ecx
  446. {$ifdef FPC_ENABLED_CLD}
  447. cld
  448. {$endif FPC_ENABLED_CLD}
  449. .LMMULSETSIZES1:
  450. lodsl
  451. andl (%ebx),%eax
  452. stosl
  453. addl $4,%ebx
  454. decl %ecx
  455. jnz .LMMULSETSIZES1
  456. end;
  457. procedure fpc_largeset_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_SUB_SETS']; compilerproc;
  458. asm
  459. movl set1,%esi
  460. movl set2,%ebx
  461. movl dest,%edi
  462. movl size,%ecx
  463. {$ifdef FPC_ENABLED_CLD}
  464. cld
  465. {$endif FPC_ENABLED_CLD}
  466. .LMSUBSETSIZES1:
  467. lodsl
  468. movl (%ebx),%edx
  469. notl %edx
  470. andl %edx,%eax
  471. stosl
  472. addl $4,%ebx
  473. decl %ecx
  474. jnz .LMSUBSETSIZES1
  475. end;
  476. procedure fpc_largeset_symdif_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_SYMDIF_SETS']; compilerproc;
  477. {
  478. computes the symetric diff from set1 to set2 result in dest
  479. }
  480. asm
  481. movl set1,%esi
  482. movl set2,%ebx
  483. movl dest,%edi
  484. movl size,%ecx
  485. {$ifdef FPC_ENABLED_CLD}
  486. cld
  487. {$endif FPC_ENABLED_CLD}
  488. .LMSYMDIFSETSIZE1:
  489. lodsl
  490. movl (%ebx),%edx
  491. xorl %edx,%eax
  492. stosl
  493. addl $4,%ebx
  494. decl %ecx
  495. jnz .LMSYMDIFSETSIZE1
  496. end;
  497. procedure fpc_largeset_comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_COMP_SETS']; compilerproc;
  498. asm
  499. movl set1,%esi
  500. movl set2,%edi
  501. movl size,%ecx
  502. {$ifdef FPC_ENABLED_CLD}
  503. cld
  504. {$endif FPC_ENABLED_CLD}
  505. .LMCOMPSETSIZES1:
  506. lodsl
  507. movl (%edi),%edx
  508. cmpl %edx,%eax
  509. jne .LMCOMPSETSIZEEND
  510. addl $4,%edi
  511. decl %ecx
  512. jnz .LMCOMPSETSIZES1
  513. { we are here only if the two sets are equal
  514. we have zero flag set, and that what is expected }
  515. .LMCOMPSETSIZEEND:
  516. end;
  517. procedure fpc_largeset_contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_LARGESET_CONTAINS_SETS']; compilerproc;
  518. {
  519. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  520. }
  521. asm
  522. movl set1,%esi
  523. movl set2,%edi
  524. movl size,%ecx
  525. .LMCONTAINSSETS2:
  526. movl (%esi),%eax
  527. movl (%edi),%edx
  528. andl %eax,%edx
  529. cmpl %edx,%eax {set1 and set2 = set1?}
  530. jne .LMCONTAINSSETEND2
  531. addl $4,%esi
  532. addl $4,%edi
  533. decl %ecx
  534. jnz .LMCONTAINSSETS2
  535. { we are here only if set2 contains set1
  536. we have zero flag set, and that what is expected }
  537. .LMCONTAINSSETEND2:
  538. end;
  539. {$endif LARGESET}
  540. {$endif FPC_OLD_BIGENDIAN_SETS}