ag386int.pas 24 KB

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