set.inc 15 KB

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