ncgset.pas 52 KB

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