set.inc 15 KB

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