set.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Jonas Maebe, member of the
  5. Free Pascal development team
  6. Include file with set operations called by the compiler
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. procedure do_load_small(p : pointer;l:longint);assembler;[public,alias:'FPC_SET_LOAD_SMALL'];
  14. {
  15. load a normal set p from a smallset l
  16. on entry: p in r3, l in r4
  17. }
  18. asm
  19. stw r4,(r3)
  20. li r4,0
  21. stw r4,4(r3)
  22. stw r4,8(r3)
  23. stw r4,12(r3)
  24. stw r4,16(r3)
  25. stw r4,20(r3)
  26. stw r4,24(r3)
  27. stw r4,28(r3)
  28. end ['R4'];
  29. procedure do_create_element(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_CREATE_ELEMENT'];
  30. {
  31. create a new set in p from an element b
  32. on entry: p in r3, b in r4
  33. }
  34. var
  35. saveR5, saveR6: longint;
  36. asm
  37. stw r5,saveR5
  38. li r5,0
  39. stw r6,saveR6
  40. stw r5,(r3)
  41. stw r5,4(r3)
  42. li r6,1
  43. stw r5,8(r3)
  44. stw r5,12(r3)
  45. stw r5,16(r3)
  46. stw r5,20(r3)
  47. // r6 := 1 shl r4[27-31] -> bit index in dword (shift instructions
  48. // with count in register only consider lower 5 bits of this register)
  49. slw r6,r6,r4
  50. stw r5,24(r3)
  51. stw r5,28(r3)
  52. // get the index of the correct *dword* in the set
  53. // (((b div 8) div 4)*4= (b div 8) and not(3))
  54. // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  55. rlwinm r5,r4,29,0,31-2
  56. // store the result
  57. stwx r6,r3,r5
  58. lwz r5,saveR5
  59. lwz r6,saveR6
  60. end ['R4'];
  61. procedure do_set_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_SET_BYTE'];
  62. {
  63. add the element b to the set pointed by p
  64. on entry: p in r3, b in r4
  65. }
  66. var
  67. saveR5, saveR6: longint;
  68. asm
  69. stw r5,saveR5
  70. stw r6,saveR6
  71. // get the index of the correct *dword* in the set
  72. rlwinm r5,r4,29,0,31-2 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  73. // load dword in which the bit has to be set (and update r3 to this address)
  74. lwzxu r6,r3,r5
  75. li r5,1
  76. // generate bit which has to be inserted
  77. slw r4,r5,r4
  78. // insert it
  79. lwz r5,saveR5
  80. or r4,r7,r4
  81. lwz r6,saveR6
  82. // store result
  83. stw r4,(r3)
  84. end ['R3','R4'];
  85. procedure do_unset_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_UNSET_BYTE'];
  86. {
  87. suppresses the element b to the set pointed by p
  88. used for exclude(set,element)
  89. on entry: p in r3, b in r4
  90. }
  91. var
  92. saveR5, saveR6: longint;
  93. asm
  94. stw r5,saveR5
  95. stw r6,saveR6
  96. // get the index of the correct *dword* in the set
  97. rlwinm r5,r4,29,0,31-2 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  98. // load dword in which the bit is (and update r3 to this address)
  99. lwzxu r6,r3,r5
  100. li r5,1
  101. // generate bit which has to be cleared
  102. slw r4,r5,r4
  103. lwz r5,saveR5
  104. // remove it
  105. andc r4,r6,r4
  106. lwz r6,saveR6
  107. // store result
  108. stw r4,(r3)
  109. end ['R3','R4'];
  110. procedure do_set_range(p : pointer;l,h : byte);assembler;[public,alias:'FPC_SET_SET_RANGE'];
  111. {
  112. on entry: p in r3, l in r4, h in r5
  113. }
  114. var
  115. saveR6, saveR7, saveR8: longint;
  116. asm
  117. cmplw cr0,r4,r5
  118. bg cr0,.LSET_RANGE_EXIT
  119. stw r6,saveR6
  120. stw r7,saveR7
  121. stw r8,saveR8
  122. rlwinm r6,r4,32-3,0,31-2 // divide by 8 to get starting and ending byte-
  123. rlwinm r7,r5,32-3,0,31-2 // address and clear two lowest bits to get
  124. // start/end longint address
  125. sub. r7,r6,r7 // are bit lo and hi in the same longint?
  126. rlwinm r5,r5,0,31-4,31 // hi := hi mod 32 (= "hi and 31", but the andi
  127. // instr. only exists in flags modifying form)
  128. eqv r8,r8,r8 // r8 = $0x0ffffffff = bitmask to be inserted
  129. subfic r5,r5,31 // hi := 31 - (hi mod 32) = shift count for later
  130. srw r8,r8,r4 // shift bitmask to clear bits below lo
  131. // note: shift right = opposite little endian!!
  132. lwzxu r4,r3,r6 // go to starting pos in set and load value
  133. // (lo is not necessary anymore)
  134. beq .Lset_range_hi // if bit lo and hi in same longint, keep
  135. // current mask and adjust for hi bit
  136. subic. r7,r7,4 // bit hi in next longint?
  137. or r4,r4,r8 // merge and
  138. stw r4,(r3) // store current mask
  139. eqv r8,r8,r8 // new mask
  140. lwzu r4,4(r3) // load next longint of set
  141. beq .Lset_range_hi // bit hi in this longint -> go to adjust for hi
  142. .Lset_range_loop:
  143. subic. r7,r7,4
  144. stwu r8,4(r3) // fill longints in between with full mask
  145. bne .Lset_range_loop
  146. lwzu r4,4(r3) // load next value from set
  147. .Lset_range_hi: // in all cases, r3 here contains the address of
  148. // the longint which contains the hi bit and r4
  149. // contains this longint
  150. slw r7,r8,r5 // r7 := bitmask shl (31 - (hi mod 32)) =
  151. // bitmask with bits higher than hi cleared
  152. // (r8 = $0xffffffff unless the first beq was
  153. // taken)
  154. and r8,r7,r8 // combine lo and hi bitmasks for this longint
  155. or r4,r4,r8 // and combine with existing set
  156. stw r4,(r3) // store to set
  157. lwz r6,saver6
  158. lwz r7,saver7
  159. lwz r8,saver8
  160. .Lset_range_exit:
  161. end ['R3','R4','R5'];
  162. procedure do_in_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_IN_BYTE'];
  163. {
  164. tests if the element b is in the set p, the **zero** flag is cleared if it's present
  165. on entry: p in r3, b in r4
  166. }
  167. var
  168. saveR5: longint;
  169. asm
  170. stw r5,saveR5
  171. // get the index of the correct *dword* in the set
  172. // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  173. rlwinm r5,r4,29,0,31-2
  174. // load dword in which the bit has to be tested
  175. lwzx r3,r3,r5
  176. li r5,1
  177. // generate bit which has to be tested
  178. slw r4,r5,r4
  179. lwz r5,saveR5
  180. // test it
  181. and. r3,r3,r4
  182. end ['R4'];
  183. procedure do_add_sets(set1,set2,dest : pointer);assembler;[public,alias:'FPC_SET_ADD_SETS'];
  184. {
  185. adds set1 and set2 into set dest
  186. on entry: set1 in r3, set2 in r4, dest in r5
  187. }
  188. var
  189. saveR6, saveR7, saveR8: longint;
  190. asm
  191. stw r6,saveR6
  192. stw r7,saveR7
  193. subi r5,r5,4
  194. li r6,8
  195. stw r8,saveR8
  196. subi r3,4
  197. subi r4,4
  198. .LMADDSETS1:
  199. subic. r6,r6,1
  200. lwzu r7,4(r3)
  201. lwzu r8,4(r4)
  202. or r7,r7,r8
  203. stwu r7,4(r5)
  204. bne cr0,.LMADDSETS1
  205. lwz r6,saveR6
  206. lwz r7,saveR7
  207. lwz r8,saveR8
  208. end ['R3','R4','R5'];
  209. procedure do_mul_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_MUL_SETS'];
  210. {
  211. multiplies (takes common elements of) set1 and set2 result put in dest
  212. on entry: set1 in r3, set2 in r4, dest in r5
  213. }
  214. var
  215. saveR6, saveR7, saveR8: longint;
  216. asm
  217. stw r6,saveR6
  218. stw r7,saveR7
  219. subi r5,r5,4
  220. li r6,8
  221. stw r8,saveR8
  222. subi r3,4
  223. subi r4,4
  224. .LMADDSETS1:
  225. subic. r6,r6,1
  226. lwzu r7,4(r3)
  227. lwzu r8,4(r4)
  228. and r7,r7,r8
  229. stwu r7,4(r5)
  230. bne cr0,.LMADDSETS1
  231. lwz r6,saveR6
  232. lwz r7,saveR7
  233. lwz r8,saveR8
  234. end ['R3','R4','R5'];
  235. procedure do_sub_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SUB_SETS'];
  236. {
  237. computes the diff from set1 to set2 result in dest
  238. on entry: set1 in r3, set2 in r4, dest in r5
  239. }
  240. var
  241. saveR6, saveR7, saveR8: longint;
  242. asm
  243. stw r6,saveR6
  244. stw r7,saveR7
  245. subi r5,r5,4
  246. li r6,8
  247. stw r8,saveR8
  248. subi r3,4
  249. subi r4,4
  250. .LMSUBSETS1:
  251. subi. r6,r6,1
  252. lwzu r8,4(r4)
  253. lwzu r7,4(r3)
  254. andc r8,r8,r7
  255. stwu r8,4(r5)
  256. bne cr0,.LMSUBSETS1
  257. lwz r6,saveR6
  258. lwz r7,saveR7
  259. lwz r8,saveR8
  260. end ['R3','R4','R5'];
  261. procedure do_symdif_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SYMDIF_SETS'];
  262. {
  263. computes the symetric diff from set1 to set2 result in dest
  264. on entry: set1 in r3, set2 in r4, dest in r5
  265. }
  266. var
  267. saveR6, saveR7, saveR8: longint;
  268. asm
  269. stw r6,saveR6
  270. stw r7,saveR7
  271. subi r5,r5,4
  272. li r6,8
  273. stw r8,saveR8
  274. subi r3,4
  275. subi r4,4
  276. .LMSYMDIFSETS1:
  277. subi. r6,r6,1
  278. lwzu r7,4(r3)
  279. lwzu r8,4(r4)
  280. xor r7,r7,r8
  281. stwu r7,4(r5)
  282. bne cr0,.LMSYMDIFSETS1
  283. lwz r6,saveR6
  284. lwz r7,saveR7
  285. lwz r8,saveR8
  286. end ['R3','R4','R5'];
  287. procedure do_comp_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_COMP_SETS'];
  288. {
  289. compares set1 and set2 zeroflag is set if they are equal
  290. on entry: set1 in r3, set2 in r4
  291. }
  292. var
  293. saveR5, saveR6, saveR7: longint;
  294. asm
  295. stw r5,saveR5
  296. mfctr r5
  297. stw r6,saveR6
  298. li r6,8
  299. stw r7,saveR7
  300. mtctr r6
  301. subi r3,4
  302. subi r4,4
  303. .LMCOMPSETS1:
  304. lwzu r6,4(r3)
  305. lwzu r7,4(r4)
  306. cmplw cr0,r6,r7
  307. bdnzeq cr0,.LMCOMPSETS1
  308. mtctr r5
  309. lwz r5,saveR5
  310. lwz r6,saveR6
  311. lwz r7,saveR7
  312. end ['R3','R4'];
  313. {$IfNDef NoSetInclusion}
  314. procedure do_contains_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  315. {
  316. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  317. on entry: set1 in r3, set2 in r4
  318. }
  319. var
  320. saveR5, saveR6, saveR7: longint;
  321. asm
  322. stw r5,saveR5
  323. mfctr r5
  324. stw r6,saveR6
  325. li r6,8
  326. stw r7,saveR7
  327. mtctr r6
  328. subi r3,4
  329. subi r4,4
  330. .LMCOMPSETS1:
  331. lwzu r7,4(r4)
  332. lwzu r6,4(r3)
  333. andc. r7,r6,r7
  334. bdnzeq cr0,.LMCOMPSETS1
  335. mtctr r5
  336. lwz r5,saveR5
  337. lwz r6,saveR6
  338. lwz r7,saveR7
  339. end ['R3','R4'];
  340. {$EndIf SetInclusion}
  341. {$ifdef LARGESETS}
  342. procedure do_set(p : pointer;b : word);assembler;[public,alias:'FPC_SET_SET_WORD'];
  343. {
  344. sets the element b in set p works for sets larger than 256 elements
  345. not yet use by the compiler so
  346. }
  347. asm
  348. pushl %eax
  349. movl p,%edi
  350. movw b,%ax
  351. andl $0xfff8,%eax
  352. shrl $3,%eax
  353. addl %eax,%edi
  354. movb 12(%ebp),%al
  355. andl $7,%eax
  356. btsl %eax,(%edi)
  357. popl %eax
  358. end;
  359. procedure do_in(p : pointer;b : word);assembler;[public,alias:'FPC_SET_IN_WORD'];
  360. {
  361. tests if the element b is in the set p the carryflag is set if it present
  362. works for sets larger than 256 elements
  363. }
  364. asm
  365. pushl %eax
  366. movl p,%edi
  367. movw b,%ax
  368. andl $0xfff8,%eax
  369. shrl $3,%eax
  370. addl %eax,%edi
  371. movb 12(%ebp),%al
  372. andl $7,%eax
  373. btl %eax,(%edi)
  374. popl %eax
  375. end;
  376. procedure add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_ADD_SETS_SIZE'];
  377. {
  378. adds set1 and set2 into set dest size is the number of bytes in the set
  379. }
  380. asm
  381. movl set1,%esi
  382. movl set2,%ebx
  383. movl dest,%edi
  384. movl size,%ecx
  385. .LMADDSETSIZES1:
  386. lodsl
  387. orl (%ebx),%eax
  388. stosl
  389. addl $4,%ebx
  390. decl %ecx
  391. jnz .LMADDSETSIZES1
  392. end;
  393. procedure mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_MUL_SETS_SIZE'];
  394. {
  395. multiplies (i.E. takes common elements of) set1 and set2 result put in
  396. dest size is the number of bytes in the set
  397. }
  398. asm
  399. movl set1,%esi
  400. movl set2,%ebx
  401. movl dest,%edi
  402. movl size,%ecx
  403. .LMMULSETSIZES1:
  404. lodsl
  405. andl (%ebx),%eax
  406. stosl
  407. addl $4,%ebx
  408. decl %ecx
  409. jnz .LMMULSETSIZES1
  410. end;
  411. procedure sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SUB_SETS_SIZE'];
  412. asm
  413. movl set1,%esi
  414. movl set2,%ebx
  415. movl dest,%edi
  416. movl size,%ecx
  417. .LMSUBSETSIZES1:
  418. lodsl
  419. movl (%ebx),%edx
  420. notl %edx
  421. andl %edx,%eax
  422. stosl
  423. addl $4,%ebx
  424. decl %ecx
  425. jnz .LMSUBSETSIZES1
  426. end;
  427. procedure sym_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SYMDIF_SETS_SIZE'];
  428. {
  429. computes the symetric diff from set1 to set2 result in dest
  430. }
  431. asm
  432. movl set1,%esi
  433. movl set2,%ebx
  434. movl dest,%edi
  435. movl size,%ecx
  436. .LMSYMDIFSETSIZE1:
  437. lodsl
  438. movl (%ebx),%edx
  439. xorl %edx,%eax
  440. stosl
  441. addl $4,%ebx
  442. decl %ecx
  443. jnz .LMSYMDIFSETSIZE1
  444. end;
  445. procedure comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_SET_COMP_SETS_SIZE'];
  446. asm
  447. movl set1,%esi
  448. movl set2,%edi
  449. movl size,%ecx
  450. .LMCOMPSETSIZES1:
  451. lodsl
  452. movl (%edi),%edx
  453. cmpl %edx,%eax
  454. jne .LMCOMPSETSIZEEND
  455. addl $4,%edi
  456. decl %ecx
  457. jnz .LMCOMPSETSIZES1
  458. { we are here only if the two sets are equal
  459. we have zero flag set, and that what is expected }
  460. .LMCOMPSETSIZEEND:
  461. end;
  462. {$IfNDef NoSetInclusion}
  463. procedure contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  464. {
  465. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  466. }
  467. asm
  468. movl set1,%esi
  469. movl set2,%edi
  470. movl size,%ecx
  471. .LMCONTAINSSETS2:
  472. movl (%esi),%eax
  473. movl (%edi),%edx
  474. andl %eax,%edx
  475. cmpl %edx,%eax {set1 and set2 = set1?}
  476. jne .LMCONTAINSSETEND2
  477. addl $4,%esi
  478. addl $4,%edi
  479. decl %ecx
  480. jnz .LMCONTAINSSETS2
  481. { we are here only if set2 contains set1
  482. we have zero flag set, and that what is expected }
  483. .LMCONTAINSSETEND2:
  484. end;
  485. {$EndIf NoSetInclusion}
  486. {$endif LARGESET}
  487. {
  488. $Log$
  489. Revision 1.6 2000-10-07 14:42:16 jonas
  490. * Fixed small error and did a small optimization
  491. Revision 1.5 2000/09/26 14:22:13 jonas
  492. * one more bug corrected
  493. Revision 1.4 2000/09/26 14:19:04 jonas
  494. * fixed several small bugs
  495. * fixed several typo's in the comments
  496. Revision 1.3 2000/09/22 10:03:18 jonas
  497. + implementation for FPC_SET_SET_RANGE
  498. * changed some routines so they never read data from after the actual
  499. set (could cause sigsegv's if the set is at the end of the heap)
  500. Revision 1.2 2000/07/13 11:33:56 michael
  501. + removed logs
  502. }