ncgset.pas 49 KB

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