set.inc 18 KB

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