set.inc 15 KB

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