set.inc 16 KB

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