set.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. {$define FPC_SYSTEM_HAS_FPC_SET_LOAD_SMALL}
  13. procedure fpc_set_load_small(p : pointer;l:longint);assembler;[public,alias:'FPC_SET_LOAD_SMALL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  14. {
  15. load a normal set p from a smallset l
  16. }
  17. asm
  18. movl p,%edi
  19. movl l,%eax
  20. movl %eax,(%edi)
  21. addl $4,%edi
  22. movl $7,%ecx
  23. xorl %eax,%eax
  24. rep
  25. stosl
  26. end;
  27. {$define FPC_SYSTEM_HAS_FPC_SET_CREATE_ELEMENT}
  28. procedure fpc_set_create_element(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_CREATE_ELEMENT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  29. {
  30. create a new set in p from an element b
  31. }
  32. asm
  33. pushl %eax
  34. pushl %ecx
  35. movl p,%edi
  36. xorl %eax,%eax
  37. movl $8,%ecx
  38. rep
  39. stosl
  40. movb b,%al
  41. movl p,%edi
  42. movl %eax,%ecx
  43. shrl $3,%eax
  44. andl $7,%ecx
  45. addl %eax,%edi
  46. btsl %ecx,(%edi)
  47. popl %ecx
  48. popl %eax
  49. end;
  50. {$define FPC_SYSTEM_HAS_FPC_SET_SET_BYTE}
  51. procedure fpc_set_set_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_SET_BYTE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  52. {
  53. add the element b to the set pointed by p
  54. }
  55. asm
  56. pushl %eax
  57. movl p,%edi
  58. movb b,%al
  59. andl $0xf8,%eax
  60. shrl $3,%eax
  61. addl %eax,%edi
  62. movb b,%al
  63. andl $7,%eax
  64. btsl %eax,(%edi)
  65. popl %eax
  66. end;
  67. {$define FPC_SYSTEM_HAS_FPC_SET_UNSET_BYTE}
  68. procedure fpc_set_unset_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_UNSET_BYTE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  69. {
  70. suppresses the element b to the set pointed by p
  71. used for exclude(set,element)
  72. }
  73. asm
  74. pushl %eax
  75. movl p,%edi
  76. movb b,%al
  77. andl $0xf8,%eax
  78. shrl $3,%eax
  79. addl %eax,%edi
  80. movb b,%al
  81. andl $7,%eax
  82. btrl %eax,(%edi)
  83. popl %eax
  84. end;
  85. {$define FPC_SYSTEM_HAS_FPC_SET_SET_RANGE}
  86. procedure fpc_set_set_range(p : pointer;l,h : byte);assembler;[public,alias:'FPC_SET_SET_RANGE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  87. {
  88. adds the range [l..h] to the set pointed to by p
  89. }
  90. asm
  91. pushl %eax
  92. movzbl l,%eax // lowest bit to be set in eax
  93. movzbl h,%ebx // highest in ebx
  94. cmpl %eax,%ebx
  95. jb .Lset_range_done
  96. movl p,%edi // set address in edi
  97. movl %eax,%ecx // lowest also in ecx
  98. shrl $3,%eax // divide by 8 to get starting and ending byte
  99. shrl $3,%ebx // address
  100. andb $31,%cl // low five bits of lo determine start of bit mask
  101. movl $0x0ffffffff,%edx // edx = bitmask to be inserted
  102. andl $0x0fffffffc,%eax // clear two lowest bits to get start/end longint
  103. andl $0x0fffffffc,%ebx // address * 4
  104. shll %cl,%edx // shift bitmask to clear bits below lo
  105. addl %eax,%edi // go to starting pos in set
  106. subl %eax,%ebx // are bit lo and hi in the same longint?
  107. jz .Lset_range_hi // yes, keep current mask and adjust for hi bit
  108. orl %edx,(%edi) // no, store current mask
  109. movl $0x0ffffffff,%edx // new mask
  110. addl $4,%edi // next longint of set
  111. subl $4,%ebx // bit hi in this longint?
  112. jz .Lset_range_hi // yes, keep full mask and adjust for hi bit
  113. .Lset_range_loop:
  114. movl %edx,(%edi) // no, fill longints in between with full mask
  115. addl $4,%edi
  116. subl $4,%ebx
  117. jnz .Lset_range_loop
  118. .Lset_range_hi:
  119. movb h,%cl
  120. movl %edx,%ebx // save current bitmask
  121. andb $31,%cl
  122. subb $31,%cl // cl := (31 - (hi and 31)) = shift count to
  123. negb %cl // adjust bitmask for hi bit
  124. shrl %cl,%edx // shift bitmask to clear bits higher than hi
  125. andl %edx,%ebx // combine both bitmasks
  126. orl %ebx,(%edi) // store to set
  127. .Lset_range_done:
  128. popl %eax
  129. end;
  130. {$define FPC_SYSTEM_HAS_FPC_SET_IN_BYTE}
  131. procedure fpc_set_in_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_IN_BYTE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  132. {
  133. tests if the element b is in the set p the carryflag is set if it present
  134. }
  135. asm
  136. pushl %eax
  137. movl p,%edi
  138. movb b,%al
  139. andl $0xf8,%eax
  140. shrl $3,%eax
  141. addl %eax,%edi
  142. movb b,%al
  143. andl $7,%eax
  144. btl %eax,(%edi)
  145. popl %eax
  146. end;
  147. {$define FPC_SYSTEM_HAS_FPC_SET_ADD_SETS}
  148. procedure fpc_set_add_sets(set1,set2,dest : pointer);assembler;[public,alias:'FPC_SET_ADD_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  149. {
  150. adds set1 and set2 into set dest
  151. }
  152. asm
  153. movl set1,%esi
  154. movl set2,%ebx
  155. movl dest,%edi
  156. movl $8,%ecx
  157. .LMADDSETS1:
  158. lodsl
  159. orl (%ebx),%eax
  160. stosl
  161. addl $4,%ebx
  162. decl %ecx
  163. jnz .LMADDSETS1
  164. end;
  165. {$define FPC_SYSTEM_HAS_FPC_SET_MUL_SETS}
  166. procedure fpc_set_mul_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_MUL_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  167. {
  168. multiplies (takes common elements of) set1 and set2 result put in dest
  169. }
  170. asm
  171. movl set1,%esi
  172. movl set2,%ebx
  173. movl dest,%edi
  174. movl $8,%ecx
  175. .LMMULSETS1:
  176. lodsl
  177. andl (%ebx),%eax
  178. stosl
  179. addl $4,%ebx
  180. decl %ecx
  181. jnz .LMMULSETS1
  182. end;
  183. {$define FPC_SYSTEM_HAS_FPC_SET_SUB_SETS}
  184. procedure fpc_set_sub_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SUB_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  185. {
  186. computes the diff from set1 to set2 result in dest
  187. }
  188. asm
  189. movl set1,%esi
  190. movl set2,%ebx
  191. movl dest,%edi
  192. movl $8,%ecx
  193. .LMSUBSETS1:
  194. lodsl
  195. movl (%ebx),%edx
  196. notl %edx
  197. andl %edx,%eax
  198. stosl
  199. addl $4,%ebx
  200. decl %ecx
  201. jnz .LMSUBSETS1
  202. end;
  203. {$define FPC_SYSTEM_HAS_FPC_SET_SYMDIF_SETS}
  204. procedure fpc_set_symdif_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SYMDIF_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  205. {
  206. computes the symetric diff from set1 to set2 result in dest
  207. }
  208. asm
  209. movl set1,%esi
  210. movl set2,%ebx
  211. movl dest,%edi
  212. movl $8,%ecx
  213. .LMSYMDIFSETS1:
  214. lodsl
  215. movl (%ebx),%edx
  216. xorl %edx,%eax
  217. stosl
  218. addl $4,%ebx
  219. decl %ecx
  220. jnz .LMSYMDIFSETS1
  221. end;
  222. {$define FPC_SYSTEM_HAS_FPC_SET_COMP_SETS}
  223. procedure fpc_set_comp_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_COMP_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  224. {
  225. compares set1 and set2 zeroflag is set if they are equal
  226. }
  227. asm
  228. movl set1,%esi
  229. movl set2,%edi
  230. movl $8,%ecx
  231. .LMCOMPSETS1:
  232. movl (%esi),%eax
  233. movl (%edi),%edx
  234. cmpl %edx,%eax
  235. jne .LMCOMPSETEND
  236. addl $4,%esi
  237. addl $4,%edi
  238. decl %ecx
  239. jnz .LMCOMPSETS1
  240. { we are here only if the two sets are equal
  241. we have zero flag set, and that what is expected }
  242. .LMCOMPSETEND:
  243. end;
  244. {$define FPC_SYSTEM_HAS_FPC_SET_CONTAINS_SET}
  245. procedure fpc_set_contains_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_CONTAINS_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  246. {
  247. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  248. }
  249. asm
  250. movl set1,%esi
  251. movl set2,%edi
  252. movl $8,%ecx
  253. .LMCONTAINSSETS1:
  254. movl (%esi),%eax
  255. movl (%edi),%edx
  256. andl %eax,%edx
  257. cmpl %edx,%eax {set1 and set2 = set1?}
  258. jne .LMCONTAINSSETEND
  259. addl $4,%esi
  260. addl $4,%edi
  261. decl %ecx
  262. jnz .LMCONTAINSSETS1
  263. { we are here only if set2 contains set1
  264. we have zero flag set, and that what is expected }
  265. .LMCONTAINSSETEND:
  266. end;
  267. {$ifdef LARGESETS}
  268. procedure fpc_largeset_set_wor(p : pointer;b : word);assembler;[public,alias:'FPC_LARGESET_SET_WORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  269. {
  270. sets the element b in set p works for sets larger than 256 elements
  271. not yet use by the compiler so
  272. }
  273. asm
  274. pushl %eax
  275. movl p,%edi
  276. movw b,%ax
  277. andl $0xfff8,%eax
  278. shrl $3,%eax
  279. addl %eax,%edi
  280. movb 12(%ebp),%al
  281. andl $7,%eax
  282. btsl %eax,(%edi)
  283. popl %eax
  284. end;
  285. procedure fpc_largeset_in_word(p : pointer;b : word);assembler;[public,alias:'FPC_LARGESET_IN_WORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  286. {
  287. tests if the element b is in the set p the carryflag is set if it present
  288. works for sets larger than 256 elements
  289. }
  290. asm
  291. pushl %eax
  292. movl p,%edi
  293. movw b,%ax
  294. andl $0xfff8,%eax
  295. shrl $3,%eax
  296. addl %eax,%edi
  297. movb 12(%ebp),%al
  298. andl $7,%eax
  299. btl %eax,(%edi)
  300. popl %eax
  301. end;
  302. procedure fpc_largeset_add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_ADD_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  303. {
  304. adds set1 and set2 into set dest size is the number of bytes in the set
  305. }
  306. asm
  307. movl set1,%esi
  308. movl set2,%ebx
  309. movl dest,%edi
  310. movl size,%ecx
  311. .LMADDSETSIZES1:
  312. lodsl
  313. orl (%ebx),%eax
  314. stosl
  315. addl $4,%ebx
  316. decl %ecx
  317. jnz .LMADDSETSIZES1
  318. end;
  319. procedure fpc_largeset_mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_MUL_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  320. {
  321. multiplies (i.E. takes common elements of) set1 and set2 result put in
  322. dest size is the number of bytes in the set
  323. }
  324. asm
  325. movl set1,%esi
  326. movl set2,%ebx
  327. movl dest,%edi
  328. movl size,%ecx
  329. .LMMULSETSIZES1:
  330. lodsl
  331. andl (%ebx),%eax
  332. stosl
  333. addl $4,%ebx
  334. decl %ecx
  335. jnz .LMMULSETSIZES1
  336. end;
  337. procedure fpc_largeset_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_SUB_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  338. asm
  339. movl set1,%esi
  340. movl set2,%ebx
  341. movl dest,%edi
  342. movl size,%ecx
  343. .LMSUBSETSIZES1:
  344. lodsl
  345. movl (%ebx),%edx
  346. notl %edx
  347. andl %edx,%eax
  348. stosl
  349. addl $4,%ebx
  350. decl %ecx
  351. jnz .LMSUBSETSIZES1
  352. end;
  353. procedure fpc_largeset_symdif_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_SYMDIF_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  354. {
  355. computes the symetric diff from set1 to set2 result in dest
  356. }
  357. asm
  358. movl set1,%esi
  359. movl set2,%ebx
  360. movl dest,%edi
  361. movl size,%ecx
  362. .LMSYMDIFSETSIZE1:
  363. lodsl
  364. movl (%ebx),%edx
  365. xorl %edx,%eax
  366. stosl
  367. addl $4,%ebx
  368. decl %ecx
  369. jnz .LMSYMDIFSETSIZE1
  370. end;
  371. procedure fpc_largeset_comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_LARGESET_COMP_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  372. asm
  373. movl set1,%esi
  374. movl set2,%edi
  375. movl size,%ecx
  376. .LMCOMPSETSIZES1:
  377. lodsl
  378. movl (%edi),%edx
  379. cmpl %edx,%eax
  380. jne .LMCOMPSETSIZEEND
  381. addl $4,%edi
  382. decl %ecx
  383. jnz .LMCOMPSETSIZES1
  384. { we are here only if the two sets are equal
  385. we have zero flag set, and that what is expected }
  386. .LMCOMPSETSIZEEND:
  387. end;
  388. procedure fpc_largeset_contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_LARGESET_CONTAINS_SETS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  389. {
  390. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  391. }
  392. asm
  393. movl set1,%esi
  394. movl set2,%edi
  395. movl size,%ecx
  396. .LMCONTAINSSETS2:
  397. movl (%esi),%eax
  398. movl (%edi),%edx
  399. andl %eax,%edx
  400. cmpl %edx,%eax {set1 and set2 = set1?}
  401. jne .LMCONTAINSSETEND2
  402. addl $4,%esi
  403. addl $4,%edi
  404. decl %ecx
  405. jnz .LMCONTAINSSETS2
  406. { we are here only if set2 contains set1
  407. we have zero flag set, and that what is expected }
  408. .LMCONTAINSSETEND2:
  409. end;
  410. {$endif LARGESET}
  411. {
  412. $Log$
  413. Revision 1.5 2001-08-01 15:00:10 jonas
  414. + "compproc" helpers
  415. * renamed several helpers so that their name is the same as their
  416. "public alias", which should facilitate the conversion of processor
  417. specific code in the code generator to processor independent code
  418. * some small fixes to the val_ansistring and val_widestring helpers
  419. (always immediately exit if the source string is longer than 255
  420. chars)
  421. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  422. still nil (used to crash, now return resp -1 and 0)
  423. Revision 1.4 2001/05/09 19:57:07 peter
  424. *** empty log message ***
  425. Revision 1.3 2000/09/21 16:09:19 jonas
  426. + new, much faster do_set_range based on the PowerPC version (which
  427. will be committed tomorrow)
  428. Revision 1.2 2000/07/13 11:33:41 michael
  429. + removed logs
  430. }