set.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Jonas Maebe, member of the
  4. 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']; compilerproc;
  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,0(r3)
  20. li r0,0
  21. stw r0,4(r3)
  22. stw r0,8(r3)
  23. stw r0,12(r3)
  24. stw r0,16(r3)
  25. stw r0,20(r3)
  26. stw r0,24(r3)
  27. stw r0,28(r3)
  28. end;
  29. {$define FPC_SYSTEM_HAS_FPC_SET_CREATE_ELEMENT}
  30. { checked 2001/09/28 (JM) }
  31. function fpc_set_create_element(b : byte): fpc_normal_set;assembler;[public,alias:'FPC_SET_CREATE_ELEMENT']; compilerproc;
  32. {
  33. create a new set in p from an element b
  34. on entry: pointer to result in r3, b in r4
  35. }
  36. asm
  37. li r0,0
  38. stw r0,0(r3)
  39. stw r0,4(r3)
  40. stw r0,8(r3)
  41. stw r0,12(r3)
  42. stw r0,16(r3)
  43. stw r0,20(r3)
  44. stw r0,24(r3)
  45. stw r0,28(r3)
  46. // r0 := 1 shl r4[27-31] -> bit index in dword (rotate instructions
  47. // with count in register only consider lower 5 bits of this register)
  48. li r0,1
  49. rlwnm r0,r0,r4,0,31
  50. // get the index of the correct *dword* in the set
  51. // (((b div 8) div 4)*4= (b div 8) and not(3))
  52. // r5 := (r4 rotl(32-3)) and (0x01ffffff8)
  53. rlwinm r4,r4,31-3+1,3,31-2
  54. // store the result
  55. stwx r0,r3,r4
  56. end;
  57. {$define FPC_SYSTEM_HAS_FPC_SET_SET_BYTE}
  58. function fpc_set_set_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  59. {
  60. add the element b to the set pointed by p
  61. on entry: result in r3, source in r4, b in r5
  62. }
  63. asm
  64. // copy source to result
  65. lfd f0,0(r4)
  66. lfd f1,8(r4)
  67. lfd f2,16(r4)
  68. lfd f3,24(r4)
  69. stfd f0,0(r3)
  70. stfd f1,8(r3)
  71. stfd f2,16(r3)
  72. stfd f3,24(r3)
  73. // get the index of the correct *dword* in the set
  74. // r0 := (r5 rotl(32-3)) and (0x0fffffff8)
  75. rlwinm r0,r5,31-3+1,3,31-2
  76. // load dword in which the bit has to be set (and update r3 to this address)
  77. lwzux r4,r3,r0
  78. li r0,1
  79. // generate bit which has to be inserted
  80. // (can't use rlwimi, since that one only works for constants)
  81. rlwnm r5,r0,r5,0,31
  82. // insert it
  83. or r5,r4,r5
  84. // store result
  85. stw r5,0(r3)
  86. end;
  87. {$define FPC_SYSTEM_HAS_FPC_SET_UNSET_BYTE}
  88. function fpc_set_unset_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  89. {
  90. suppresses the element b to the set pointed by p
  91. used for exclude(set,element)
  92. on entry: p in r3, b in r4
  93. }
  94. asm
  95. // copy source to result
  96. lfd f0,0(r4)
  97. lfd f1,8(r4)
  98. lfd f2,16(r4)
  99. lfd f3,24(r4)
  100. stfd f0,0(r3)
  101. stfd f1,8(r3)
  102. stfd f2,16(r3)
  103. stfd f3,24(r3)
  104. // get the index of the correct *dword* in the set
  105. // r0 := (r4 rotl(32-3)) and (0x0fffffff8)
  106. rlwinm r0,r5,31-3+1,3,31-2
  107. // load dword in which the bit has to be set (and update r3 to this address)
  108. lwzux r4,r3,r0
  109. li r0,1
  110. // generate bit which has to be removed
  111. rlwnm r5,r0,r5,0,31
  112. // remove it
  113. andc r5,r4,r5
  114. // store result
  115. stw r4,0(r3)
  116. end;
  117. {$define FPC_SYSTEM_HAS_FPC_SET_SET_RANGE}
  118. function fpc_set_set_range(const orgset: fpc_normal_set; l,h : byte): fpc_normal_set;assembler; compilerproc;
  119. {
  120. on entry: result in r3, l in r4, h in r5
  121. on entry: result in r3, ptr to orgset in r4, l in r5, h in r6
  122. }
  123. asm
  124. // copy source to result
  125. lfd f0,0(r4)
  126. lfd f1,8(r4)
  127. lfd f2,16(r4)
  128. lfd f3,24(r4)
  129. stfd f0,0(r3)
  130. stfd f1,8(r3)
  131. stfd f2,16(r3)
  132. stfd f3,24(r3)
  133. cmplw cr0,r5,r6
  134. bgt cr0,.Lset_range_exit
  135. rlwinm r4,r5,31-3+1,3,31-2 // divide by 8 to get starting and ending byte-
  136. { load the set the data cache }
  137. dcbtst r3,r4
  138. rlwinm r9,r6,31-3+1,3,31-2 // address and clear two lowest bits to get
  139. // start/end longint address
  140. sub. r9,r9,r4 // are bit lo and hi in the same longint?
  141. rlwinm r6,r6,0,31-5+1,31 // hi := hi mod 32 (= "hi and 31", but the andi
  142. // instr. only exists in flags modifying form)
  143. rlwinm r5,r5,0,31-5+1,31 // lo := lo mod 32 (= "lo and 31", but the andi
  144. // instr. only exists in flags modifying form)
  145. li r10,-1 // r10 = $0x0ffffffff = bitmask to be inserted
  146. subfic r6,r6,31 // hi := 31 - (hi mod 32) = shift count for later
  147. slw r10,r10,r5 // shift bitmask to clear bits below lo
  148. lwzux r5,r3,r4 // go to starting pos in set and load value
  149. // (lo is not necessary anymore)
  150. beq .Lset_range_hi // if bit lo and hi in same longint, keep
  151. // current mask and adjust for hi bit
  152. subic. r9,r9,4 // bit hi in next longint?
  153. or r5,r5,r10 // merge and
  154. stw r5,0(r3) // store current mask
  155. li r10,-1 // new mask
  156. lwzu r5,4(r3) // load next longint of set
  157. beq .Lset_range_hi // bit hi in this longint -> go to adjust for hi
  158. subi r3,r3,4
  159. .Lset_range_loop:
  160. subic. r9,r9,4
  161. stwu r10,4(r3) // fill longints in between with full mask
  162. bne .Lset_range_loop
  163. lwzu r5,4(r3) // load next value from set
  164. .Lset_range_hi: // in all cases, r3 here contains the address of
  165. // the longint which contains the hi bit and r4
  166. // contains this longint
  167. srw r9,r10,r6 // r9 := bitmask shl (31 - (hi mod 32)) =
  168. // bitmask with bits higher than hi cleared
  169. // (r8 = $0xffffffff unless the first beq was
  170. // taken)
  171. and r10,r9,r10 // combine lo and hi bitmasks for this longint
  172. or r5,r5,r10 // and combine with existing set
  173. stw r5,0(r3) // store to set
  174. .Lset_range_exit:
  175. end;
  176. {$define FPC_SYSTEM_HAS_FPC_SET_IN_BYTE}
  177. function fpc_set_in_byte(const p: fpc_normal_set; b : byte): boolean;compilerproc;assembler;[public,alias:'FPC_SET_IN_BYTE'];
  178. {
  179. tests if the element b is in the set p, the **zero** flag is cleared if it's present
  180. on entry: p in r3, b in r4
  181. }
  182. asm
  183. // get the index of the correct *dword* in the set
  184. // r0 := (r4 rotl(32-3)) and (0x0fffffff8)
  185. rlwinm r0,r4,31-3+1,3,31-2
  186. // load dword in which the bit has to be tested
  187. lwzx r3,r3,r0
  188. // r4 := 32 - r4 (no problem if r4 > 32, the rlwnm next does a mod 32)
  189. subfic r4,r4,32
  190. // r3 := (r3 shr (r4 mod 32)) and 1
  191. rlwnm r3,r3,r4,31,31
  192. end;
  193. {$define FPC_SYSTEM_HAS_FPC_SET_ADD_SETS}
  194. function fpc_set_add_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_ADD_SETS']; compilerproc;
  195. {
  196. adds set1 and set2 into set dest
  197. on entry: result in r3, set1 in r4, set2 in r5
  198. }
  199. asm
  200. { load the begin of the result set in the data cache }
  201. dcbtst 0,r3
  202. li r0,8
  203. mtctr r0
  204. subi r5,r5,4
  205. subi r4,r4,4
  206. subi r3,r3,4
  207. .LMADDSETS1:
  208. lwzu r0,4(r4)
  209. lwzu r10,4(r5)
  210. or r0,r0,r10
  211. stwu r0,4(r3)
  212. bdnz .LMADDSETS1
  213. end;
  214. {$define FPC_SYSTEM_HAS_FPC_SET_MUL_SETS}
  215. function fpc_set_mul_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_MUL_SETS']; compilerproc;
  216. {
  217. multiplies (takes common elements of) set1 and set2 result put in dest
  218. on entry: result in r3, set1 in r4, set2 in r5
  219. }
  220. asm
  221. { load the begin of the result set in the data cache }
  222. dcbtst 0,r3
  223. li r0,8
  224. mtctr r0
  225. subi r5,r5,4
  226. subi r4,r4,4
  227. subi r3,r3,4
  228. .LMMULSETS1:
  229. lwzu r0,4(r4)
  230. lwzu r10,4(r5)
  231. and r0,r0,r10
  232. stwu r0,4(r3)
  233. bdnz .LMMULSETS1
  234. end;
  235. {$define FPC_SYSTEM_HAS_FPC_SET_SUB_SETS}
  236. function fpc_set_sub_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SUB_SETS']; compilerproc;
  237. {
  238. computes the diff from set1 to set2 result in dest
  239. on entry: result in r3, set1 in r4, set2 in r5
  240. }
  241. asm
  242. { load the begin of the result set in the data cache }
  243. dcbtst 0,r3
  244. li r0,8
  245. mtctr r0
  246. subi r5,r5,4
  247. subi r4,r4,4
  248. subi r3,r3,4
  249. .LMSUBSETS1:
  250. lwzu r0,4(r4)
  251. lwzu r10,4(r5)
  252. andc r0,r0,r10
  253. stwu r0,4(r3)
  254. bdnz .LMSUBSETS1
  255. end;
  256. {$define FPC_SYSTEM_HAS_FPC_SET_SYMDIF_SETS}
  257. function fpc_set_symdif_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SYMDIF_SETS']; compilerproc;
  258. {
  259. computes the symetric diff from set1 to set2 result in dest
  260. on entry: result in r3, set1 in r4, set2 in r5
  261. }
  262. asm
  263. { load the begin of the result set in the data cache }
  264. dcbtst 0,r3
  265. li r0,8
  266. mtctr r0
  267. subi r5,r5,4
  268. subi r4,r4,4
  269. subi r3,r3,4
  270. .LMSYMDIFSETS1:
  271. lwzu r0,4(r4)
  272. lwzu r10,4(r5)
  273. xor r0,r0,r10
  274. stwu r0,4(r3)
  275. bdnz .LMSYMDIFSETS1
  276. end;
  277. {$define FPC_SYSTEM_HAS_FPC_SET_COMP_SETS}
  278. function fpc_set_comp_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_COMP_SETS']; compilerproc;
  279. {
  280. compares set1 and set2 zeroflag is set if they are equal
  281. on entry: set1 in r3, set2 in r4
  282. }
  283. asm
  284. li r0,8
  285. mtctr r0
  286. subi r3,r3,4
  287. subi r4,r4,4
  288. .LMCOMPSETS1:
  289. lwzu r0,4(r3)
  290. lwzu r10,4(r4)
  291. sub. r0,r0,r10
  292. bdnzt cr0*4+eq,.LMCOMPSETS1
  293. cntlzw r3,r0
  294. srwi. r3,r3,5
  295. end;
  296. {$define FPC_SYSTEM_HAS_FPC_SET_CONTAINS_SET}
  297. function fpc_set_contains_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_CONTAINS_SETS']; compilerproc;
  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. asm
  303. li r0,8
  304. mtctr r0
  305. subi r3,r3,4
  306. subi r4,r4,4
  307. .LMCONTAINSSETS1:
  308. lwzu r0,4(r3)
  309. lwzu r10,4(r4)
  310. { set1 and not(set2) = 0? }
  311. andc. r0,r0,r10
  312. bdnzt cr0*4+eq,.LMCONTAINSSETS1
  313. cntlzw r3,r0
  314. srwi. r3,r3,5
  315. end;
  316. {$ifdef LARGESETS}
  317. procedure do_set(p : pointer;b : word);assembler;[public,alias:'FPC_SET_SET_WORD'];
  318. {
  319. sets the element b in set p works for sets larger than 256 elements
  320. not yet use by the compiler so
  321. }
  322. asm
  323. pushl %eax
  324. movl p,%edi
  325. movw b,%ax
  326. andl $0xfff8,%eax
  327. shrl $3,%eax
  328. addl %eax,%edi
  329. movb 12(%ebp),%al
  330. andl $7,%eax
  331. btsl %eax,(%edi)
  332. popl %eax
  333. end;
  334. procedure do_in(p : pointer;b : word);assembler;[public,alias:'FPC_SET_IN_WORD'];
  335. {
  336. tests if the element b is in the set p the carryflag is set if it present
  337. works for sets larger than 256 elements
  338. }
  339. asm
  340. pushl %eax
  341. movl p,%edi
  342. movw b,%ax
  343. andl $0xfff8,%eax
  344. shrl $3,%eax
  345. addl %eax,%edi
  346. movb 12(%ebp),%al
  347. andl $7,%eax
  348. btl %eax,(%edi)
  349. popl %eax
  350. end;
  351. procedure add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_ADD_SETS_SIZE'];
  352. {
  353. adds set1 and set2 into set dest size is the number of bytes in the set
  354. }
  355. asm
  356. movl set1,%esi
  357. movl set2,%ebx
  358. movl dest,%edi
  359. movl size,%ecx
  360. .LMADDSETSIZES1:
  361. lodsl
  362. orl (%ebx),%eax
  363. stosl
  364. addl $4,%ebx
  365. decl %ecx
  366. jnz .LMADDSETSIZES1
  367. end;
  368. procedure mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_MUL_SETS_SIZE'];
  369. {
  370. multiplies (i.E. takes common elements of) set1 and set2 result put in
  371. dest size is the number of bytes in the set
  372. }
  373. asm
  374. movl set1,%esi
  375. movl set2,%ebx
  376. movl dest,%edi
  377. movl size,%ecx
  378. .LMMULSETSIZES1:
  379. lodsl
  380. andl (%ebx),%eax
  381. stosl
  382. addl $4,%ebx
  383. decl %ecx
  384. jnz .LMMULSETSIZES1
  385. end;
  386. procedure sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SUB_SETS_SIZE'];
  387. asm
  388. movl set1,%esi
  389. movl set2,%ebx
  390. movl dest,%edi
  391. movl size,%ecx
  392. .LMSUBSETSIZES1:
  393. lodsl
  394. movl (%ebx),%edx
  395. notl %edx
  396. andl %edx,%eax
  397. stosl
  398. addl $4,%ebx
  399. decl %ecx
  400. jnz .LMSUBSETSIZES1
  401. end;
  402. procedure sym_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SYMDIF_SETS_SIZE'];
  403. {
  404. computes the symetric diff from set1 to set2 result in dest
  405. }
  406. asm
  407. movl set1,%esi
  408. movl set2,%ebx
  409. movl dest,%edi
  410. movl size,%ecx
  411. .LMSYMDIFSETSIZE1:
  412. lodsl
  413. movl (%ebx),%edx
  414. xorl %edx,%eax
  415. stosl
  416. addl $4,%ebx
  417. decl %ecx
  418. jnz LMSYMDIFSETSIZE1
  419. end;
  420. procedure comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_SET_COMP_SETS_SIZE'];
  421. asm
  422. movl set1,%esi
  423. movl set2,%edi
  424. movl size,%ecx
  425. LMCOMPSETSIZES1:
  426. lodsl
  427. movl (%edi),%edx
  428. cmpl %edx,%eax
  429. jne LMCOMPSETSIZEEND
  430. addl $4,%edi
  431. decl %ecx
  432. jnz LMCOMPSETSIZES1
  433. { we are here only if the two sets are equal
  434. we have zero flag set, and that what is expected }
  435. LMCOMPSETSIZEEND:
  436. end;
  437. {$IfNDef NoSetInclusion}
  438. procedure contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_SET_CONTAINS_SETS'];
  439. {
  440. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  441. }
  442. asm
  443. movl set1,%esi
  444. movl set2,%edi
  445. movl size,%ecx
  446. LMCONTAINSSETS2:
  447. movl (%esi),%eax
  448. movl (%edi),%edx
  449. andl %eax,%edx
  450. cmpl %edx,%eax {set1 and set2 = set1?}
  451. jne LMCONTAINSSETEND2
  452. addl $4,%esi
  453. addl $4,%edi
  454. decl %ecx
  455. jnz LMCONTAINSSETS2
  456. { we are here only if set2 contains set1
  457. we have zero flag set, and that what is expected }
  458. LMCONTAINSSETEND2:
  459. end;
  460. {$EndIf NoSetInclusion}
  461. {$endif LARGESET}