set.inc 16 KB

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