ncgset.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
  4. Generate generic assembler for in set/case nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  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. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgset;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nset,cpubase,cgbase,cgobj,aasmbase,aasmtai,globals;
  23. type
  24. tcgsetelementnode = class(tsetelementnode)
  25. procedure pass_2;override;
  26. end;
  27. tcginnode = class(tinnode)
  28. procedure pass_2;override;
  29. protected
  30. {# Routine to test bitnumber in bitnumber register on value
  31. in value register. The __result register should be set
  32. to one if the bit is set, otherwise __result register
  33. should be set to zero.
  34. Should be overriden on processors which have specific
  35. instructions to do bit tests.
  36. }
  37. procedure emit_bit_test_reg_reg(list : taasmoutput;
  38. bitsize: tcgsize; bitnumber,value : tregister;
  39. ressize: tcgsize; res :tregister);virtual;
  40. end;
  41. tcgcasenode = class(tcasenode)
  42. {
  43. Emits the case node statement. Contrary to the intel
  44. 80x86 version, this version does not emit jump tables,
  45. because of portability problems.
  46. }
  47. procedure pass_2;override;
  48. protected
  49. with_sign : boolean;
  50. opsize : tcgsize;
  51. jmp_gt,jmp_lt,jmp_le : topcmp;
  52. { register with case expression }
  53. hregister,hregister2 : tregister;
  54. endlabel,elselabel : tasmlabel;
  55. { true, if we can omit the range check of the jump table }
  56. jumptable_no_range : boolean;
  57. { has the implementation jumptable support }
  58. min_label : tconstexprint;
  59. procedure optimizevalues(var max_linear_list:longint;var max_dist:cardinal);virtual;
  60. function has_jumptable : boolean;virtual;
  61. procedure genjumptable(hp : pcaserecord;min_,max_ : longint); virtual;
  62. procedure genlinearlist(hp : pcaserecord); virtual;
  63. procedure genlinearcmplist(hp : pcaserecord); virtual;
  64. procedure gentreejmp(p : pcaserecord);
  65. end;
  66. implementation
  67. uses
  68. globtype,systems,
  69. verbose,
  70. symconst,symdef,defutil,
  71. paramgr,
  72. pass_2,
  73. nbas,ncon,nflw,
  74. ncgutil,regvars,cpuinfo;
  75. {*****************************************************************************
  76. TCGSETELEMENTNODE
  77. *****************************************************************************}
  78. procedure tcgsetelementnode.pass_2;
  79. begin
  80. { load first value in 32bit register }
  81. secondpass(left);
  82. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  83. location_force_reg(exprasmlist,left.location,OS_32,false);
  84. { also a second value ? }
  85. if assigned(right) then
  86. begin
  87. secondpass(right);
  88. if codegenerror then
  89. exit;
  90. if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  91. location_force_reg(exprasmlist,right.location,OS_32,false);
  92. end;
  93. { we doesn't modify the left side, we check only the type }
  94. location_copy(location,left.location);
  95. end;
  96. {*****************************************************************************
  97. *****************************************************************************}
  98. {**********************************************************************}
  99. { Description: Emit operation to do a bit test, where the bitnumber }
  100. { to test is in the bitnumber register. The value to test against is }
  101. { located in the value register. }
  102. { WARNING: Bitnumber register value is DESTROYED! }
  103. { __Result register is set to 1, if the bit is set otherwise, __Result}
  104. { is set to zero. __RESULT register is also used as scratch. }
  105. {**********************************************************************}
  106. procedure tcginnode.emit_bit_test_reg_reg(list : taasmoutput;
  107. bitsize: tcgsize; bitnumber,value : tregister;
  108. ressize: tcgsize; res :tregister);
  109. begin
  110. { first make sure that the bit number is modulo 32 }
  111. { not necessary, since if it's > 31, we have a range error -> will }
  112. { be caught when range checking is on! (JM) }
  113. { cg.a_op_const_reg(list,OP_AND,31,bitnumber); }
  114. { rotate value register "bitnumber" bits to the right }
  115. cg.a_op_reg_reg(list,OP_SHR,bitsize,bitnumber,value);
  116. { extract the bit we want }
  117. cg.a_op_const_reg(list,OP_AND,bitsize,1,value);
  118. cg.a_load_reg_reg(list,bitsize,ressize,value,res);
  119. end;
  120. procedure tcginnode.pass_2;
  121. type
  122. Tsetpart=record
  123. range : boolean; {Part is a range.}
  124. start,stop : byte; {Start/stop when range; Stop=element when an element.}
  125. end;
  126. var
  127. l,l2,l3 : tasmlabel;
  128. adjustment : longint;
  129. href : treference;
  130. hr,hr2,hr3,
  131. pleftreg : tregister;
  132. setparts : array[1..8] of Tsetpart;
  133. opsize : tcgsize;
  134. genjumps,
  135. use_small,
  136. ranges : boolean;
  137. i,numparts : byte;
  138. function analizeset(const Aset:Tconstset;is_small:boolean):boolean;
  139. var
  140. compares,maxcompares:word;
  141. i:byte;
  142. begin
  143. analizeset:=false;
  144. ranges:=false;
  145. numparts:=0;
  146. compares:=0;
  147. { Lots of comparisions take a lot of time, so do not allow
  148. too much comparisions. 8 comparisions are, however, still
  149. smalller than emitting the set }
  150. if cs_littlesize in aktglobalswitches then
  151. maxcompares:=8
  152. else
  153. maxcompares:=5;
  154. { when smallset is possible allow only 3 compares the smallset
  155. code is for littlesize also smaller when more compares are used }
  156. if is_small then
  157. maxcompares:=3;
  158. for i:=0 to 255 do
  159. if i in Aset then
  160. begin
  161. if (numparts=0) or (i<>setparts[numparts].stop+1) then
  162. begin
  163. {Set element is a separate element.}
  164. inc(compares);
  165. if compares>maxcompares then
  166. exit;
  167. inc(numparts);
  168. setparts[numparts].range:=false;
  169. setparts[numparts].stop:=i;
  170. end
  171. else
  172. {Set element is part of a range.}
  173. if not setparts[numparts].range then
  174. begin
  175. {Transform an element into a range.}
  176. setparts[numparts].range:=true;
  177. setparts[numparts].start:=setparts[numparts].stop;
  178. setparts[numparts].stop:=i;
  179. ranges := true;
  180. { there's only one compare per range anymore. Only a }
  181. { sub is added, but that's much faster than a }
  182. { cmp/jcc combo so neglect its effect }
  183. { inc(compares);
  184. if compares>maxcompares then
  185. exit; }
  186. end
  187. else
  188. begin
  189. {Extend a range.}
  190. setparts[numparts].stop:=i;
  191. end;
  192. end;
  193. analizeset:=true;
  194. end;
  195. begin
  196. { We check first if we can generate jumps, this can be done
  197. because the resulttype.def is already set in firstpass }
  198. { check if we can use smallset operation using btl which is limited
  199. to 32 bits, the left side may also not contain higher values !! }
  200. use_small:=(tsetdef(right.resulttype.def).settype=smallset) and
  201. ((left.resulttype.def.deftype=orddef) and (torddef(left.resulttype.def).high<=32) or
  202. (left.resulttype.def.deftype=enumdef) and (tenumdef(left.resulttype.def).max<=32));
  203. { Can we generate jumps? Possible for all types of sets }
  204. genjumps:=(right.nodetype=setconstn) and
  205. analizeset(Tsetconstnode(right).value_set^,use_small);
  206. { calculate both operators }
  207. { the complex one first }
  208. firstcomplex(self);
  209. secondpass(left);
  210. { Only process the right if we are not generating jumps }
  211. if not genjumps then
  212. secondpass(right);
  213. if codegenerror then
  214. exit;
  215. { ofcourse not commutative }
  216. if nf_swaped in flags then
  217. swapleftright;
  218. { location is always LOC_JUMP }
  219. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  220. if genjumps then
  221. begin
  222. { allocate a register for the result }
  223. location.register := cg.getintregister(exprasmlist,location.size);
  224. { Get a label to jump to the end }
  225. objectlibrary.getlabel(l);
  226. { clear the register value, indicating result is FALSE }
  227. cg.a_load_const_reg(exprasmlist,location.size,0,location.register);
  228. opsize := def_cgsize(left.resulttype.def);
  229. { If register is used, use only lower 8 bits }
  230. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  231. begin
  232. { for ranges we always need a 32bit register, because then we }
  233. { use the register as base in a reference (JM) }
  234. if ranges then
  235. begin
  236. pleftreg:=cg.makeregsize(left.location.register,OS_INT);
  237. cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,pleftreg);
  238. if opsize <> OS_INT then
  239. cg.a_op_const_reg(exprasmlist,OP_AND,OS_INT,255,pleftreg);
  240. opsize := OS_INT;
  241. end
  242. else
  243. { otherwise simply use the lower 8 bits (no "and" }
  244. { necessary this way) (JM) }
  245. begin
  246. pleftreg:=cg.makeregsize(left.location.register,OS_8);
  247. opsize := OS_8;
  248. end;
  249. end
  250. else
  251. begin
  252. { load the value in a register }
  253. opsize := OS_INT;
  254. pleftreg:=cg.getintregister(exprasmlist,opsize);
  255. cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),opsize,left.location.reference,pleftreg);
  256. end;
  257. { how much have we already substracted from the x in the }
  258. { "x in [y..z]" expression }
  259. adjustment := 0;
  260. hr:=NR_NO;
  261. for i:=1 to numparts do
  262. if setparts[i].range then
  263. { use fact that a <= x <= b <=> cardinal(x-a) <= cardinal(b-a) }
  264. begin
  265. { is the range different from all legal values? }
  266. if (setparts[i].stop-setparts[i].start <> 255) then
  267. begin
  268. { yes, is the lower bound <> 0? }
  269. if (setparts[i].start <> 0) then
  270. { we're going to substract from the left register, }
  271. { so in case of a LOC_CREGISTER first move the value }
  272. { to edi (not done before because now we can do the }
  273. { move and substract in one instruction with LEA) }
  274. if (left.location.loc = LOC_CREGISTER) and
  275. (hr<>pleftreg) then
  276. begin
  277. cg.a_op_const_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg);
  278. hr:=cg.getintregister(exprasmlist,OS_INT);
  279. cg.a_load_reg_reg(exprasmlist,opsize,OS_INT,pleftreg,hr);
  280. pleftreg:=hr;
  281. opsize := OS_INT;
  282. end
  283. else
  284. begin
  285. { otherwise, the value is already in a register }
  286. { that can be modified }
  287. cg.a_op_const_reg(exprasmlist,OP_SUB,opsize,
  288. setparts[i].start-adjustment,pleftreg)
  289. end;
  290. { new total value substracted from x: }
  291. { adjustment + (setparts[i].start - adjustment) }
  292. adjustment := setparts[i].start;
  293. { check if result < b-a+1 (not "result <= b-a", since }
  294. { we need a carry in case the element is in the range }
  295. { (this will never overflow since we check at the }
  296. { beginning whether stop-start <> 255) }
  297. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_B,
  298. setparts[i].stop-setparts[i].start+1,pleftreg,l);
  299. end
  300. else
  301. { if setparts[i].start = 0 and setparts[i].stop = 255, }
  302. { it's always true since "in" is only allowed for bytes }
  303. begin
  304. cg.a_jmp_always(exprasmlist,l);
  305. end;
  306. end
  307. else
  308. begin
  309. { Emit code to check if left is an element }
  310. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,
  311. setparts[i].stop-adjustment,pleftreg,l);
  312. end;
  313. { To compensate for not doing a second pass }
  314. right.location.reference.symbol:=nil;
  315. objectlibrary.getlabel(l3);
  316. cg.a_jmp_always(exprasmlist,l3);
  317. { Now place the end label if IN success }
  318. cg.a_label(exprasmlist,l);
  319. { result register is 1 }
  320. cg.a_load_const_reg(exprasmlist,location.size,1,location.register);
  321. { in case value is not found }
  322. cg.a_label(exprasmlist,l3);
  323. case left.location.loc of
  324. LOC_CREGISTER :
  325. cg.ungetregister(exprasmlist,pleftreg);
  326. LOC_REGISTER :
  327. cg.ungetregister(exprasmlist,pleftreg);
  328. else
  329. begin
  330. reference_release(exprasmlist,left.location.reference);
  331. cg.ungetregister(exprasmlist,pleftreg);
  332. end;
  333. end;
  334. end
  335. else
  336. {*****************************************************************}
  337. { NO JUMP TABLE GENERATION }
  338. {*****************************************************************}
  339. begin
  340. { We will now generated code to check the set itself, no jmps,
  341. handle smallsets separate, because it allows faster checks }
  342. if use_small then
  343. begin
  344. {**************************** SMALL SET **********************}
  345. if left.nodetype=ordconstn then
  346. begin
  347. location_force_reg(exprasmlist,right.location,OS_32,true);
  348. { first SHR the register }
  349. cg.a_op_const_reg(exprasmlist,OP_SHR,OS_32,tordconstnode(left).value and 31,right.location.register);
  350. { then extract the lowest bit }
  351. cg.a_op_const_reg(exprasmlist,OP_AND,OS_32,1,right.location.register);
  352. location.register:=cg.getintregister(exprasmlist,location.size);
  353. cg.a_load_reg_reg(exprasmlist,OS_32,location.size,right.location.register,location.register);
  354. end
  355. else
  356. begin
  357. location_force_reg(exprasmlist,left.location,OS_32,false);
  358. location_force_reg(exprasmlist,right.location,OS_32,true);
  359. { allocate a register for the result }
  360. location.register:=cg.getintregister(exprasmlist,location.size);
  361. { emit bit test operation }
  362. emit_bit_test_reg_reg(exprasmlist,right.location.size,left.location.register,
  363. right.location.register,location.size,location.register);
  364. end;
  365. location_release(exprasmlist,left.location);
  366. location_release(exprasmlist,right.location);
  367. end
  368. else
  369. {************************** NOT SMALL SET ********************}
  370. begin
  371. if right.location.loc=LOC_CONSTANT then
  372. begin
  373. { can it actually occur currently? CEC }
  374. { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
  375. { note: this code assumes that left in [0..255], which is a valid }
  376. { assumption (other cases will be caught by range checking) (JM) }
  377. { load left in register }
  378. location_force_reg(exprasmlist,left.location,OS_32,true);
  379. if left.location.loc = LOC_CREGISTER then
  380. hr := cg.getintregister(exprasmlist,OS_32)
  381. else
  382. hr := left.location.register;
  383. { load right in register }
  384. hr2:=cg.getintregister(exprasmlist,OS_32);
  385. cg.a_load_const_reg(exprasmlist,OS_32,right.location.value,hr2);
  386. { emit bit test operation }
  387. emit_bit_test_reg_reg(exprasmlist,OS_32,left.location.register,hr2,OS_32,hr2);
  388. { if left > 31 then hr := 0 else hr := $ffffffff }
  389. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_32,32,left.location.register,hr);
  390. cg.a_op_const_reg(exprasmlist,OP_SAR,OS_32,31,hr);
  391. { free registers }
  392. cg.ungetregister(exprasmlist,hr2);
  393. if (left.location.loc in [LOC_CREGISTER]) then
  394. cg.ungetregister(exprasmlist,hr)
  395. else
  396. cg.ungetregister(exprasmlist,left.location.register);
  397. { if left > 31, then result := 0 else result := result of bit test }
  398. cg.a_op_reg_reg(exprasmlist,OP_AND,OS_32,hr,hr2);
  399. { allocate a register for the result }
  400. location.register := cg.getintregister(exprasmlist,location.size);
  401. cg.a_load_reg_reg(exprasmlist,OS_32,location.size,hr2,location.register);
  402. end { of right.location.loc=LOC_CONSTANT }
  403. { do search in a normal set which could have >32 elementsm
  404. but also used if the left side contains higher values > 32 }
  405. else if left.nodetype=ordconstn then
  406. begin
  407. { use location.register as scratch register here }
  408. if (target_info.endian = endian_little) then
  409. inc(right.location.reference.offset,tordconstnode(left).value shr 3)
  410. else
  411. { adjust for endianess differences }
  412. inc(right.location.reference.offset,(tordconstnode(left).value shr 3) xor 3);
  413. { allocate a register for the result }
  414. location.register := cg.getintregister(exprasmlist,location.size);
  415. cg.a_load_ref_reg(exprasmlist,OS_8,location.size,right.location.reference, location.register);
  416. location_release(exprasmlist,right.location);
  417. cg.a_op_const_reg(exprasmlist,OP_SHR,location.size,tordconstnode(left).value and 7,
  418. location.register);
  419. cg.a_op_const_reg(exprasmlist,OP_AND,location.size,1,location.register);
  420. end
  421. else
  422. begin
  423. location_force_reg(exprasmlist,left.location,OS_32,true);
  424. pleftreg := left.location.register;
  425. location_freetemp(exprasmlist,left.location);
  426. cg.a_op_const_reg(exprasmlist,OP_SHR,OS_32,5,pleftreg);
  427. hr := cg.getaddressregister(exprasmlist);
  428. cg.a_load_reg_reg(exprasmlist,OS_32,OS_ADDR,pleftreg,hr);
  429. cg.a_op_const_reg(exprasmlist,OP_SHL,OS_ADDR,2,hr);
  430. href := right.location.reference;
  431. if (href.base = NR_NO) then
  432. href.base := hr
  433. else if (right.location.reference.index = NR_NO) then
  434. href.index := hr
  435. else
  436. begin
  437. reference_release(exprasmlist,href);
  438. hr2 := cg.getaddressregister(exprasmlist);
  439. cg.a_loadaddr_ref_reg(exprasmlist,href, hr2);
  440. reference_reset_base(href,hr2,0);
  441. href.index := hr;
  442. end;
  443. reference_release(exprasmlist,href);
  444. { allocate a register for the result }
  445. hr := cg.getintregister(exprasmlist,OS_32);
  446. cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,href,hr);
  447. cg.a_op_const_reg(exprasmlist,OP_AND,OS_32,31,pleftreg);
  448. cg.a_op_reg_reg(exprasmlist,OP_SHR,OS_32,pleftreg,hr);
  449. cg.ungetregister(exprasmlist,pleftreg);
  450. cg.a_op_const_reg(exprasmlist,OP_AND,OS_32,1,hr);
  451. location.register := cg.getintregister(exprasmlist,location.size);
  452. cg.a_load_reg_reg(exprasmlist,OS_32,location.size,hr,location.register);
  453. cg.ungetregister(exprasmlist,hr);
  454. end;
  455. end;
  456. end;
  457. location_freetemp(exprasmlist,right.location);
  458. end;
  459. {*****************************************************************************
  460. TCGCASENODE
  461. *****************************************************************************}
  462. procedure tcgcasenode.optimizevalues(var max_linear_list:longint;var max_dist:cardinal);
  463. begin
  464. { no changes by default }
  465. end;
  466. function tcgcasenode.has_jumptable : boolean;
  467. begin
  468. { No jumptable support in the default implementation }
  469. has_jumptable:=false;
  470. end;
  471. procedure tcgcasenode.genjumptable(hp : pcaserecord;min_,max_ : longint);
  472. begin
  473. internalerror(200209161);
  474. end;
  475. procedure tcgcasenode.genlinearlist(hp : pcaserecord);
  476. var
  477. first : boolean;
  478. last : TConstExprInt;
  479. scratch_reg: tregister;
  480. procedure genitem(t : pcaserecord);
  481. procedure gensub(value:longint);
  482. begin
  483. { here, since the sub and cmp are separate we need
  484. to move the result before subtract to a help
  485. register.
  486. }
  487. cg.a_load_reg_reg(exprasmlist, opsize, opsize, hregister, scratch_reg);
  488. cg.a_op_const_reg(exprasmlist, OP_SUB, opsize, value, hregister);
  489. end;
  490. begin
  491. if assigned(t^.less) then
  492. genitem(t^.less);
  493. { need we to test the first value }
  494. if first and (t^._low>get_min_value(left.resulttype.def)) then
  495. begin
  496. cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aword(t^._low),hregister,elselabel);
  497. end;
  498. if t^._low=t^._high then
  499. begin
  500. if t^._low-last=0 then
  501. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,0,hregister,t^.statement)
  502. else
  503. begin
  504. gensub(longint(t^._low-last));
  505. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,aword(t^._low-last),scratch_reg,t^.statement);
  506. end;
  507. last:=t^._low;
  508. end
  509. else
  510. begin
  511. { it begins with the smallest label, if the value }
  512. { is even smaller then jump immediately to the }
  513. { ELSE-label }
  514. if first then
  515. begin
  516. { have we to ajust the first value ? }
  517. if (t^._low>get_min_value(left.resulttype.def)) then
  518. gensub(longint(t^._low));
  519. end
  520. else
  521. begin
  522. { if there is no unused label between the last and the }
  523. { present label then the lower limit can be checked }
  524. { immediately. else check the range in between: }
  525. gensub(longint(t^._low-last));
  526. cg.a_cmp_const_reg_label(exprasmlist, opsize,jmp_lt,aword(t^._low-last),scratch_reg,elselabel);
  527. end;
  528. gensub(longint(t^._high-t^._low));
  529. cg.a_cmp_const_reg_label(exprasmlist, opsize,jmp_le,aword(t^._high-t^._low),scratch_reg,t^.statement);
  530. last:=t^._high;
  531. end;
  532. first:=false;
  533. if assigned(t^.greater) then
  534. genitem(t^.greater);
  535. end;
  536. begin
  537. { do we need to generate cmps? }
  538. if (with_sign and (min_label<0)) then
  539. genlinearcmplist(hp)
  540. else
  541. begin
  542. last:=0;
  543. first:=true;
  544. scratch_reg:=cg.getintregister(exprasmlist,opsize);
  545. genitem(hp);
  546. cg.ungetregister(exprasmlist,scratch_reg);
  547. cg.a_jmp_always(exprasmlist,elselabel);
  548. end;
  549. end;
  550. procedure tcgcasenode.genlinearcmplist(hp : pcaserecord);
  551. var
  552. first : boolean;
  553. last : TConstExprInt;
  554. procedure genitem(t : pcaserecord);
  555. var
  556. l1 : tasmlabel;
  557. begin
  558. if assigned(t^.less) then
  559. genitem(t^.less);
  560. if t^._low=t^._high then
  561. begin
  562. if opsize in [OS_S64,OS_64] then
  563. begin
  564. objectlibrary.getlabel(l1);
  565. {$ifdef Delphi}
  566. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_NE, hi((t^._low)),hregister2,l1);
  567. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_EQ, lo((t^._low)),hregister, t^.statement);
  568. {$else}
  569. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_NE, aword(hi(int64(t^._low))),hregister2,l1);
  570. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_EQ, aword(lo(int64(t^._low))),hregister, t^.statement);
  571. {$endif}
  572. cg.a_label(exprasmlist,l1);
  573. end
  574. else
  575. begin
  576. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ, aword(t^._low),hregister, t^.statement);
  577. end;
  578. { Reset last here, because we've only checked for one value and need to compare
  579. for the next range both the lower and upper bound }
  580. last:=0;
  581. end
  582. else
  583. begin
  584. { it begins with the smallest label, if the value }
  585. { is even smaller then jump immediately to the }
  586. { ELSE-label }
  587. if first or (t^._low-last>1) then
  588. begin
  589. if opsize in [OS_64,OS_S64] then
  590. begin
  591. objectlibrary.getlabel(l1);
  592. {$ifdef Delphi}
  593. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aword(hi((t^._low))),
  594. hregister2, elselabel);
  595. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aword(hi((t^._low))),
  596. hregister2, l1);
  597. { the comparisation of the low dword must be always unsigned! }
  598. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_B, aword(lo((t^._low))), hregister, elselabel);
  599. {$else}
  600. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aword(hi(int64(t^._low))),
  601. hregister2, elselabel);
  602. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aword(hi(int64(t^._low))),
  603. hregister2, l1);
  604. { the comparisation of the low dword must be always unsigned! }
  605. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_B, aword(lo(int64(t^._low))), hregister, elselabel);
  606. {$endif}
  607. cg.a_label(exprasmlist,l1);
  608. end
  609. else
  610. begin
  611. cg.a_cmp_const_reg_label(exprasmlist, opsize, jmp_lt, aword(t^._low), hregister,
  612. elselabel);
  613. end;
  614. end;
  615. if opsize in [OS_S64,OS_64] then
  616. begin
  617. objectlibrary.getlabel(l1);
  618. {$ifdef Delphi}
  619. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aword(hi(t^._high)), hregister2,
  620. t^.statement);
  621. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aword(hi(t^._high)), hregister2,
  622. l1);
  623. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_BE, aword(lo(t^._high)), hregister, t^.statement);
  624. {$else}
  625. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aword(hi(int64(t^._high))), hregister2,
  626. t^.statement);
  627. cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aword(hi(int64(t^._high))), hregister2,
  628. l1);
  629. cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_BE, aword(lo(int64(t^._high))), hregister, t^.statement);
  630. {$endif}
  631. cg.a_label(exprasmlist,l1);
  632. end
  633. else
  634. begin
  635. cg.a_cmp_const_reg_label(exprasmlist, opsize, jmp_le, aword(t^._high), hregister, t^.statement);
  636. end;
  637. last:=t^._high;
  638. end;
  639. first:=false;
  640. if assigned(t^.greater) then
  641. genitem(t^.greater);
  642. end;
  643. begin
  644. last:=0;
  645. first:=true;
  646. genitem(hp);
  647. cg.a_jmp_always(exprasmlist,elselabel);
  648. end;
  649. procedure tcgcasenode.gentreejmp(p : pcaserecord);
  650. var
  651. lesslabel,greaterlabel : tasmlabel;
  652. begin
  653. cg.a_label(exprasmlist,p^._at);
  654. { calculate labels for left and right }
  655. if (p^.less=nil) then
  656. lesslabel:=elselabel
  657. else
  658. lesslabel:=p^.less^._at;
  659. if (p^.greater=nil) then
  660. greaterlabel:=elselabel
  661. else
  662. greaterlabel:=p^.greater^._at;
  663. { calculate labels for left and right }
  664. { no range label: }
  665. if p^._low=p^._high then
  666. begin
  667. if greaterlabel=lesslabel then
  668. begin
  669. cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_NE,p^._low,hregister, lesslabel);
  670. end
  671. else
  672. begin
  673. cg.a_cmp_const_reg_label(exprasmlist,opsize, jmp_lt,p^._low,hregister, lesslabel);
  674. cg.a_cmp_const_reg_label(exprasmlist,opsize, jmp_gt,p^._low,hregister, greaterlabel);
  675. end;
  676. cg.a_jmp_always(exprasmlist,p^.statement);
  677. end
  678. else
  679. begin
  680. cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,p^._low, hregister, lesslabel);
  681. cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,p^._high,hregister, greaterlabel);
  682. cg.a_jmp_always(exprasmlist,p^.statement);
  683. end;
  684. if assigned(p^.less) then
  685. gentreejmp(p^.less);
  686. if assigned(p^.greater) then
  687. gentreejmp(p^.greater);
  688. end;
  689. procedure ReLabel(var p:tasmsymbol);
  690. begin
  691. if p.defbind = AB_LOCAL then
  692. begin
  693. if not assigned(p.altsymbol) then
  694. objectlibrary.GenerateAltSymbol(p);
  695. p:=p.altsymbol;
  696. p.increfs;
  697. end;
  698. end;
  699. procedure relabelcaserecord(p : pcaserecord);
  700. begin
  701. Relabel(p^.statement);
  702. Relabel(p^._at);
  703. if assigned(p^.greater) then
  704. relabelcaserecord(p^.greater);
  705. if assigned(p^.less) then
  706. relabelcaserecord(p^.less);
  707. end;
  708. procedure tcgcasenode.pass_2;
  709. var
  710. lv,hv,
  711. max_label: tconstexprint;
  712. labels : longint;
  713. max_linear_list : longint;
  714. otl, ofl: tasmlabel;
  715. isjump : boolean;
  716. max_dist,
  717. dist : cardinal;
  718. hp : tstatementnode;
  719. begin
  720. location_reset(location,LOC_VOID,OS_NO);
  721. { Relabel for inlining? }
  722. if inlining_procedure and assigned(nodes) then
  723. begin
  724. objectlibrary.CreateUsedAsmSymbolList;
  725. relabelcaserecord(nodes);
  726. end;
  727. objectlibrary.getlabel(endlabel);
  728. objectlibrary.getlabel(elselabel);
  729. with_sign:=is_signed(left.resulttype.def);
  730. if with_sign then
  731. begin
  732. jmp_gt:=OC_GT;
  733. jmp_lt:=OC_LT;
  734. jmp_le:=OC_LTE;
  735. end
  736. else
  737. begin
  738. jmp_gt:=OC_A;
  739. jmp_lt:=OC_B;
  740. jmp_le:=OC_BE;
  741. end;
  742. { save current truelabel and falselabel }
  743. isjump:=false;
  744. if left.location.loc=LOC_JUMP then
  745. begin
  746. otl:=truelabel;
  747. objectlibrary.getlabel(truelabel);
  748. ofl:=falselabel;
  749. objectlibrary.getlabel(falselabel);
  750. isjump:=true;
  751. end;
  752. secondpass(left);
  753. { determines the size of the operand }
  754. opsize:=def_cgsize(left.resulttype.def);
  755. { copy the case expression to a register }
  756. location_force_reg(exprasmlist,left.location,opsize,false);
  757. if opsize in [OS_S64,OS_64] then
  758. begin
  759. hregister:=left.location.registerlow;
  760. hregister2:=left.location.registerhigh;
  761. end
  762. else
  763. hregister:=left.location.register;
  764. if isjump then
  765. begin
  766. truelabel:=otl;
  767. falselabel:=ofl;
  768. end;
  769. { we need the min_label always to choose between }
  770. { cmps and subs/decs }
  771. min_label:=case_get_min(nodes);
  772. {$ifdef OLDREGVARS}
  773. load_all_regvars(exprasmlist);
  774. {$endif OLDREGVARS}
  775. { now generate the jumps }
  776. if opsize in [OS_64,OS_S64] then
  777. genlinearcmplist(nodes)
  778. else
  779. begin
  780. if cs_optimize in aktglobalswitches then
  781. begin
  782. { procedures are empirically passed on }
  783. { consumption can also be calculated }
  784. { but does it pay on the different }
  785. { processors? }
  786. { moreover can the size only be appro- }
  787. { ximated as it is not known if rel8, }
  788. { rel16 or rel32 jumps are used }
  789. max_label:=case_get_max(nodes);
  790. labels:=case_count_labels(nodes);
  791. { can we omit the range check of the jump table ? }
  792. getrange(left.resulttype.def,lv,hv);
  793. jumptable_no_range:=(lv=min_label) and (hv=max_label);
  794. { hack a little bit, because the range can be greater }
  795. { than the positive range of a longint }
  796. if (min_label<0) and (max_label>0) then
  797. begin
  798. if min_label=TConstExprInt($80000000) then
  799. dist:=Cardinal(max_label)+Cardinal($80000000)
  800. else
  801. dist:=Cardinal(max_label)+Cardinal(-min_label)
  802. end
  803. else
  804. dist:=max_label-min_label;
  805. { optimize for size ? }
  806. if cs_littlesize in aktglobalswitches then
  807. begin
  808. if (has_jumptable) and
  809. not((labels<=2) or
  810. ((max_label-min_label)<0) or
  811. ((max_label-min_label)>3*labels)) then
  812. begin
  813. { if the labels less or more a continuum then }
  814. genjumptable(nodes,min_label,max_label);
  815. end
  816. else
  817. begin
  818. { a linear list is always smaller than a jump tree }
  819. genlinearlist(nodes);
  820. end;
  821. end
  822. else
  823. begin
  824. max_dist:=4*cardinal(labels);
  825. if jumptable_no_range then
  826. max_linear_list:=4
  827. else
  828. max_linear_list:=2;
  829. { allow processor specific values }
  830. optimizevalues(max_linear_list,max_dist);
  831. if (labels<=max_linear_list) then
  832. genlinearlist(nodes)
  833. else
  834. begin
  835. if (has_jumptable) and
  836. (dist<max_dist) then
  837. genjumptable(nodes,min_label,max_label)
  838. else
  839. begin
  840. {
  841. This one expects that the case labels are a
  842. perfectly balanced tree, which is not the case
  843. very often -> generates really bad code (JM)
  844. if labels>16 then
  845. gentreejmp(nodes)
  846. else
  847. }
  848. genlinearlist(nodes);
  849. end;
  850. end;
  851. end;
  852. end
  853. else
  854. { it's always not bad }
  855. genlinearlist(nodes);
  856. end;
  857. cg.ungetregister(exprasmlist,hregister);
  858. { now generate the instructions }
  859. hp:=tstatementnode(right);
  860. while assigned(hp) do
  861. begin
  862. { relabel when inlining }
  863. if inlining_procedure then
  864. begin
  865. if hp.left.nodetype<>labeln then
  866. internalerror(200211261);
  867. Relabel(tlabelnode(hp.left).labelnr);
  868. end;
  869. secondpass(hp.left);
  870. { don't come back to case line }
  871. aktfilepos:=exprasmList.getlasttaifilepos^;
  872. {$ifdef OLDREGVARS}
  873. load_all_regvars(exprasmlist);
  874. {$endif OLDREGVARS}
  875. cg.a_jmp_always(exprasmlist,endlabel);
  876. hp:=tstatementnode(hp.right);
  877. end;
  878. cg.a_label(exprasmlist,elselabel);
  879. { ...and the else block }
  880. if assigned(elseblock) then
  881. begin
  882. secondpass(elseblock);
  883. {$ifdef OLDREGVARS}
  884. load_all_regvars(exprasmlist);
  885. {$endif OLDREGVARS}
  886. end;
  887. cg.a_label(exprasmlist,endlabel);
  888. { Remove relabels for inlining }
  889. if inlining_procedure and
  890. assigned(nodes) then
  891. begin
  892. { restore used symbols }
  893. objectlibrary.UsedAsmSymbolListResetAltSym;
  894. objectlibrary.DestroyUsedAsmSymbolList;
  895. end;
  896. end;
  897. begin
  898. csetelementnode:=tcgsetelementnode;
  899. cinnode:=tcginnode;
  900. ccasenode:=tcgcasenode;
  901. end.
  902. {
  903. $Log$
  904. Revision 1.56 2004-01-31 17:45:17 peter
  905. * Change several $ifdef i386 to x86
  906. * Change several OS_32 to OS_INT/OS_ADDR
  907. Revision 1.55 2004/01/28 15:36:46 florian
  908. * fixed another couple of arm bugs
  909. Revision 1.54 2003/12/09 19:14:50 jonas
  910. * fixed and optimized in-node with constant smallset
  911. * some register usage optimisations.
  912. Revision 1.53 2003/11/10 19:10:31 peter
  913. * fixed range compare when the last value was an equal
  914. compare. The compare for the lower range was skipped
  915. Revision 1.52 2003/10/17 14:38:32 peter
  916. * 64k registers supported
  917. * fixed some memory leaks
  918. Revision 1.51 2003/10/10 17:48:13 peter
  919. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  920. * tregisteralloctor renamed to trgobj
  921. * removed rgobj from a lot of units
  922. * moved location_* and reference_* to cgobj
  923. * first things for mmx register allocation
  924. Revision 1.50 2003/10/09 21:31:37 daniel
  925. * Register allocator splitted, ans abstract now
  926. Revision 1.49 2003/10/01 20:34:48 peter
  927. * procinfo unit contains tprocinfo
  928. * cginfo renamed to cgbase
  929. * moved cgmessage to verbose
  930. * fixed ppc and sparc compiles
  931. Revision 1.48 2003/09/03 15:55:01 peter
  932. * NEWRA branch merged
  933. Revision 1.47.2.1 2003/08/29 17:28:59 peter
  934. * next batch of updates
  935. Revision 1.47 2003/08/20 20:29:06 daniel
  936. * Some more R_NO changes
  937. * Preventive code to loadref added
  938. Revision 1.46 2003/07/23 11:02:53 jonas
  939. * final (?) fix to in-code
  940. Revision 1.45 2003/07/20 18:03:27 jonas
  941. * fixed bug in tcginnode.pass_2
  942. Revision 1.44 2003/07/06 14:28:04 jonas
  943. * fixed register leak
  944. * changed a couple of case-statements to location_force_reg()
  945. Revision 1.43 2003/06/12 22:09:54 jonas
  946. * tcginnode.pass_2 doesn't call a helper anymore in any case
  947. * fixed ungetregisterfpu compilation problems
  948. Revision 1.42 2003/06/08 16:03:22 jonas
  949. - disabled gentreejmp for now, it expects that the case labels are
  950. ordered as a perfectly balanced tree, while they are often a linked
  951. list -> generates extremely bad code
  952. Revision 1.41 2003/06/07 18:57:04 jonas
  953. + added freeintparaloc
  954. * ppc get/freeintparaloc now check whether the parameter regs are
  955. properly allocated/deallocated (and get an extra list para)
  956. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  957. * fixed lot of missing pi_do_call's
  958. Revision 1.40 2003/06/03 21:11:09 peter
  959. * cg.a_load_* get a from and to size specifier
  960. * makeregsize only accepts newregister
  961. * i386 uses generic tcgnotnode,tcgunaryminus
  962. Revision 1.39 2003/06/01 21:38:06 peter
  963. * getregisterfpu size parameter added
  964. * op_const_reg size parameter added
  965. * sparc updates
  966. Revision 1.38 2003/05/30 23:57:08 peter
  967. * more sparc cleanup
  968. * accumulator removed, splitted in function_return_reg (called) and
  969. function_result_reg (caller)
  970. Revision 1.37 2003/05/30 23:49:18 jonas
  971. * a_load_loc_reg now has an extra size parameter for the destination
  972. register (properly fixes what I worked around in revision 1.106 of
  973. ncgutil.pas)
  974. Revision 1.36 2003/05/24 19:48:49 jonas
  975. * fixed tcginnode endian bug again, but correcty this time :)
  976. Revision 1.35 2003/05/23 21:10:50 florian
  977. * fixed sparc compiler compilation
  978. Revision 1.34 2003/05/23 19:52:28 jonas
  979. * corrected fix for endian differences in tcginnode
  980. Revision 1.33 2003/05/17 19:17:35 jonas
  981. * fixed size setting of result location of innodes
  982. Revision 1.32 2003/05/01 12:26:50 jonas
  983. * fixed endian issue in inlined in-test for smallsets
  984. * pass the address of normalsets to fpc_set_in_set_byte instead of the
  985. contents of the first 4 bytes
  986. Revision 1.31 2003/04/25 08:25:26 daniel
  987. * Ifdefs around a lot of calls to cleartempgen
  988. * Fixed registers that are allocated but not freed in several nodes
  989. * Tweak to register allocator to cause less spills
  990. * 8-bit registers now interfere with esi,edi and ebp
  991. Compiler can now compile rtl successfully when using new register
  992. allocator
  993. Revision 1.30 2003/04/22 23:50:23 peter
  994. * firstpass uses expectloc
  995. * checks if there are differences between the expectloc and
  996. location.loc from secondpass in EXTDEBUG
  997. Revision 1.29 2003/04/22 14:33:38 peter
  998. * removed some notes/hints
  999. Revision 1.28 2003/04/22 12:45:58 florian
  1000. * fixed generic in operator code
  1001. + added debug code to check if all scratch registers are released
  1002. Revision 1.27 2003/04/22 10:09:35 daniel
  1003. + Implemented the actual register allocator
  1004. + Scratch registers unavailable when new register allocator used
  1005. + maybe_save/maybe_restore unavailable when new register allocator used
  1006. Revision 1.26 2003/02/19 22:00:14 daniel
  1007. * Code generator converted to new register notation
  1008. - Horribily outdated todo.txt removed
  1009. Revision 1.25 2003/01/08 18:43:56 daniel
  1010. * Tregister changed into a record
  1011. Revision 1.24 2002/11/27 02:37:13 peter
  1012. * case statement inlining added
  1013. * fixed inlining of write()
  1014. * switched statementnode left and right parts so the statements are
  1015. processed in the correct order when getcopy is used. This is
  1016. required for tempnodes
  1017. Revision 1.23 2002/11/25 17:43:18 peter
  1018. * splitted defbase in defutil,symutil,defcmp
  1019. * merged isconvertable and is_equal into compare_defs(_ext)
  1020. * made operator search faster by walking the list only once
  1021. Revision 1.22 2002/10/05 12:43:25 carl
  1022. * fixes for Delphi 6 compilation
  1023. (warning : Some features do not work under Delphi)
  1024. Revision 1.21 2002/10/03 21:31:10 carl
  1025. * range check error fixes
  1026. Revision 1.20 2002/09/17 18:54:03 jonas
  1027. * a_load_reg_reg() now has two size parameters: source and dest. This
  1028. allows some optimizations on architectures that don't encode the
  1029. register size in the register name.
  1030. Revision 1.19 2002/09/16 18:08:26 peter
  1031. * fix last optimization in genlinearlist, detected by bug tw1066
  1032. * use generic casenode.pass2 routine and override genlinearlist
  1033. * add jumptable support to generic casenode, by default there is
  1034. no jumptable support
  1035. Revision 1.18 2002/08/15 15:11:53 carl
  1036. * oldset define is now correct for all cpu's except i386
  1037. * correct compilation problems because of the above
  1038. Revision 1.17 2002/08/13 18:01:52 carl
  1039. * rename swatoperands to swapoperands
  1040. + m68k first compilable version (still needs a lot of testing):
  1041. assembler generator, system information , inline
  1042. assembler reader.
  1043. Revision 1.16 2002/08/11 14:32:27 peter
  1044. * renamed current_library to objectlibrary
  1045. Revision 1.15 2002/08/11 13:24:12 peter
  1046. * saving of asmsymbols in ppu supported
  1047. * asmsymbollist global is removed and moved into a new class
  1048. tasmlibrarydata that will hold the info of a .a file which
  1049. corresponds with a single module. Added librarydata to tmodule
  1050. to keep the library info stored for the module. In the future the
  1051. objectfiles will also be stored to the tasmlibrarydata class
  1052. * all getlabel/newasmsymbol and friends are moved to the new class
  1053. Revision 1.14 2002/08/11 11:37:42 jonas
  1054. * genlinear(cmp)list can now be overridden by descendents
  1055. Revision 1.13 2002/08/11 06:14:40 florian
  1056. * fixed powerpc compilation problems
  1057. Revision 1.12 2002/08/10 17:15:12 jonas
  1058. * optimizations and bugfix
  1059. Revision 1.11 2002/07/28 09:24:18 carl
  1060. + generic case node
  1061. Revision 1.10 2002/07/23 14:31:00 daniel
  1062. * Added internal error when asked to generate code for 'if expr in []'
  1063. Revision 1.9 2002/07/23 12:34:30 daniel
  1064. * Readded old set code. To use it define 'oldset'. Activated by default
  1065. for ppc.
  1066. Revision 1.8 2002/07/22 11:48:04 daniel
  1067. * Sets are now internally sets.
  1068. Revision 1.7 2002/07/21 16:58:20 jonas
  1069. * fixed some bugs in tcginnode.pass_2() and optimized the bit test
  1070. Revision 1.6 2002/07/20 11:57:54 florian
  1071. * types.pas renamed to defbase.pas because D6 contains a types
  1072. unit so this would conflicts if D6 programms are compiled
  1073. + Willamette/SSE2 instructions to assembler added
  1074. Revision 1.5 2002/07/11 14:41:28 florian
  1075. * start of the new generic parameter handling
  1076. Revision 1.4 2002/07/07 10:16:29 florian
  1077. * problems with last commit fixed
  1078. Revision 1.3 2002/07/06 20:19:25 carl
  1079. + generic set handling
  1080. Revision 1.2 2002/07/01 16:23:53 peter
  1081. * cg64 patch
  1082. * basics for currency
  1083. * asnode updates for class and interface (not finished)
  1084. Revision 1.1 2002/06/16 08:14:56 carl
  1085. + generic sets
  1086. }