set.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. std r0,8(r3)
  23. std r0,16(r3)
  24. std r0,24(r3)
  25. end;
  26. {$define FPC_SYSTEM_HAS_FPC_SET_CREATE_ELEMENT}
  27. { checked 2001/09/28 (JM) }
  28. function fpc_set_create_element(b : byte): fpc_normal_set;assembler;[public,alias:'FPC_SET_CREATE_ELEMENT']; compilerproc;
  29. {
  30. create a new set in p from an element b
  31. on entry: pointer to result in r3, b in r4
  32. }
  33. asm
  34. li r0,0
  35. stw r0,0(r3)
  36. stw r0,4(r3)
  37. stw r0,8(r3)
  38. stw r0,12(r3)
  39. stw r0,16(r3)
  40. stw r0,20(r3)
  41. stw r0,24(r3)
  42. stw r0,28(r3)
  43. // r0 := 1 shl r4[27-31] -> bit index in dword (rotate instructions
  44. // with count in register only consider lower 5 bits of this register)
  45. li r0,1
  46. rlwnm r0,r0,r4,0,31
  47. // get the index of the correct *dword* in the set
  48. // (((b div 8) div 4)*4= (b div 8) and not(3))
  49. // r5 := (r4 rotl(32-3)) and (0x01ffffff8)
  50. rlwinm r4,r4,31-3+1,3,31-2
  51. // store the result
  52. stwx r0,r3,r4
  53. end;
  54. {$define FPC_SYSTEM_HAS_FPC_SET_SET_BYTE}
  55. function fpc_set_set_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  56. {
  57. add the element b to the set pointed by p
  58. on entry: result in r3, source in r4, b in r5
  59. }
  60. asm
  61. // copy source to result
  62. lfd f0,0(r4)
  63. lfd f1,8(r4)
  64. lfd f2,16(r4)
  65. lfd f3,24(r4)
  66. stfd f0,0(r3)
  67. stfd f1,8(r3)
  68. stfd f2,16(r3)
  69. stfd f3,24(r3)
  70. // get the index of the correct *dword* in the set
  71. // r0 := (r5 rotl(32-3)) and (0x0fffffff8)
  72. rlwinm r0,r5,31-3+1,3,31-2
  73. // load dword in which the bit has to be set (and update r3 to this address)
  74. lwzux r4,r3,r0
  75. li r0,1
  76. // generate bit which has to be inserted
  77. // (can't use rlwimi, since that one only works for constants)
  78. rlwnm r5,r0,r5,0,31
  79. // insert it
  80. or r5,r4,r5
  81. // store result
  82. stw r5,0(r3)
  83. end;
  84. {$define FPC_SYSTEM_HAS_FPC_SET_UNSET_BYTE}
  85. function fpc_set_unset_byte(const source: fpc_normal_set; b : byte): fpc_normal_set;assembler; compilerproc;
  86. {
  87. suppresses the element b to the set pointed by p
  88. used for exclude(set,element)
  89. on entry: p in r3, b in r4
  90. }
  91. asm
  92. // copy source to result
  93. lfd f0,0(r4)
  94. lfd f1,8(r4)
  95. lfd f2,16(r4)
  96. lfd f3,24(r4)
  97. stfd f0,0(r3)
  98. stfd f1,8(r3)
  99. stfd f2,16(r3)
  100. stfd f3,24(r3)
  101. // get the index of the correct *dword* in the set
  102. // r0 := (r4 rotl(32-3)) and (0x0fffffff8)
  103. rlwinm r0,r5,31-3+1,3,31-2
  104. // load dword in which the bit has to be set (and update r3 to this address)
  105. lwzux r4,r3,r0
  106. li r0,1
  107. // generate bit which has to be removed
  108. rlwnm r5,r0,r5,0,31
  109. // remove it
  110. andc r5,r4,r5
  111. // store result
  112. stw r4,0(r3)
  113. end;
  114. {$define FPC_SYSTEM_HAS_FPC_SET_SET_RANGE}
  115. function fpc_set_set_range(const orgset: fpc_normal_set; l,h : byte): fpc_normal_set;assembler; compilerproc;
  116. {
  117. on entry: result in r3, l in r4, h in r5
  118. on entry: result in r3, ptr to orgset in r4, l in r5, h in r6
  119. }
  120. asm
  121. // copy source to result
  122. lfd f0,0(r4)
  123. lfd f1,8(r4)
  124. lfd f2,16(r4)
  125. lfd f3,24(r4)
  126. stfd f0,0(r3)
  127. stfd f1,8(r3)
  128. stfd f2,16(r3)
  129. stfd f3,24(r3)
  130. cmplw cr0,r5,r6
  131. bgt cr0,.Lset_range_exit
  132. rlwinm r4,r5,31-3+1,3,31-2 // divide by 8 to get starting and ending byte-
  133. { load the set the data cache }
  134. dcbtst r3,r4
  135. rlwinm r9,r6,31-3+1,3,31-2 // address and clear two lowest bits to get
  136. // start/end longint address
  137. sub. r9,r9,r4 // are bit lo and hi in the same longint?
  138. rlwinm r6,r6,0,31-5+1,31 // hi := hi mod 32 (= "hi and 31", but the andi
  139. // instr. only exists in flags modifying form)
  140. rlwinm r5,r5,0,31-5+1,31 // lo := lo mod 32 (= "lo 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. slw r10,r10,r5 // shift bitmask to clear bits below lo
  145. lwzux r5,r3,r4 // go to starting pos in set and load value
  146. // (lo is not necessary anymore)
  147. beq .Lset_range_hi // if bit lo and hi in same longint, keep
  148. // current mask and adjust for hi bit
  149. subic. r9,r9,4 // bit hi in next longint?
  150. or r5,r5,r10 // merge and
  151. stw r5,0(r3) // store current mask
  152. li r10,-1 // new mask
  153. lwzu r5,4(r3) // load next longint of set
  154. beq .Lset_range_hi // bit hi in this longint -> go to adjust for hi
  155. subi r3,r3,4
  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. srw r9,r10,r6 // r9 := 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,0(r3) // store to set
  171. .Lset_range_exit:
  172. end;
  173. {$define FPC_SYSTEM_HAS_FPC_SET_IN_BYTE}
  174. function fpc_set_in_byte(const p: fpc_normal_set; b : byte): boolean;compilerproc;assembler;[public,alias:'FPC_SET_IN_BYTE'];
  175. {
  176. tests if the element b is in the set p, the **zero** flag is cleared if it's present
  177. on entry: p in r3, b in r4
  178. }
  179. asm
  180. // get the index of the correct *dword* in the set
  181. // r0 := (r4 rotl(32-3)) and (0x0fffffff8)
  182. rlwinm r0,r4,31-3+1,3,31-2
  183. // load dword in which the bit has to be tested
  184. lwzx r3,r3,r0
  185. // r4 := 32 - r4 (no problem if r4 > 32, the rlwnm next does a mod 32)
  186. subfic r4,r4,32
  187. // r3 := (r3 shr (r4 mod 32)) and 1
  188. rlwnm r3,r3,r4,31,31
  189. end;
  190. {$define FPC_SYSTEM_HAS_FPC_SET_ADD_SETS}
  191. function fpc_set_add_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_ADD_SETS']; compilerproc;
  192. {
  193. adds set1 and set2 into set dest
  194. on entry: result in r3, set1 in r4, set2 in r5
  195. }
  196. asm
  197. { load the begin of the result set in the data cache }
  198. dcbtst 0,r3
  199. li r0,8
  200. mtctr r0
  201. subi r5,r5,4
  202. subi r4,r4,4
  203. subi r3,r3,4
  204. .LMADDSETS1:
  205. lwzu r0,4(r4)
  206. lwzu r10,4(r5)
  207. or r0,r0,r10
  208. stwu r0,4(r3)
  209. bdnz .LMADDSETS1
  210. end;
  211. {$define FPC_SYSTEM_HAS_FPC_SET_MUL_SETS}
  212. function fpc_set_mul_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_MUL_SETS']; compilerproc;
  213. {
  214. multiplies (takes common elements of) set1 and set2 result put in dest
  215. on entry: result in r3, set1 in r4, set2 in r5
  216. }
  217. asm
  218. { load the begin of the result set in the data cache }
  219. dcbtst 0,r3
  220. li r0,8
  221. mtctr r0
  222. subi r5,r5,4
  223. subi r4,r4,4
  224. subi r3,r3,4
  225. .LMMULSETS1:
  226. lwzu r0,4(r4)
  227. lwzu r10,4(r5)
  228. and r0,r0,r10
  229. stwu r0,4(r3)
  230. bdnz .LMMULSETS1
  231. end;
  232. {$define FPC_SYSTEM_HAS_FPC_SET_SUB_SETS}
  233. function fpc_set_sub_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SUB_SETS']; compilerproc;
  234. {
  235. computes the diff from set1 to set2 result in dest
  236. on entry: result in r3, set1 in r4, set2 in r5
  237. }
  238. asm
  239. { load the begin of the result set in the data cache }
  240. dcbtst 0,r3
  241. li r0,8
  242. mtctr r0
  243. subi r5,r5,4
  244. subi r4,r4,4
  245. subi r3,r3,4
  246. .LMSUBSETS1:
  247. lwzu r0,4(r4)
  248. lwzu r10,4(r5)
  249. andc r0,r0,r10
  250. stwu r0,4(r3)
  251. bdnz .LMSUBSETS1
  252. end;
  253. {$define FPC_SYSTEM_HAS_FPC_SET_SYMDIF_SETS}
  254. function fpc_set_symdif_sets(const set1,set2: fpc_normal_set): fpc_normal_set;assembler;[public,alias:'FPC_SET_SYMDIF_SETS']; compilerproc;
  255. {
  256. computes the symetric diff from set1 to set2 result in dest
  257. on entry: result in r3, set1 in r4, set2 in r5
  258. }
  259. asm
  260. { load the begin of the result set in the data cache }
  261. dcbtst 0,r3
  262. li r0,8
  263. mtctr r0
  264. subi r5,r5,4
  265. subi r4,r4,4
  266. subi r3,r3,4
  267. .LMSYMDIFSETS1:
  268. lwzu r0,4(r4)
  269. lwzu r10,4(r5)
  270. xor r0,r0,r10
  271. stwu r0,4(r3)
  272. bdnz .LMSYMDIFSETS1
  273. end;
  274. {$define FPC_SYSTEM_HAS_FPC_SET_COMP_SETS}
  275. function fpc_set_comp_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_COMP_SETS']; compilerproc;
  276. {
  277. compares set1 and set2 zeroflag is set if they are equal
  278. on entry: set1 in r3, set2 in r4
  279. }
  280. asm
  281. li r0,8
  282. mtctr r0
  283. subi r3,r3,4
  284. subi r4,r4,4
  285. .LMCOMPSETS1:
  286. lwzu r0,4(r3)
  287. lwzu r10,4(r4)
  288. sub. r0,r0,r10
  289. bdnzt cr0*4+eq,.LMCOMPSETS1
  290. cntlzw r3,r0
  291. srwi. r3,r3,5
  292. end;
  293. {$define FPC_SYSTEM_HAS_FPC_SET_CONTAINS_SET}
  294. function fpc_set_contains_sets(const set1,set2: fpc_normal_set): boolean;assembler;[public,alias:'FPC_SET_CONTAINS_SETS']; compilerproc;
  295. {
  296. on exit, zero flag is set if set1 <= set2 (set2 contains set1)
  297. on entry: set1 in r3, set2 in r4
  298. }
  299. asm
  300. li r0,8
  301. mtctr r0
  302. subi r3,r3,4
  303. subi r4,r4,4
  304. .LMCONTAINSSETS1:
  305. lwzu r0,4(r3)
  306. lwzu r10,4(r4)
  307. { set1 and not(set2) = 0? }
  308. andc. r0,r0,r10
  309. bdnzt cr0*4+eq,.LMCONTAINSSETS1
  310. cntlzw r3,r0
  311. srwi. r3,r3,5
  312. end;