ncgset.pas 52 KB

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