ag386int.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. {
  2. $Id$
  3. Copyright (c) 1996,97 by Florian Klaempfl
  4. This unit implements an asmoutput class for Intel syntax with Intel i386+
  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 ag386int;
  19. interface
  20. uses aasm,assemble;
  21. type
  22. pi386intasmlist=^ti386intasmlist;
  23. ti386intasmlist = object(tasmlist)
  24. procedure WriteTree(p:paasmoutput);virtual;
  25. procedure WriteAsmList;virtual;
  26. end;
  27. implementation
  28. uses
  29. dos,globals,systems,cobjects,i386,
  30. strings,files,verbose
  31. {$ifdef GDB}
  32. ,gdb
  33. {$endif GDB}
  34. ;
  35. const
  36. line_length = 70;
  37. extstr : array[EXT_NEAR..EXT_ABS] of String[8] =
  38. ('NEAR','FAR','PROC','BYTE','WORD','DWORD',
  39. 'CODEPTR','DATAPTR','FWORD','PWORD','QWORD','TBYTE','ABS');
  40. function double2str(d : double) : string;
  41. var
  42. hs : string;
  43. p : byte;
  44. begin
  45. str(d,hs);
  46. { nasm expects a lowercase e }
  47. p:=pos('E',hs);
  48. if p>0 then
  49. hs[p]:='e';
  50. p:=pos('+',hs);
  51. if p>0 then
  52. delete(hs,p,1);
  53. double2str:=lower(hs);
  54. end;
  55. function extended2str(e : extended) : string;
  56. var
  57. hs : string;
  58. p : byte;
  59. begin
  60. {$ifdef VER0_99_5}
  61. str(double(e),hs);
  62. {$else}
  63. str(e,hs);
  64. {$endif}
  65. { nasm expects a lowercase e }
  66. p:=pos('E',hs);
  67. if p>0 then
  68. hs[p]:='e';
  69. p:=pos('+',hs);
  70. if p>0 then
  71. delete(hs,p,1);
  72. extended2str:=lower(hs);
  73. end;
  74. function comp2str(d : bestreal) : string;
  75. type
  76. pdouble = ^double;
  77. var
  78. c : comp;
  79. dd : pdouble;
  80. begin
  81. {$ifdef TP}
  82. c:=d;
  83. {$else}
  84. c:=comp(d);
  85. {$endif}
  86. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  87. comp2str:=double2str(dd^);
  88. end;
  89. function getreferencestring(const ref : treference) : string;
  90. var
  91. s : string;
  92. first : boolean;
  93. begin
  94. if ref.isintvalue then
  95. s:= tostr(ref.offset)
  96. else
  97. with ref do
  98. begin
  99. first:=true;
  100. if ref.segment<>R_DEFAULT_SEG then
  101. s:=int_reg2str[segment]+':['
  102. else
  103. s:='[';
  104. if assigned(symbol) then
  105. begin
  106. s:=s+symbol^;
  107. first:=false;
  108. end;
  109. if (base<>R_NO) then
  110. begin
  111. if not(first) then
  112. s:=s+'+'
  113. else
  114. first:=false;
  115. s:=s+int_reg2str[base];
  116. end;
  117. if (index<>R_NO) then
  118. begin
  119. if not(first) then
  120. s:=s+'+'
  121. else
  122. first:=false;
  123. s:=s+int_reg2str[index];
  124. if scalefactor<>0 then
  125. s:=s+'*'+tostr(scalefactor);
  126. end;
  127. if offset<0 then
  128. s:=s+tostr(offset)
  129. else if (offset>0) then
  130. s:=s+'+'+tostr(offset);
  131. s:=s+']';
  132. end;
  133. getreferencestring:=s;
  134. end;
  135. function getopstr(t : byte;o : pointer;s : topsize; _operator: tasmop;dest : boolean) : string;
  136. var
  137. hs : string;
  138. begin
  139. case t of
  140. top_reg : getopstr:=int_reg2str[tregister(o)];
  141. top_const,
  142. top_ref : begin
  143. if t=top_const then
  144. hs := tostr(longint(o))
  145. else
  146. hs:=getreferencestring(preference(o)^);
  147. { can possibly give a range check error under tp }
  148. { if using in... }
  149. if ((_operator <> A_LGS) and (_operator <> A_LSS) and
  150. (_operator <> A_LFS) and (_operator <> A_LDS) and
  151. (_operator <> A_LES)) then
  152. Begin
  153. case s of
  154. S_B : hs:='byte ptr '+hs;
  155. S_W : hs:='word ptr '+hs;
  156. S_L : hs:='dword ptr '+hs;
  157. S_IS : hs:='word ptr '+hs;
  158. S_IL : hs:='dword ptr '+hs;
  159. S_IQ : hs:='qword ptr '+hs;
  160. S_FS : hs:='dword ptr '+hs;
  161. S_FL : hs:='qword ptr '+hs;
  162. S_FX : hs:='tbyte ptr '+hs;
  163. S_BW : if dest then
  164. hs:='word ptr '+hs
  165. else
  166. hs:='byte ptr '+hs;
  167. S_BL : if dest then
  168. hs:='dword ptr '+hs
  169. else
  170. hs:='byte ptr '+hs;
  171. S_WL : if dest then
  172. hs:='dword ptr '+hs
  173. else
  174. hs:='word ptr '+hs;
  175. end;
  176. end;
  177. getopstr:=hs;
  178. end;
  179. top_symbol : begin
  180. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  181. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  182. hs:='offset '+hs;
  183. if pcsymbol(o)^.offset>0 then
  184. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  185. else
  186. if pcsymbol(o)^.offset<0 then
  187. hs:=hs+tostr(pcsymbol(o)^.offset);
  188. getopstr:=hs;
  189. end;
  190. else
  191. internalerror(10001);
  192. end;
  193. end;
  194. function getopstr_jmp(t : byte;o : pointer) : string;
  195. var
  196. hs : string;
  197. begin
  198. case t of
  199. top_reg : getopstr_jmp:=int_reg2str[tregister(o)];
  200. top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
  201. top_const : getopstr_jmp:=tostr(longint(o));
  202. top_symbol : begin
  203. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  204. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  205. if pcsymbol(o)^.offset>0 then
  206. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  207. else
  208. if pcsymbol(o)^.offset<0 then
  209. hs:=hs+tostr(pcsymbol(o)^.offset);
  210. getopstr_jmp:=hs;
  211. end;
  212. else
  213. internalerror(10001);
  214. end;
  215. end;
  216. {****************************************************************************
  217. TI386INTASMLIST
  218. ****************************************************************************}
  219. var
  220. LastSec : tsection;
  221. const
  222. ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
  223. (#9'DD'#9,'',#9'DW'#9,#9'DB'#9);
  224. ait_section2masmstr : array[tsection] of string[6]=
  225. ('','CODE','DATA','BSS','');
  226. Function PadTabs(p:pchar;addch:char):string;
  227. var
  228. s : string;
  229. i : longint;
  230. begin
  231. i:=strlen(p);
  232. if addch<>#0 then
  233. begin
  234. inc(i);
  235. s:=StrPas(p)+addch;
  236. end
  237. else
  238. s:=StrPas(p);
  239. if i<8 then
  240. PadTabs:=s+#9#9
  241. else
  242. PadTabs:=s+#9;
  243. end;
  244. procedure ti386intasmlist.WriteTree(p:paasmoutput);
  245. type
  246. twowords=record
  247. word1,word2:word;
  248. end;
  249. var
  250. s,
  251. prefix,
  252. suffix : string;
  253. hp : pai;
  254. counter,
  255. lines,
  256. i,j,l : longint;
  257. consttyp : tait;
  258. found,
  259. quoted : boolean;
  260. begin
  261. if not assigned(p) then
  262. exit;
  263. hp:=pai(p^.first);
  264. while assigned(hp) do
  265. begin
  266. case hp^.typ of
  267. ait_comment : Begin
  268. AsmWrite(target_asm.comment);
  269. AsmWritePChar(pai_asm_comment(hp)^.str);
  270. AsmLn;
  271. End;
  272. ait_regalloc,
  273. ait_regdealloc :;
  274. ait_section : begin
  275. if LastSec<>sec_none then
  276. AsmWriteLn('_'+ait_section2masmstr[LastSec]+#9#9'ENDS');
  277. if pai_section(hp)^.sec<>sec_none then
  278. begin
  279. AsmLn;
  280. AsmWriteLn('_'+ait_section2masmstr[pai_section(hp)^.sec]+#9#9+
  281. 'SEGMENT'#9'PARA PUBLIC USE32 '''+
  282. ait_section2masmstr[pai_section(hp)^.sec]+'''');
  283. end;
  284. LastSec:=pai_section(hp)^.sec;
  285. end;
  286. ait_align : begin
  287. { CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
  288. { SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
  289. { HERE UNDER TASM! }
  290. AsmWriteLn(#9'ALIGN '+tostr(pai_align(hp)^.aligntype));
  291. end;
  292. ait_external : AsmWriteLn(#9'EXTRN'#9+StrPas(pai_external(hp)^.name)+
  293. ' :'+extstr[pai_external(hp)^.exttyp]);
  294. ait_datablock : begin
  295. if pai_datablock(hp)^.is_global then
  296. AsmWriteLn(#9'PUBLIC'#9+StrPas(pai_datablock(hp)^.name));
  297. AsmWriteLn(PadTabs(pai_datablock(hp)^.name,#0)+'DB'#9+tostr(pai_datablock(hp)^.size)+' DUP(?)');
  298. end;
  299. ait_const_32bit,
  300. ait_const_8bit,
  301. ait_const_16bit : begin
  302. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  303. consttyp:=hp^.typ;
  304. l:=0;
  305. repeat
  306. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  307. if found then
  308. begin
  309. hp:=Pai(hp^.next);
  310. s:=','+tostr(pai_const(hp)^.value);
  311. AsmWrite(s);
  312. inc(l,length(s));
  313. end;
  314. until (not found) or (l>line_length);
  315. AsmLn;
  316. end;
  317. ait_const_symbol : begin
  318. AsmWrite(#9#9+'DD '#9'offset ');
  319. AsmWritePChar(pchar(pai_const(hp)^.value));
  320. AsmLn;
  321. end;
  322. ait_real_32bit : AsmWriteLn(#9#9'DD'#9+double2str(pai_single(hp)^.value));
  323. ait_real_64bit : AsmWriteLn(#9#9'DQ'#9+double2str(pai_double(hp)^.value));
  324. ait_real_extended : AsmWriteLn(#9#9'DT'#9+extended2str(pai_extended(hp)^.value));
  325. ait_comp : AsmWriteLn(#9#9'DQ'#9+comp2str(pai_extended(hp)^.value));
  326. ait_string : begin
  327. counter := 0;
  328. lines := pai_string(hp)^.len div line_length;
  329. { separate lines in different parts }
  330. if pai_string(hp)^.len > 0 then
  331. Begin
  332. for j := 0 to lines-1 do
  333. begin
  334. AsmWrite(#9#9'DB'#9);
  335. quoted:=false;
  336. for i:=counter to counter+line_length do
  337. begin
  338. { it is an ascii character. }
  339. if (ord(pai_string(hp)^.str[i])>31) and
  340. (ord(pai_string(hp)^.str[i])<128) and
  341. (pai_string(hp)^.str[i]<>'"') then
  342. begin
  343. if not(quoted) then
  344. begin
  345. if i>counter then
  346. AsmWrite(',');
  347. AsmWrite('"');
  348. end;
  349. AsmWrite(pai_string(hp)^.str[i]);
  350. quoted:=true;
  351. end { if > 31 and < 128 and ord('"') }
  352. else
  353. begin
  354. if quoted then
  355. AsmWrite('"');
  356. if i>counter then
  357. AsmWrite(',');
  358. quoted:=false;
  359. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  360. end;
  361. end; { end for i:=0 to... }
  362. if quoted then AsmWrite('"');
  363. AsmWrite(target_os.newline);
  364. counter := counter+line_length;
  365. end; { end for j:=0 ... }
  366. { do last line of lines }
  367. AsmWrite(#9#9'DB'#9);
  368. quoted:=false;
  369. for i:=counter to pai_string(hp)^.len-1 do
  370. begin
  371. { it is an ascii character. }
  372. if (ord(pai_string(hp)^.str[i])>31) and
  373. (ord(pai_string(hp)^.str[i])<128) and
  374. (pai_string(hp)^.str[i]<>'"') then
  375. begin
  376. if not(quoted) then
  377. begin
  378. if i>counter then
  379. AsmWrite(',');
  380. AsmWrite('"');
  381. end;
  382. AsmWrite(pai_string(hp)^.str[i]);
  383. quoted:=true;
  384. end { if > 31 and < 128 and " }
  385. else
  386. begin
  387. if quoted then
  388. AsmWrite('"');
  389. if i>counter then
  390. AsmWrite(',');
  391. quoted:=false;
  392. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  393. end;
  394. end; { end for i:=0 to... }
  395. if quoted then
  396. AsmWrite('"');
  397. end;
  398. AsmLn;
  399. end;
  400. ait_label : begin
  401. if pai_label(hp)^.l^.is_used then
  402. begin
  403. AsmWrite(lab2str(pai_label(hp)^.l));
  404. if (assigned(hp^.next) and not(pai(hp^.next)^.typ in
  405. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  406. ait_real_32bit,ait_real_64bit,ait_real_extended,ait_string])) then
  407. AsmWriteLn(':');
  408. end;
  409. end;
  410. ait_direct : begin
  411. AsmWritePChar(pai_direct(hp)^.str);
  412. AsmLn;
  413. end;
  414. ait_labeled_instruction : AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab));
  415. ait_symbol : begin
  416. if pai_symbol(hp)^.is_global then
  417. AsmWriteLn(#9'PUBLIC'#9+StrPas(pai_symbol(hp)^.name));
  418. AsmWritePChar(pai_symbol(hp)^.name);
  419. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  420. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  421. ait_real_64bit,ait_real_extended,ait_string]) then
  422. AsmWriteLn(':')
  423. end;
  424. ait_instruction : begin
  425. suffix:='';
  426. prefix:= '';
  427. { added prefix instructions, must be on same line as opcode }
  428. if (pai386(hp)^.op1t = top_none) and
  429. ((pai386(hp)^._operator = A_REP) or
  430. (pai386(hp)^._operator = A_LOCK) or
  431. (pai386(hp)^._operator = A_REPE) or
  432. (pai386(hp)^._operator = A_REPNE)) then
  433. Begin
  434. prefix:=int_op2str[pai386(hp)^._operator]+#9;
  435. hp:=Pai(hp^.next);
  436. { this is theorically impossible... }
  437. if hp=nil then
  438. begin
  439. s:=#9#9+prefix;
  440. AsmWriteLn(s);
  441. break;
  442. end;
  443. end
  444. else
  445. prefix:= '';
  446. if pai386(hp)^.op1t<>top_none then
  447. begin
  448. if pai386(hp)^._operator in [A_CALL] then
  449. begin
  450. { with tasm call near ptr [edi+12] does not
  451. work but call near [edi+12] works ?? (PM)
  452. It works with call dword ptr [], but you
  453. need /m2 (2 passes) with tasm (PFV)
  454. }
  455. { if pai386(hp)^.op1t=top_ref then
  456. s:='near '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
  457. else
  458. s:='near ptr '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1);}
  459. s:='dword ptr '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1);
  460. end
  461. else
  462. begin
  463. s:=getopstr(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.size,pai386(hp)^._operator,false);
  464. if pai386(hp)^.op3t<>top_none then
  465. begin
  466. if pai386(hp)^.op2t<>top_none then
  467. s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),
  468. pai386(hp)^.size,pai386(hp)^._operator,true)+','+s;
  469. s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),
  470. pai386(hp)^.size,pai386(hp)^._operator,false)+','+s;
  471. end
  472. else
  473. if pai386(hp)^.op2t<>top_none then
  474. s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,pai386(hp)^.size,
  475. pai386(hp)^._operator,true)+','+s;
  476. end;
  477. s:=#9+s;
  478. end
  479. else
  480. begin
  481. { check if string instruction }
  482. { long form, otherwise may give range check errors }
  483. { in turbo pascal... }
  484. if ((pai386(hp)^._operator = A_CMPS) or
  485. (pai386(hp)^._operator = A_INS) or
  486. (pai386(hp)^._operator = A_OUTS) or
  487. (pai386(hp)^._operator = A_SCAS) or
  488. (pai386(hp)^._operator = A_STOS) or
  489. (pai386(hp)^._operator = A_MOVS) or
  490. (pai386(hp)^._operator = A_LODS) or
  491. (pai386(hp)^._operator = A_XLAT)) then
  492. Begin
  493. case pai386(hp)^.size of
  494. S_B: suffix:='b';
  495. S_W: suffix:='w';
  496. S_L: suffix:='d';
  497. else
  498. Message(assem_f_invalid_suffix_intel);
  499. end;
  500. end;
  501. s:='';
  502. end;
  503. AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^._operator]+suffix+s);
  504. end;
  505. {$ifdef GDB}
  506. ait_stabn,
  507. ait_stabs,
  508. ait_stab_function_name : ;
  509. {$endif GDB}
  510. else
  511. internalerror(10000);
  512. end;
  513. hp:=pai(hp^.next);
  514. end;
  515. end;
  516. procedure ti386intasmlist.WriteAsmList;
  517. begin
  518. {$ifdef EXTDEBUG}
  519. if assigned(current_module^.mainsource) then
  520. comment(v_info,'Start writing intel-styled assembler output for '+current_module^.mainsource^);
  521. {$endif}
  522. LastSec:=sec_none;
  523. AsmWriteLn(#9'.386p');
  524. AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
  525. AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
  526. AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
  527. AsmLn;
  528. countlabelref:=false;
  529. WriteTree(externals);
  530. { INTEL ASM doesn't support stabs
  531. WriteTree(debuglist);}
  532. WriteTree(codesegment);
  533. WriteTree(datasegment);
  534. WriteTree(consts);
  535. WriteTree(rttilist);
  536. WriteTree(bsssegment);
  537. countlabelref:=true;
  538. AsmWriteLn(#9'END');
  539. AsmLn;
  540. {$ifdef EXTDEBUG}
  541. if assigned(current_module^.mainsource) then
  542. comment(v_info,'Done writing intel-styled assembler output for '+current_module^.mainsource^);
  543. {$endif EXTDEBUG}
  544. end;
  545. end.
  546. {
  547. $Log$
  548. Revision 1.16 1998-10-06 17:16:33 pierre
  549. * some memory leaks fixed (thanks to Peter for heaptrc !)
  550. Revision 1.15 1998/10/01 20:19:06 jonas
  551. + ait_marker support
  552. Revision 1.14 1998/09/20 17:11:21 jonas
  553. * released REGALLOC
  554. Revision 1.13 1998/08/10 15:49:38 peter
  555. * small fixes for 0.99.5
  556. Revision 1.12 1998/08/08 10:19:17 florian
  557. * small fixes to write the extended type correct
  558. Revision 1.11 1998/06/05 17:46:02 peter
  559. * tp doesn't like comp() typecast
  560. Revision 1.10 1998/05/25 17:11:36 pierre
  561. * firstpasscount bug fixed
  562. now all is already set correctly the first time
  563. under EXTDEBUG try -gp to skip all other firstpasses
  564. it works !!
  565. * small bug fixes
  566. - for smallsets with -dTESTSMALLSET
  567. - some warnings removed (by correcting code !)
  568. Revision 1.9 1998/05/23 01:20:55 peter
  569. + aktasmmode, aktoptprocessor, aktoutputformat
  570. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  571. + $LIBNAME to set the library name where the unit will be put in
  572. * splitted cgi386 a bit (codeseg to large for bp7)
  573. * nasm, tasm works again. nasm moved to ag386nsm.pas
  574. Revision 1.8 1998/05/06 18:36:53 peter
  575. * tai_section extended with code,data,bss sections and enumerated type
  576. * ident 'compiled by FPC' moved to pmodules
  577. * small fix for smartlink
  578. Revision 1.7 1998/05/06 08:38:32 pierre
  579. * better position info with UseTokenInfo
  580. UseTokenInfo greatly simplified
  581. + added check for changed tree after first time firstpass
  582. (if we could remove all the cases were it happen
  583. we could skip all firstpass if firstpasscount > 1)
  584. Only with ExtDebug
  585. Revision 1.6 1998/05/04 17:54:24 peter
  586. + smartlinking works (only case jumptable left todo)
  587. * redesign of systems.pas to support assemblers and linkers
  588. + Unitname is now also in the PPU-file, increased version to 14
  589. Revision 1.5 1998/05/01 07:43:52 florian
  590. + basics for rtti implemented
  591. + switch $m (generate rtti for published sections)
  592. Revision 1.4 1998/04/29 10:33:41 pierre
  593. + added some code for ansistring (not complete nor working yet)
  594. * corrected operator overloading
  595. * corrected nasm output
  596. + started inline procedures
  597. + added starstarn : use ** for exponentiation (^ gave problems)
  598. + started UseTokenInfo cond to get accurate positions
  599. Revision 1.3 1998/04/08 16:58:01 pierre
  600. * several bugfixes
  601. ADD ADC and AND are also sign extended
  602. nasm output OK (program still crashes at end
  603. and creates wrong assembler files !!)
  604. procsym types sym in tdef removed !!
  605. Revision 1.2 1998/04/08 11:34:17 peter
  606. * nasm works (linux only tested)
  607. }