set.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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. Include file with set operations called by the compiler
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. procedure do_load_small(p : pointer;l:longint);assembler;[public,alias:'FPC_SET_LOAD_SMALL'];
  13. {
  14. load a normal set p from a smallset l
  15. }
  16. asm
  17. movl p,%edi
  18. movl l,%eax
  19. movl %eax,(%edi)
  20. addl $4,%edi
  21. movl $7,%ecx
  22. xorl %eax,%eax
  23. rep
  24. stosl
  25. end;
  26. procedure do_create_element(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_CREATE_ELEMENT'];
  27. {
  28. create a new set in p from an element b
  29. }
  30. asm
  31. pushl %eax
  32. pushl %ecx
  33. movl p,%edi
  34. xorl %eax,%eax
  35. movl $8,%ecx
  36. rep
  37. stosl
  38. movb b,%al
  39. movl p,%edi
  40. movl %eax,%ecx
  41. shrl $3,%eax
  42. andl $7,%ecx
  43. addl %eax,%edi
  44. btsl %ecx,(%edi)
  45. popl %ecx
  46. popl %eax
  47. end;
  48. procedure do_set_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_SET_BYTE'];
  49. {
  50. add the element b to the set pointed by p
  51. }
  52. asm
  53. pushl %eax
  54. movl p,%edi
  55. movb b,%al
  56. andl $0xf8,%eax
  57. shrl $3,%eax
  58. addl %eax,%edi
  59. movb b,%al
  60. andl $7,%eax
  61. btsl %eax,(%edi)
  62. popl %eax
  63. end;
  64. procedure do_unset_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_UNSET_BYTE'];
  65. {
  66. suppresses the element b to the set pointed by p
  67. used for exclude(set,element)
  68. }
  69. asm
  70. pushl %eax
  71. movl p,%edi
  72. movb b,%al
  73. andl $0xf8,%eax
  74. shrl $3,%eax
  75. addl %eax,%edi
  76. movb b,%al
  77. andl $7,%eax
  78. btrl %eax,(%edi)
  79. popl %eax
  80. end;
  81. procedure do_set_range(p : pointer;l,h : byte);assembler;[public,alias:'FPC_SET_SET_RANGE'];
  82. {
  83. adds the range [l..h] to the set pointed to by p
  84. }
  85. asm
  86. pushl %eax
  87. movzbl l,%eax // lowest bit to be set in eax
  88. movzbl h,%ebx // highest in ebx
  89. cmpl %eax,%ebx
  90. jb .Lset_range_done
  91. movl p,%edi // set address in edi
  92. movl %eax,%ecx // lowest also in ecx
  93. shrl $3,%eax // divide by 8 to get starting and ending byte
  94. shrl $3,%ebx // address
  95. andb $31,%cl // low five bits of lo determine start of bit mask
  96. movl $0x0ffffffff,%edx // edx = bitmask to be inserted
  97. andl $0x0fffffffc,%eax // clear two lowest bits to get start/end longint
  98. andl $0x0fffffffc,%ebx // address * 4
  99. shll %cl,%edx // shift bitmask to clear bits below lo
  100. addl %eax,%edi // go to starting pos in set
  101. subl %eax,%ebx // are bit lo and hi in the same longint?
  102. jz .Lset_range_hi // yes, keep current mask and adjust for hi bit
  103. orl %edx,(%edi) // no, store current mask
  104. movl $0x0ffffffff,%edx // new mask
  105. addl $4,%edi // next longint of set
  106. subl $4,%ebx // bit hi in this longint?
  107. jz .Lset_range_hi // yes, keep full mask and adjust for hi bit
  108. .Lset_range_loop:
  109. movl %edx,(%edi) // no, fill longints in between with full mask
  110. addl $4,%edi
  111. subl $4,%ebx
  112. jnz .Lset_range_loop
  113. .Lset_range_hi:
  114. movb h,%cl
  115. movl %edx,%ebx // save current bitmask
  116. andb $31,%cl
  117. subb $31,%cl // cl := (31 - (hi and 31)) = shift count to
  118. negb %cl // adjust bitmask for hi bit
  119. shrl %cl,%edx // shift bitmask to clear bits higher than hi
  120. andl %edx,%ebx // combine both bitmasks
  121. orl %ebx,(%edi) // store to set
  122. .Lset_range_done:
  123. popl %eax
  124. end;
  125. procedure do_in_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_IN_BYTE'];
  126. {
  127. tests if the element b is in the set p the carryflag is set if it present
  128. }
  129. asm
  130. pushl %eax
  131. movl p,%edi
  132. movb b,%al
  133. andl $0xf8,%eax
  134. shrl $3,%eax
  135. addl %eax,%edi
  136. movb b,%al
  137. andl $7,%eax
  138. btl %eax,(%edi)
  139. popl %eax
  140. end;
  141. procedure do_add_sets(set1,set2,dest : pointer);assembler;[public,alias:'FPC_SET_ADD_SETS'];
  142. {
  143. adds set1 and set2 into set dest
  144. }
  145. asm
  146. movl set1,%esi
  147. movl set2,%ebx
  148. movl dest,%edi
  149. movl $8,%ecx
  150. .LMADDSETS1:
  151. lodsl
  152. orl (%ebx),%eax
  153. stosl
  154. addl $4,%ebx
  155. decl %ecx
  156. jnz .LMADDSETS1
  157. end;
  158. procedure do_mul_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_MUL_SETS'];
  159. {
  160. multiplies (takes common elements of) set1 and set2 result put in dest
  161. }
  162. asm
  163. movl set1,%esi
  164. movl set2,%ebx
  165. movl dest,%edi
  166. movl $8,%ecx
  167. .LMMULSETS1:
  168. lodsl
  169. andl (%ebx),%eax
  170. stosl
  171. addl $4,%ebx
  172. decl %ecx
  173. jnz .LMMULSETS1
  174. end;
  175. procedure do_sub_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SUB_SETS'];
  176. {
  177. computes the diff from set1 to set2 result in dest
  178. }
  179. asm
  180. movl set1,%esi
  181. movl set2,%ebx
  182. movl dest,%edi
  183. movl $8,%ecx
  184. .LMSUBSETS1:
  185. lodsl
  186. movl (%ebx),%edx
  187. notl %edx
  188. andl %edx,%eax
  189. stosl
  190. addl $4,%ebx
  191. decl %ecx
  192. jnz .LMSUBSETS1
  193. end;
  194. procedure do_symdif_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SYMDIF_SETS'];
  195. {
  196. computes the symetric diff from set1 to set2 result in dest
  197. }
  198. asm
  199. movl set1,%esi
  200. movl set2,%ebx
  201. movl dest,%edi
  202. movl $8,%ecx
  203. .LMSYMDIFSETS1:
  204. lodsl
  205. movl (%ebx),%edx
  206. xorl %edx,%eax
  207. stosl
  208. addl $4,%ebx
  209. decl %ecx
  210. jnz .LMSYMDIFSETS1
  211. end;
  212. procedure do_comp_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_COMP_SETS'];
  213. {
  214. compares set1 and set2 zeroflag is set if they are equal
  215. }
  216. asm
  217. movl set1,%esi
  218. movl set2,%edi
  219. movl $8,%ecx
  220. .LMCOMPSETS1:
  221. movl (%esi),%eax
  222. movl (%edi),%edx
  223. cmpl %edx,%eax
  224. jne .LMCOMPSETEND
  225. addl $4,%esi
  226. addl $4,%edi
  227. decl %ecx
  228. jnz .LMCOMPSETS1
  229. { we are here only if the two sets are equal
  230. we have zero flag set, and that what is expected }
  231. .LMCOMPSETEND:
  232. end;
  233. {$IfNDef NoSetInclusion}
  234. procedure do_contains_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  235. {
  236. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  237. }
  238. asm
  239. movl set1,%esi
  240. movl set2,%edi
  241. movl $8,%ecx
  242. .LMCONTAINSSETS1:
  243. movl (%esi),%eax
  244. movl (%edi),%edx
  245. andl %eax,%edx
  246. cmpl %edx,%eax {set1 and set2 = set1?}
  247. jne .LMCONTAINSSETEND
  248. addl $4,%esi
  249. addl $4,%edi
  250. decl %ecx
  251. jnz .LMCONTAINSSETS1
  252. { we are here only if set2 contains set1
  253. we have zero flag set, and that what is expected }
  254. .LMCONTAINSSETEND:
  255. end;
  256. {$EndIf SetInclusion}
  257. {$ifdef LARGESETS}
  258. procedure do_set(p : pointer;b : word);assembler;[public,alias:'FPC_SET_SET_WORD'];
  259. {
  260. sets the element b in set p works for sets larger than 256 elements
  261. not yet use by the compiler so
  262. }
  263. asm
  264. pushl %eax
  265. movl p,%edi
  266. movw b,%ax
  267. andl $0xfff8,%eax
  268. shrl $3,%eax
  269. addl %eax,%edi
  270. movb 12(%ebp),%al
  271. andl $7,%eax
  272. btsl %eax,(%edi)
  273. popl %eax
  274. end;
  275. procedure do_in(p : pointer;b : word);assembler;[public,alias:'FPC_SET_IN_WORD'];
  276. {
  277. tests if the element b is in the set p the carryflag is set if it present
  278. works for sets larger than 256 elements
  279. }
  280. asm
  281. pushl %eax
  282. movl p,%edi
  283. movw b,%ax
  284. andl $0xfff8,%eax
  285. shrl $3,%eax
  286. addl %eax,%edi
  287. movb 12(%ebp),%al
  288. andl $7,%eax
  289. btl %eax,(%edi)
  290. popl %eax
  291. end;
  292. procedure add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_ADD_SETS_SIZE'];
  293. {
  294. adds set1 and set2 into set dest size is the number of bytes in the set
  295. }
  296. asm
  297. movl set1,%esi
  298. movl set2,%ebx
  299. movl dest,%edi
  300. movl size,%ecx
  301. .LMADDSETSIZES1:
  302. lodsl
  303. orl (%ebx),%eax
  304. stosl
  305. addl $4,%ebx
  306. decl %ecx
  307. jnz .LMADDSETSIZES1
  308. end;
  309. procedure mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_MUL_SETS_SIZE'];
  310. {
  311. multiplies (i.E. takes common elements of) set1 and set2 result put in
  312. dest size is the number of bytes in the set
  313. }
  314. asm
  315. movl set1,%esi
  316. movl set2,%ebx
  317. movl dest,%edi
  318. movl size,%ecx
  319. .LMMULSETSIZES1:
  320. lodsl
  321. andl (%ebx),%eax
  322. stosl
  323. addl $4,%ebx
  324. decl %ecx
  325. jnz .LMMULSETSIZES1
  326. end;
  327. procedure sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SUB_SETS_SIZE'];
  328. asm
  329. movl set1,%esi
  330. movl set2,%ebx
  331. movl dest,%edi
  332. movl size,%ecx
  333. .LMSUBSETSIZES1:
  334. lodsl
  335. movl (%ebx),%edx
  336. notl %edx
  337. andl %edx,%eax
  338. stosl
  339. addl $4,%ebx
  340. decl %ecx
  341. jnz .LMSUBSETSIZES1
  342. end;
  343. procedure sym_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SYMDIF_SETS_SIZE'];
  344. {
  345. computes the symetric diff from set1 to set2 result in dest
  346. }
  347. asm
  348. movl set1,%esi
  349. movl set2,%ebx
  350. movl dest,%edi
  351. movl size,%ecx
  352. .LMSYMDIFSETSIZE1:
  353. lodsl
  354. movl (%ebx),%edx
  355. xorl %edx,%eax
  356. stosl
  357. addl $4,%ebx
  358. decl %ecx
  359. jnz .LMSYMDIFSETSIZE1
  360. end;
  361. procedure comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_SET_COMP_SETS_SIZE'];
  362. asm
  363. movl set1,%esi
  364. movl set2,%edi
  365. movl size,%ecx
  366. .LMCOMPSETSIZES1:
  367. lodsl
  368. movl (%edi),%edx
  369. cmpl %edx,%eax
  370. jne .LMCOMPSETSIZEEND
  371. addl $4,%edi
  372. decl %ecx
  373. jnz .LMCOMPSETSIZES1
  374. { we are here only if the two sets are equal
  375. we have zero flag set, and that what is expected }
  376. .LMCOMPSETSIZEEND:
  377. end;
  378. {$IfNDef NoSetInclusion}
  379. procedure contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  380. {
  381. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  382. }
  383. asm
  384. movl set1,%esi
  385. movl set2,%edi
  386. movl size,%ecx
  387. .LMCONTAINSSETS2:
  388. movl (%esi),%eax
  389. movl (%edi),%edx
  390. andl %eax,%edx
  391. cmpl %edx,%eax {set1 and set2 = set1?}
  392. jne .LMCONTAINSSETEND2
  393. addl $4,%esi
  394. addl $4,%edi
  395. decl %ecx
  396. jnz .LMCONTAINSSETS2
  397. { we are here only if set2 contains set1
  398. we have zero flag set, and that what is expected }
  399. .LMCONTAINSSETEND2:
  400. end;
  401. {$EndIf NoSetInclusion}
  402. {$endif LARGESET}
  403. {
  404. $Log$
  405. Revision 1.3 2000-09-21 16:09:19 jonas
  406. + new, much faster do_set_range based on the PowerPC version (which
  407. will be committed tomorrow)
  408. Revision 1.2 2000/07/13 11:33:41 michael
  409. + removed logs
  410. }