set.inc 16 KB

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