2
0

set.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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. on entry: p in r3, l in r4
  16. }
  17. asm
  18. stw r4,(r3)
  19. li r4,0
  20. stw r4,4(r3)
  21. stw r4,8(r3)
  22. stw r4,12(r3)
  23. stw r4,16(r3)
  24. stw r4,20(r3)
  25. stw r4,24(r3)
  26. stw r4,28(r3)
  27. end ['R4'];
  28. procedure do_create_element(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_CREATE_ELEMENT'];
  29. {
  30. create a new set in p from an element b
  31. on entry: p in r3, b in r4
  32. }
  33. var
  34. saveR5, saveR6: longint;
  35. asm
  36. stw r5,saveR5
  37. li r5,0
  38. stw r6,saveR6
  39. stw r5,(r3)
  40. stw r5,4(r3)
  41. stw r5,8(r3)
  42. stw r5,12(r3)
  43. li r6,1
  44. stw r5,16(r3)
  45. stw r5,20(r3)
  46. stw r5,24(r3)
  47. stw r5,28(r3)
  48. // get the index of the correct *dword* in the set
  49. // (((b div 8) div 4)*4= (b div 8) and not(3))
  50. rlwinm r5,r4,29,3,31 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  51. // r4 := 1 shl r4[27-31] -> bit index in dword (rlw* instructions with
  52. // shift count in register only consider lower 5 bits of this register)
  53. rotlw r4,r6,r4 // equivalent to rlwnm r4,r6,r4,0,31
  54. // store the result
  55. stwx r4,r3,r5
  56. lwz r5,saveR5
  57. lwz r6,saveR6
  58. end ['R4'];
  59. procedure do_set_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_SET_BYTE'];
  60. {
  61. add the element b to the set pointed by p
  62. on entry: p in r3, b in r4
  63. }
  64. var
  65. saveR5, saveR6: longint;
  66. asm
  67. stw r5,saveR5
  68. stw r6,saveR6
  69. // get the index of the correct *dword* in the set
  70. rlwinm r5,r4,29,3,31 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  71. // load dword in which the bit has to be set (and update r3 to this address)
  72. lwzxu r6,r3,r5
  73. li r5,1
  74. // generate bit which has to be inserted
  75. rotlw r4,r5,r4 // equivalent to rlwnm r4,r5,r4,0,31
  76. // insert it
  77. lwz r5,saveR5
  78. or r7,r7,r4
  79. lwz r6,saveR6
  80. // store result
  81. stw r7,(r3)
  82. end ['R3','R4'];
  83. procedure do_unset_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_UNSET_BYTE'];
  84. {
  85. suppresses the element b to the set pointed by p
  86. used for exclude(set,element)
  87. on entry: p in r3, b in r4
  88. }
  89. var
  90. saveR5, saveR6: longint;
  91. asm
  92. stw r5,saveR5
  93. stw r6,saveR6
  94. // get the index of the correct *dword* in the set
  95. rlwinm r5,r4,29,3,31 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  96. // load dword in which the bit has to be set (and update r3 to this address)
  97. lwzxu r6,r3,r5
  98. li r5,1
  99. // generate bit which has to be inserted
  100. rotlw r4,r5,r4 // equivalent to rlwnm r4,r5,r4,0,31
  101. // insert it
  102. lwz r5,saveR5
  103. nor r7,r7,r4
  104. lwz r6,saveR6
  105. // store result
  106. stw r7,(r3)
  107. end ['R3','R4'];
  108. procedure do_set_range(p : pointer;l,h : byte);assembler;[public,alias:'FPC_SET_SET_RANGE'];
  109. {
  110. bad implementation, but it's very seldom used
  111. on entry: p in r3, l in r4, h in r5
  112. }
  113. var
  114. saveR6, saveR7, saveR8: longint;
  115. asm
  116. cmplw cr0,r4,r5
  117. bg cr0,.LSET_RANGE_EXIT
  118. stw r6,saveR6
  119. stw r7,saveR7
  120. stw r8,saveR8
  121. lwz r7,(r3)
  122. pushl %eax
  123. movl p,%edi
  124. xorl %eax,%eax
  125. xorl %ecx,%ecx
  126. movb h,%al
  127. movb l,%cl
  128. .LSET_SET_RANGE_LOOP:
  129. cmpl %ecx,%eax
  130. jl .LSET_SET_RANGE_EXIT
  131. movl %eax,%ebx
  132. movl %eax,%edx
  133. andl $0xf8,%ebx
  134. andl $7,%edx
  135. shrl $3,%ebx
  136. btsl %edx,(%edi,%ebx)
  137. dec %eax
  138. jmp .LSET_SET_RANGE_LOOP
  139. .LSET_SET_RANGE_EXIT:
  140. popl %eax
  141. end ['R4'];
  142. procedure do_in_byte(p : pointer;b : byte);assembler;[public,alias:'FPC_SET_IN_BYTE'];
  143. {
  144. tests if the element b is in the set p, the **zero** flag is cleared if it's present
  145. on entry: p in r3, b in r4
  146. }
  147. var
  148. saveR5, saveR6: longint;
  149. asm
  150. stw r5,saveR5
  151. stw r6,saveR6
  152. // get the index of the correct *dword* in the set
  153. rlwinm r5,r4,29,3,31 // r5 := (r4 rotl(32-3)) and (0x0fffffff8)
  154. // load dword in which the bit has to be set (and update r3 to this address)
  155. lwzx r6,r3,r5
  156. li r5,1
  157. // generate bit which has to be inserted
  158. rotlw r4,r5,r4 // equivalent to rlwnm r4,r5,r4,0,31
  159. // insert it
  160. lwz r5,saveR5
  161. and. r7,r7,r4
  162. lwz r6,saveR6
  163. // store result
  164. stw r7,(r3)
  165. end ['R4'];
  166. procedure do_add_sets(set1,set2,dest : pointer);assembler;[public,alias:'FPC_SET_ADD_SETS'];
  167. {
  168. adds set1 and set2 into set dest
  169. on entry: set1 in r3, set2 in r4, dest in r5
  170. }
  171. var
  172. saveR6, saveR7, saveR8: longint;
  173. asm
  174. stw r6,saveR6
  175. stw r7,saveR7
  176. subi r5,r5,4
  177. li r6,8
  178. stw r8,saveR8
  179. lwz r7,(r3)
  180. lwz r8,(r4)
  181. .LMADDSETS1:
  182. subi. r6,r6,1
  183. or r7,r7,r8
  184. lwzu r8,4(r4)
  185. stwu r7,4(r5)
  186. lwzu r7,4(r3)
  187. bne cr0,.LMADDSETS1
  188. lwz r6,saveR6
  189. lwz r7,saveR7
  190. lwz r8,saveR8
  191. end ['R3','R4','R5'];
  192. procedure do_mul_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_MUL_SETS'];
  193. {
  194. multiplies (takes common elements of) set1 and set2 result put in dest
  195. on entry: set1 in r3, set2 in r4, dest in r5
  196. }
  197. var
  198. saveR6, saveR7, saveR8: longint;
  199. asm
  200. stw r6,saveR6
  201. stw r7,saveR7
  202. subi r5,r5,4
  203. li r6,8
  204. stw r8,saveR8
  205. lwz r7,(r3)
  206. lwz r8,(r4)
  207. .LMADDSETS1:
  208. subi. r6,r6,1
  209. and r7,r7,r8
  210. lwzu r8,4(r4)
  211. stwu r7,4(r5)
  212. lwzu r7,4(r3)
  213. bne cr0,.LMADDSETS1
  214. lwz r6,saveR6
  215. lwz r7,saveR7
  216. lwz r8,saveR8
  217. end ['R3','R4','R5'];
  218. procedure do_sub_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SUB_SETS'];
  219. {
  220. computes the diff from set1 to set2 result in dest
  221. on entry: set1 in r3, set2 in r4, dest in r5
  222. }
  223. var
  224. saveR6, saveR7, saveR8: longint;
  225. asm
  226. stw r6,saveR6
  227. stw r7,saveR7
  228. subi r5,r5,4
  229. li r6,8
  230. stw r8,saveR8
  231. lwz r7,(r3)
  232. lwz r8,(r4)
  233. .LMSUBSETS1:
  234. subi. r6,r6,1
  235. andc r8,r8,r7
  236. lwzu r7,4(r3)
  237. stwu r8,4(r5)
  238. lwzu r8,4(r4)
  239. bne cr0,.LMSUBSETS1
  240. lwz r6,saveR6
  241. lwz r7,saveR7
  242. lwz r8,saveR8
  243. end ['R3','R4','R5'];
  244. procedure do_symdif_sets(set1,set2,dest:pointer);assembler;[public,alias:'FPC_SET_SYMDIF_SETS'];
  245. {
  246. computes the symetric diff from set1 to set2 result in dest
  247. on entry: set1 in r3, set2 in r4, dest in r5
  248. }
  249. var
  250. saveR6, saveR7, saveR8: longint;
  251. asm
  252. stw r6,saveR6
  253. stw r7,saveR7
  254. subi r5,r5,4
  255. li r6,8
  256. stw r8,saveR8
  257. lwz r7,(r3)
  258. lwz r8,(r4)
  259. .LMSYMDIFSETS1:
  260. subi. r6,r6,1
  261. xor r7,r7,r8
  262. lwzu r8,4(r4)
  263. stwu r7,4(r5)
  264. lwzu r7,4(r3)
  265. bne cr0,.LMSYMDIFSETS1
  266. lwz r6,saveR6
  267. lwz r7,saveR7
  268. lwz r8,saveR8
  269. end ['R3','R4','R5'];
  270. procedure do_comp_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_COMP_SETS'];
  271. {
  272. compares set1 and set2 zeroflag is set if they are equal
  273. on entry: set1 in r3, set2 in r4
  274. }
  275. var
  276. saveR5, saveR6, saveR7: longint;
  277. asm
  278. stw r5,saveR5
  279. mfctr r5
  280. stw r6,saveR6
  281. li r6,8
  282. stw r7,saveR7
  283. mtctr r6
  284. lwz r6,(r3)
  285. lwz r7,(r4)
  286. .LMCOMPSETS1:
  287. cmplw cr0,r6,r7
  288. lwzu r6,4(r3)
  289. lwzu r7,4(r4)
  290. bdnzeq cr0,.LMCOMPSETS1
  291. mtctr r5
  292. lwz r5,saveR5
  293. lwz r6,saveR6
  294. lwz r7,saveR7
  295. end ['R3','R4'];
  296. {$IfNDef NoSetInclusion}
  297. procedure do_contains_sets(set1,set2 : pointer);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  298. {
  299. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  300. on entry: set1 in r3, set2 in r4
  301. }
  302. var
  303. saveR5, saveR6, saveR7: longint;
  304. asm
  305. stw r5,saveR5
  306. mfctr r5
  307. stw r6,saveR6
  308. li r6,8
  309. stw r7,saveR7
  310. mtctr r6
  311. lwz r6,(r3)
  312. lwz r7,(r4)
  313. .LMCOMPSETS1:
  314. andc. r7,r6,r7
  315. lwzu r6,4(r3)
  316. lwzu r7,4(r4)
  317. bdnzeq cr0,.LMCOMPSETS1
  318. mtctr r5
  319. lwz r5,saveR5
  320. lwz r6,saveR6
  321. lwz r7,saveR7
  322. end ['R3','R4'];
  323. {$EndIf SetInclusion}
  324. {$ifdef LARGESETS}
  325. procedure do_set(p : pointer;b : word);assembler;[public,alias:'FPC_SET_SET_WORD'];
  326. {
  327. sets the element b in set p works for sets larger than 256 elements
  328. not yet use by the compiler so
  329. }
  330. asm
  331. pushl %eax
  332. movl p,%edi
  333. movw b,%ax
  334. andl $0xfff8,%eax
  335. shrl $3,%eax
  336. addl %eax,%edi
  337. movb 12(%ebp),%al
  338. andl $7,%eax
  339. btsl %eax,(%edi)
  340. popl %eax
  341. end;
  342. procedure do_in(p : pointer;b : word);assembler;[public,alias:'FPC_SET_IN_WORD'];
  343. {
  344. tests if the element b is in the set p the carryflag is set if it present
  345. works for sets larger than 256 elements
  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. btl %eax,(%edi)
  357. popl %eax
  358. end;
  359. procedure add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_ADD_SETS_SIZE'];
  360. {
  361. adds set1 and set2 into set dest size is the number of bytes in the set
  362. }
  363. asm
  364. movl set1,%esi
  365. movl set2,%ebx
  366. movl dest,%edi
  367. movl size,%ecx
  368. .LMADDSETSIZES1:
  369. lodsl
  370. orl (%ebx),%eax
  371. stosl
  372. addl $4,%ebx
  373. decl %ecx
  374. jnz .LMADDSETSIZES1
  375. end;
  376. procedure mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_MUL_SETS_SIZE'];
  377. {
  378. multiplies (i.E. takes common elements of) set1 and set2 result put in
  379. dest size is the number of bytes in the set
  380. }
  381. asm
  382. movl set1,%esi
  383. movl set2,%ebx
  384. movl dest,%edi
  385. movl size,%ecx
  386. .LMMULSETSIZES1:
  387. lodsl
  388. andl (%ebx),%eax
  389. stosl
  390. addl $4,%ebx
  391. decl %ecx
  392. jnz .LMMULSETSIZES1
  393. end;
  394. procedure sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SUB_SETS_SIZE'];
  395. asm
  396. movl set1,%esi
  397. movl set2,%ebx
  398. movl dest,%edi
  399. movl size,%ecx
  400. .LMSUBSETSIZES1:
  401. lodsl
  402. movl (%ebx),%edx
  403. notl %edx
  404. andl %edx,%eax
  405. stosl
  406. addl $4,%ebx
  407. decl %ecx
  408. jnz .LMSUBSETSIZES1
  409. end;
  410. procedure sym_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SYMDIF_SETS_SIZE'];
  411. {
  412. computes the symetric diff from set1 to set2 result in dest
  413. }
  414. asm
  415. movl set1,%esi
  416. movl set2,%ebx
  417. movl dest,%edi
  418. movl size,%ecx
  419. .LMSYMDIFSETSIZE1:
  420. lodsl
  421. movl (%ebx),%edx
  422. xorl %edx,%eax
  423. stosl
  424. addl $4,%ebx
  425. decl %ecx
  426. jnz .LMSYMDIFSETSIZE1
  427. end;
  428. procedure comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_SET_COMP_SETS_SIZE'];
  429. asm
  430. movl set1,%esi
  431. movl set2,%edi
  432. movl size,%ecx
  433. .LMCOMPSETSIZES1:
  434. lodsl
  435. movl (%edi),%edx
  436. cmpl %edx,%eax
  437. jne .LMCOMPSETSIZEEND
  438. addl $4,%edi
  439. decl %ecx
  440. jnz .LMCOMPSETSIZES1
  441. { we are here only if the two sets are equal
  442. we have zero flag set, and that what is expected }
  443. .LMCOMPSETSIZEEND:
  444. end;
  445. {$IfNDef NoSetInclusion}
  446. procedure contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  447. {
  448. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  449. }
  450. asm
  451. movl set1,%esi
  452. movl set2,%edi
  453. movl size,%ecx
  454. .LMCONTAINSSETS2:
  455. movl (%esi),%eax
  456. movl (%edi),%edx
  457. andl %eax,%edx
  458. cmpl %edx,%eax {set1 and set2 = set1?}
  459. jne .LMCONTAINSSETEND2
  460. addl $4,%esi
  461. addl $4,%edi
  462. decl %ecx
  463. jnz .LMCONTAINSSETS2
  464. { we are here only if set2 contains set1
  465. we have zero flag set, and that what is expected }
  466. .LMCONTAINSSETEND2:
  467. end;
  468. {$EndIf NoSetInclusion}
  469. {$endif LARGESET}
  470. {
  471. $Log$
  472. Revision 1.1 2000-07-13 06:31:13 michael
  473. + Initial import
  474. Revision 1.3 2000/06/30 10:32:43 jonas
  475. * some optimizations suggested by Anton Rang in c.s.powerpc.misc
  476. Revision 1.1 2000/06/28 13:43:29 jonas
  477. * inital version, everything not yet implemented
  478. }