ag386att.pas 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  1. {
  2. $Id$
  3. Copyright (c) 1996-98 by the FPC development team
  4. This unit implements an asmoutput class for i386 AT&T syntax
  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. {$ifdef TP}
  19. {$N+,E+}
  20. {$endif}
  21. unit ag386att;
  22. interface
  23. uses cobjects,aasm,assemble;
  24. type
  25. pi386attasmlist=^ti386attasmlist;
  26. ti386attasmlist=object(tasmlist)
  27. procedure WriteTree(p:paasmoutput);virtual;
  28. procedure WriteAsmList;virtual;
  29. {$ifdef GDB}
  30. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  31. {$endif}
  32. end;
  33. implementation
  34. uses
  35. {$ifdef Delphi}
  36. dmisc,
  37. {$else Delphi}
  38. dos,
  39. {$endif Delphi}
  40. strings,
  41. globtype,globals,systems,
  42. files,verbose,cpubase,cpuasm
  43. {$ifdef GDB}
  44. ,gdb
  45. {$endif GDB}
  46. ;
  47. const
  48. line_length = 70;
  49. var
  50. {$ifdef GDB}
  51. n_line : byte; { different types of source lines }
  52. linecount,
  53. includecount : longint;
  54. funcname : pchar;
  55. stabslastfileinfo : tfileposinfo;
  56. {$endif}
  57. lastsec : tsection; { last section type written }
  58. lastfileinfo : tfileposinfo;
  59. infile,
  60. lastinfile : pinputfile;
  61. symendcount : longint;
  62. function fixline(s:string):string;
  63. {
  64. return s with all leading and ending spaces and tabs removed
  65. }
  66. var
  67. i,j,k : longint;
  68. begin
  69. i:=length(s);
  70. while (i>0) and (s[i] in [#9,' ']) do
  71. dec(i);
  72. j:=1;
  73. while (j<i) and (s[j] in [#9,' ']) do
  74. inc(j);
  75. for k:=j to i do
  76. if s[k] in [#0..#31,#127..#255] then
  77. s[k]:='.';
  78. fixline:=Copy(s,j,i-j+1);
  79. end;
  80. function single2str(d : single) : string;
  81. var
  82. hs : string;
  83. begin
  84. str(d,hs);
  85. { replace space with + }
  86. if hs[1]=' ' then
  87. hs[1]:='+';
  88. single2str:='0d'+hs
  89. end;
  90. function double2str(d : double) : string;
  91. var
  92. hs : string;
  93. begin
  94. str(d,hs);
  95. { replace space with + }
  96. if hs[1]=' ' then
  97. hs[1]:='+';
  98. double2str:='0d'+hs
  99. end;
  100. function extended2str(e : extended) : string;
  101. var
  102. hs : string;
  103. begin
  104. str(e,hs);
  105. { replace space with + }
  106. if hs[1]=' ' then
  107. hs[1]:='+';
  108. extended2str:='0d'+hs
  109. end;
  110. type
  111. pdouble = ^double;
  112. function comp2str(d : bestreal) : string;
  113. var
  114. c : comp;
  115. dd : pdouble;
  116. begin
  117. {$ifdef FPC}
  118. c:=comp(d);
  119. {$else}
  120. c:=d;
  121. {$endif}
  122. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  123. comp2str:=double2str(dd^);
  124. end;
  125. function getreferencestring(var ref : treference) : string;
  126. var
  127. s : string;
  128. begin
  129. if ref.is_immediate then
  130. begin
  131. internalerror(1000101);
  132. exit;
  133. end
  134. else
  135. begin
  136. with ref do
  137. begin
  138. inc(offset,offsetfixup);
  139. offsetfixup:=0;
  140. { have we a segment prefix ? }
  141. { These are probably not correctly handled under GAS }
  142. { should be replaced by coding the segment override }
  143. { directly! - DJGPP FAQ }
  144. if segment<>R_NO then
  145. s:=att_reg2str[segment]+':'
  146. else
  147. s:='';
  148. if assigned(symbol) then
  149. s:=s+symbol^.name;
  150. if offset<0 then
  151. s:=s+tostr(offset)
  152. else
  153. if (offset>0) then
  154. begin
  155. if assigned(symbol) then
  156. s:=s+'+'+tostr(offset)
  157. else
  158. s:=s+tostr(offset);
  159. end;
  160. if (index<>R_NO) and (base=R_NO) then
  161. Begin
  162. s:=s+'(,'+att_reg2str[index];
  163. if scalefactor<>0 then
  164. s:=s+','+tostr(scalefactor)+')'
  165. else
  166. s:=s+')';
  167. end
  168. else
  169. if (index=R_NO) and (base<>R_NO) then
  170. s:=s+'('+att_reg2str[base]+')'
  171. else
  172. if (index<>R_NO) and (base<>R_NO) then
  173. Begin
  174. s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
  175. if scalefactor<>0 then
  176. s:=s+','+tostr(scalefactor)+')'
  177. else
  178. s := s+')';
  179. end;
  180. end;
  181. end;
  182. getreferencestring:=s;
  183. end;
  184. function getopstr(const o:toper) : string;
  185. var
  186. hs : string;
  187. begin
  188. case o.typ of
  189. top_reg :
  190. getopstr:=att_reg2str[o.reg];
  191. top_ref :
  192. getopstr:=getreferencestring(o.ref^);
  193. top_const :
  194. getopstr:='$'+tostr(o.val);
  195. top_symbol :
  196. begin
  197. if assigned(o.sym) then
  198. hs:='$'+o.sym^.name
  199. else
  200. hs:='$';
  201. if o.symofs>0 then
  202. hs:=hs+'+'+tostr(o.symofs)
  203. else
  204. if o.symofs<0 then
  205. hs:=hs+tostr(o.symofs)
  206. else
  207. if not(assigned(o.sym)) then
  208. hs:=hs+'0';
  209. getopstr:=hs;
  210. end;
  211. else
  212. internalerror(10001);
  213. end;
  214. end;
  215. function getopstr_jmp(const o:toper) : string;
  216. var
  217. hs : string;
  218. begin
  219. case o.typ of
  220. top_reg :
  221. getopstr_jmp:='*'+att_reg2str[o.reg];
  222. top_ref :
  223. getopstr_jmp:='*'+getreferencestring(o.ref^);
  224. top_const :
  225. getopstr_jmp:=tostr(o.val);
  226. top_symbol :
  227. begin
  228. hs:=o.sym^.name;
  229. if o.symofs>0 then
  230. hs:=hs+'+'+tostr(o.symofs)
  231. else
  232. if o.symofs<0 then
  233. hs:=hs+tostr(o.symofs);
  234. getopstr_jmp:=hs;
  235. end;
  236. else
  237. internalerror(10001);
  238. end;
  239. end;
  240. {****************************************************************************
  241. TI386ATTASMOUTPUT
  242. ****************************************************************************}
  243. const
  244. ait_const2str : array[ait_const_32bit..ait_const_8bit] of string[8]=
  245. (#9'.long'#9,#9'.short'#9,#9'.byte'#9);
  246. function ait_section2str(s:tsection):string;
  247. begin
  248. ait_section2str:=target_asm.secnames[s];
  249. {$ifdef GDB}
  250. { this is needed for line info in data }
  251. funcname:=nil;
  252. case s of
  253. sec_code : n_line:=n_textline;
  254. sec_data : n_line:=n_dataline;
  255. sec_bss : n_line:=n_bssline;
  256. else n_line:=n_dataline;
  257. end;
  258. {$endif GDB}
  259. LastSec:=s;
  260. end;
  261. {$ifdef GDB}
  262. procedure ti386attasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  263. var
  264. curr_n : byte;
  265. begin
  266. if not (cs_debuginfo in aktmoduleswitches) then
  267. exit;
  268. { file changed ? (must be before line info) }
  269. if (fileinfo.fileindex<>0) and
  270. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  271. begin
  272. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  273. if includecount=0 then
  274. curr_n:=n_sourcefile
  275. else
  276. curr_n:=n_includefile;
  277. if (infile^.path^<>'') then
  278. begin
  279. AsmWriteLn(#9'.stabs "'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+
  280. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  281. end;
  282. AsmWriteLn(#9'.stabs "'+lower(FixFileName(infile^.name^))+'",'+
  283. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  284. AsmWriteLn('Ltext'+ToStr(IncludeCount)+':');
  285. inc(includecount);
  286. end;
  287. { line changed ? }
  288. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  289. begin
  290. if (n_line=n_textline) and assigned(funcname) and
  291. (target_os.use_function_relative_addresses) then
  292. begin
  293. AsmWriteLn(target_asm.labelprefix+'l'+tostr(linecount)+':');
  294. AsmWrite(#9'.stabn '+tostr(n_line)+',0,'+tostr(fileinfo.line)+','+
  295. target_asm.labelprefix+'l'+tostr(linecount)+' - ');
  296. AsmWritePChar(FuncName);
  297. AsmLn;
  298. inc(linecount);
  299. end
  300. else
  301. AsmWriteLn(#9'.stabd'#9+tostr(n_line)+',0,'+tostr(fileinfo.line));
  302. end;
  303. stabslastfileinfo:=fileinfo;
  304. end;
  305. {$endif GDB}
  306. procedure ti386attasmlist.WriteTree(p:paasmoutput);
  307. const
  308. allocstr : array[boolean] of string[10]=(' released',' allocated');
  309. type
  310. t80bitarray = array[0..9] of byte;
  311. t64bitarray = array[0..7] of byte;
  312. t32bitarray = array[0..3] of byte;
  313. var
  314. ch : char;
  315. hp : pai;
  316. consttyp : tait;
  317. s : string;
  318. found : boolean;
  319. i,pos,l : longint;
  320. co : comp;
  321. sin : single;
  322. d : double;
  323. e : extended;
  324. op : tasmop;
  325. calljmp,
  326. do_line : boolean;
  327. sep : char;
  328. begin
  329. if not assigned(p) then
  330. exit;
  331. do_line:=(cs_debuginfo in aktmoduleswitches) or (cs_asm_source in aktglobalswitches);
  332. hp:=pai(p^.first);
  333. while assigned(hp) do
  334. begin
  335. aktfilepos:=hp^.fileinfo;
  336. if do_line then
  337. begin
  338. { I think it is better to write stabs before source line PM }
  339. {$ifdef GDB}
  340. { write stabs }
  341. if cs_debuginfo in aktmoduleswitches then
  342. begin
  343. if not (hp^.typ in [
  344. ait_label,
  345. ait_regalloc,ait_tempalloc,
  346. ait_stabn,ait_stabs,ait_section,
  347. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  348. begin
  349. WriteFileLineInfo(hp^.fileinfo);
  350. end;
  351. end;
  352. {$endif GDB}
  353. { load infile }
  354. if lastfileinfo.fileindex<>hp^.fileinfo.fileindex then
  355. begin
  356. infile:=current_module^.sourcefiles^.get_file(hp^.fileinfo.fileindex);
  357. { open only if needed !! }
  358. if (cs_asm_source in aktglobalswitches) then
  359. infile^.open;
  360. { avoid unnecessary reopens of the same file !! }
  361. lastfileinfo.fileindex:=hp^.fileinfo.fileindex;
  362. { be sure to change line !! }
  363. lastfileinfo.line:=-1;
  364. end;
  365. { write source }
  366. if (cs_asm_source in aktglobalswitches) and
  367. not (hp^.typ in [
  368. ait_label,
  369. ait_stabn,ait_stabs,ait_section,
  370. ait_cut,ait_align,ait_stab_function_name]) then
  371. begin
  372. if (infile<>lastinfile) and assigned(lastinfile) then
  373. begin
  374. AsmWriteLn(target_asm.comment+'['+infile^.name^+']');
  375. lastinfile^.close;
  376. end;
  377. if (hp^.fileinfo.line<>lastfileinfo.line) and
  378. (hp^.fileinfo.line<infile^.maxlinebuf) then
  379. begin
  380. if (hp^.fileinfo.line<>0) and
  381. (infile^.linebuf^[hp^.fileinfo.line]>=0) then
  382. AsmWriteLn(target_asm.comment+'['+tostr(hp^.fileinfo.line)+'] '+
  383. fixline(infile^.GetLineStr(hp^.fileinfo.line)));
  384. { set it to a negative value !
  385. to make that is has been read already !! PM }
  386. infile^.linebuf^[hp^.fileinfo.line]:=-infile^.linebuf^[hp^.fileinfo.line]-1;
  387. end;
  388. lastfileinfo:=hp^.fileinfo;
  389. lastinfile:=infile;
  390. end;
  391. end;
  392. case hp^.typ of
  393. ait_comment :
  394. Begin
  395. AsmWrite(target_asm.comment);
  396. AsmWritePChar(pai_asm_comment(hp)^.str);
  397. AsmLn;
  398. End;
  399. ait_regalloc :
  400. begin
  401. if (cs_asm_regalloc in aktglobalswitches) then
  402. AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+
  403. allocstr[pairegalloc(hp)^.allocation]);
  404. end;
  405. ait_tempalloc :
  406. begin
  407. if (cs_asm_tempalloc in aktglobalswitches) then
  408. AsmWriteLn(target_asm.comment+'Temp '+tostr(paitempalloc(hp)^.temppos)+','+
  409. tostr(paitempalloc(hp)^.tempsize)+allocstr[paitempalloc(hp)^.allocation]);
  410. end;
  411. ait_align :
  412. begin
  413. AsmWrite(#9'.balign '+tostr(pai_align(hp)^.aligntype));
  414. if pai_align(hp)^.use_op then
  415. AsmWrite(','+tostr(pai_align(hp)^.fillop));
  416. AsmLn;
  417. end;
  418. ait_section :
  419. begin
  420. if pai_section(hp)^.sec<>sec_none then
  421. begin
  422. AsmLn;
  423. AsmWriteLn(ait_section2str(pai_section(hp)^.sec));
  424. {$ifdef GDB}
  425. lastfileinfo.line:=-1;
  426. {$endif GDB}
  427. end;
  428. end;
  429. ait_datablock :
  430. begin
  431. if pai_datablock(hp)^.is_global then
  432. AsmWrite(#9'.comm'#9)
  433. else
  434. AsmWrite(#9'.lcomm'#9);
  435. AsmWrite(pai_datablock(hp)^.sym^.name);
  436. AsmWriteLn(','+tostr(pai_datablock(hp)^.size));
  437. end;
  438. ait_const_32bit,
  439. ait_const_16bit,
  440. ait_const_8bit :
  441. begin
  442. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  443. consttyp:=hp^.typ;
  444. l:=0;
  445. repeat
  446. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  447. if found then
  448. begin
  449. hp:=Pai(hp^.next);
  450. s:=','+tostr(pai_const(hp)^.value);
  451. AsmWrite(s);
  452. inc(l,length(s));
  453. end;
  454. until (not found) or (l>line_length);
  455. AsmLn;
  456. end;
  457. ait_const_symbol :
  458. begin
  459. AsmWrite(#9'.long'#9+pai_const_symbol(hp)^.sym^.name);
  460. if pai_const_symbol(hp)^.offset>0 then
  461. AsmWrite('+'+tostr(pai_const_symbol(hp)^.offset))
  462. else if pai_const_symbol(hp)^.offset<0 then
  463. AsmWrite(tostr(pai_const_symbol(hp)^.offset));
  464. AsmLn;
  465. end;
  466. ait_const_rva :
  467. AsmWriteLn(#9'.rva'#9+pai_const_symbol(hp)^.sym^.name);
  468. ait_real_80bit :
  469. begin
  470. if do_line then
  471. AsmWriteLn(target_asm.comment+extended2str(pai_real_80bit(hp)^.value));
  472. { Make sure e is a extended type, bestreal could be
  473. a different type (bestreal) !! (PFV) }
  474. e:=pai_real_80bit(hp)^.value;
  475. AsmWrite(#9'.byte'#9);
  476. for i:=0 to 9 do
  477. begin
  478. if i<>0 then
  479. AsmWrite(',');
  480. AsmWrite(tostr(t80bitarray(e)[i]));
  481. end;
  482. AsmLn;
  483. end;
  484. ait_real_64bit :
  485. begin
  486. if do_line then
  487. AsmWriteLn(target_asm.comment+double2str(pai_real_64bit(hp)^.value));
  488. d:=pai_real_64bit(hp)^.value;
  489. AsmWrite(#9'.byte'#9);
  490. for i:=0 to 7 do
  491. begin
  492. if i<>0 then
  493. AsmWrite(',');
  494. AsmWrite(tostr(t64bitarray(d)[i]));
  495. end;
  496. AsmLn;
  497. end;
  498. ait_real_32bit :
  499. begin
  500. if do_line then
  501. AsmWriteLn(target_asm.comment+single2str(pai_real_32bit(hp)^.value));
  502. sin:=pai_real_32bit(hp)^.value;
  503. AsmWrite(#9'.byte'#9);
  504. for i:=0 to 3 do
  505. begin
  506. if i<>0 then
  507. AsmWrite(',');
  508. AsmWrite(tostr(t32bitarray(sin)[i]));
  509. end;
  510. AsmLn;
  511. end;
  512. ait_comp_64bit :
  513. begin
  514. if do_line then
  515. AsmWriteLn(target_asm.comment+comp2str(pai_comp_64bit(hp)^.value));
  516. AsmWrite(#9'.byte'#9);
  517. {$ifdef FPC}
  518. co:=comp(pai_comp_64bit(hp)^.value);
  519. {$else}
  520. co:=pai_comp_64bit(hp)^.value;
  521. {$endif}
  522. for i:=0 to 7 do
  523. begin
  524. if i<>0 then
  525. AsmWrite(',');
  526. AsmWrite(tostr(t64bitarray(co)[i]));
  527. end;
  528. AsmLn;
  529. end;
  530. ait_direct :
  531. begin
  532. AsmWritePChar(pai_direct(hp)^.str);
  533. AsmLn;
  534. {$IfDef GDB}
  535. if strpos(pai_direct(hp)^.str,'.data')<>nil then
  536. n_line:=n_dataline
  537. else if strpos(pai_direct(hp)^.str,'.text')<>nil then
  538. n_line:=n_textline
  539. else if strpos(pai_direct(hp)^.str,'.bss')<>nil then
  540. n_line:=n_bssline;
  541. {$endif GDB}
  542. end;
  543. ait_string :
  544. begin
  545. pos:=0;
  546. for i:=1 to pai_string(hp)^.len do
  547. begin
  548. if pos=0 then
  549. begin
  550. AsmWrite(#9'.ascii'#9'"');
  551. pos:=20;
  552. end;
  553. ch:=pai_string(hp)^.str[i-1];
  554. case ch of
  555. #0, {This can't be done by range, because a bug in FPC}
  556. #1..#31,
  557. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  558. '"' : s:='\"';
  559. '\' : s:='\\';
  560. else
  561. s:=ch;
  562. end;
  563. AsmWrite(s);
  564. inc(pos,length(s));
  565. if (pos>line_length) or (i=pai_string(hp)^.len) then
  566. begin
  567. AsmWriteLn('"');
  568. pos:=0;
  569. end;
  570. end;
  571. end;
  572. ait_label :
  573. begin
  574. if (pai_label(hp)^.l^.is_used) then
  575. begin
  576. if pai_label(hp)^.l^.typ=AS_GLOBAL then
  577. AsmWriteLn('.globl'#9+pai_label(hp)^.l^.name);
  578. AsmWriteLn(pai_label(hp)^.l^.name+':');
  579. end;
  580. end;
  581. ait_symbol :
  582. begin
  583. if pai_symbol(hp)^.is_global then
  584. AsmWriteLn('.globl'#9+pai_symbol(hp)^.sym^.name);
  585. if target_info.target=target_i386_linux then
  586. begin
  587. AsmWrite(#9'.type'#9+pai_symbol(hp)^.sym^.name);
  588. if assigned(pai(hp^.next)) and
  589. (pai(hp^.next)^.typ in [ait_const_symbol,ait_const_rva,
  590. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  591. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  592. AsmWriteLn(',@object')
  593. else
  594. AsmWriteLn(',@function');
  595. if pai_symbol(hp)^.sym^.size>0 then
  596. AsmWriteLn(#9'.size'#9+pai_symbol(hp)^.sym^.name+', '+tostr(pai_symbol(hp)^.sym^.size));
  597. end;
  598. AsmWriteLn(pai_symbol(hp)^.sym^.name+':');
  599. end;
  600. ait_symbol_end :
  601. begin
  602. if target_info.target=target_i386_linux then
  603. begin
  604. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  605. inc(symendcount);
  606. AsmWriteLn(s+':');
  607. AsmWriteLn(#9'.size'#9+pai_symbol(hp)^.sym^.name+', '+s+' - '+pai_symbol(hp)^.sym^.name);
  608. end;
  609. end;
  610. ait_instruction :
  611. begin
  612. op:=pai386(hp)^.opcode;
  613. calljmp:=is_calljmp(op);
  614. { call maybe not translated to calll }
  615. s:=#9+att_op2str[op]+cond2str[pai386(hp)^.condition];
  616. if (not calljmp) and
  617. (not att_nosuffix[op]) and
  618. not(
  619. (pai386(hp)^.oper[0].typ=top_reg) and
  620. (pai386(hp)^.oper[0].reg in [R_ST..R_ST7])
  621. ) then
  622. s:=s+att_opsize2str[pai386(hp)^.opsize];
  623. { process operands }
  624. if pai386(hp)^.ops<>0 then
  625. begin
  626. { call and jmp need an extra handling }
  627. { this code is only called if jmp isn't a labeled instruction }
  628. if calljmp then
  629. s:=s+#9+getopstr_jmp(pai386(hp)^.oper[0])
  630. else
  631. begin
  632. for i:=0to pai386(hp)^.ops-1 do
  633. begin
  634. if i=0 then
  635. sep:=#9
  636. else
  637. sep:=',';
  638. s:=s+sep+getopstr(pai386(hp)^.oper[i])
  639. end;
  640. end;
  641. end;
  642. AsmWriteLn(s);
  643. end;
  644. {$ifdef GDB}
  645. ait_stabs :
  646. begin
  647. AsmWrite(#9'.stabs ');
  648. AsmWritePChar(pai_stabs(hp)^.str);
  649. AsmLn;
  650. end;
  651. ait_stabn :
  652. begin
  653. AsmWrite(#9'.stabn ');
  654. AsmWritePChar(pai_stabn(hp)^.str);
  655. AsmLn;
  656. end;
  657. ait_force_line :
  658. stabslastfileinfo.line:=0;
  659. ait_stab_function_name:
  660. funcname:=pai_stab_function_name(hp)^.str;
  661. {$endif GDB}
  662. ait_cut :
  663. begin
  664. if SmartAsm then
  665. begin
  666. { only reset buffer if nothing has changed }
  667. if AsmSize=AsmStartSize then
  668. AsmClear
  669. else
  670. begin
  671. AsmClose;
  672. DoAssemble;
  673. if pai_cut(hp)^.EndName then
  674. IsEndFile:=true;
  675. AsmCreate;
  676. end;
  677. { avoid empty files }
  678. while assigned(hp^.next) and (pai(hp^.next)^.typ in [ait_cut,ait_section,ait_comment]) do
  679. begin
  680. if pai(hp^.next)^.typ=ait_section then
  681. lastsec:=pai_section(hp^.next)^.sec;
  682. hp:=pai(hp^.next);
  683. end;
  684. {$ifdef GDB}
  685. { force write of filename }
  686. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  687. includecount:=0;
  688. funcname:=nil;
  689. WriteFileLineInfo(hp^.fileinfo);
  690. {$endif GDB}
  691. if lastsec<>sec_none then
  692. AsmWriteLn(ait_section2str(lastsec));
  693. AsmStartSize:=AsmSize;
  694. end;
  695. end;
  696. ait_marker :
  697. ;
  698. else
  699. internalerror(10000);
  700. end;
  701. hp:=pai(hp^.next);
  702. end;
  703. end;
  704. procedure ti386attasmlist.WriteAsmList;
  705. var
  706. p:dirstr;
  707. n:namestr;
  708. e:extstr;
  709. {$ifdef GDB}
  710. fileinfo : tfileposinfo;
  711. {$endif GDB}
  712. begin
  713. {$ifdef EXTDEBUG}
  714. if assigned(current_module^.mainsource) then
  715. Comment(v_info,'Start writing att-styled assembler output for '+current_module^.mainsource^);
  716. {$endif}
  717. LastSec:=sec_none;
  718. {$ifdef GDB}
  719. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  720. {$endif GDB}
  721. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  722. LastInfile:=nil;
  723. if assigned(current_module^.mainsource) then
  724. fsplit(current_module^.mainsource^,p,n,e)
  725. else
  726. begin
  727. p:=inputdir;
  728. n:=inputfile;
  729. e:=inputextension;
  730. end;
  731. { to get symify to work }
  732. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  733. {$ifdef GDB}
  734. n_line:=n_bssline;
  735. funcname:=nil;
  736. linecount:=1;
  737. includecount:=0;
  738. fileinfo.fileindex:=1;
  739. fileinfo.line:=1;
  740. { Write main file }
  741. WriteFileLineInfo(fileinfo);
  742. {$endif GDB}
  743. AsmStartSize:=AsmSize;
  744. symendcount:=0;
  745. countlabelref:=false;
  746. If (cs_debuginfo in aktmoduleswitches) then
  747. WriteTree(debuglist);
  748. WriteTree(codesegment);
  749. WriteTree(datasegment);
  750. WriteTree(consts);
  751. WriteTree(rttilist);
  752. Writetree(resourcestringlist);
  753. WriteTree(bsssegment);
  754. Writetree(importssection);
  755. { exports are written by DLLTOOL
  756. if we use it so don't insert it twice (PM) }
  757. if not RelocSection then
  758. Writetree(exportssection);
  759. Writetree(resourcesection);
  760. countlabelref:=true;
  761. AsmLn;
  762. {$ifdef EXTDEBUG}
  763. if assigned(current_module^.mainsource) then
  764. comment(v_info,'Done writing att-styled assembler output for '+current_module^.mainsource^);
  765. {$endif EXTDEBUG}
  766. end;
  767. end.
  768. {
  769. $Log$
  770. Revision 1.9 1999-08-10 12:26:20 pierre
  771. * avoid double .edata section if using DLLTOOL
  772. Revision 1.8 1999/08/04 00:22:34 florian
  773. * renamed i386asm and i386base to cpuasm and cpubase
  774. Revision 1.7 1999/07/30 12:26:07 peter
  775. * write .size only for linux
  776. Revision 1.6 1999/07/29 20:53:56 peter
  777. * write .size also
  778. Revision 1.5 1999/07/22 09:37:29 florian
  779. + resourcestring implemented
  780. + start of longstring support
  781. Revision 1.4 1999/07/18 10:19:38 florian
  782. * made it compilable with Dlephi 4 again
  783. + fixed problem with large stack allocations on win32
  784. Revision 1.3 1999/07/03 00:27:04 peter
  785. * better smartlinking support
  786. Revision 1.2 1999/06/22 15:25:14 peter
  787. * merged
  788. Revision 1.1.2.1 1999/06/22 15:23:08 peter
  789. * reinserted
  790. Revision 1.100 1999/06/22 14:41:20 peter
  791. * merged
  792. Revision 1.99 1999/06/14 17:47:44 peter
  793. * merged
  794. Revision 1.97.2.3 1999/06/22 14:40:27 peter
  795. * small change to fpureg check
  796. Revision 1.97.2.2 1999/06/22 14:20:19 peter
  797. * fixed parsing and writing of fpureg
  798. Revision 1.97.2.1 1999/06/14 17:30:41 peter
  799. * align fixes from pierre
  800. Revision 1.98 1999/06/11 22:54:10 pierre
  801. * .align problem treated :
  802. .align is considered as .p2align on go32v1 and go32v2
  803. and as .balign on other targets
  804. + ra386att supports also .balign and .p2align
  805. * ag386att uses .balign allways
  806. Revision 1.97 1999/06/09 23:00:06 peter
  807. * small ansistring fixes
  808. * val_ansistr_sint destsize changed to longint
  809. * don't write low/hi ascii with -al
  810. Revision 1.96 1999/06/06 15:53:13 peter
  811. * suffix adding can be turned of for some tasmops in att_nosuffix array
  812. Revision 1.95 1999/05/27 19:43:56 peter
  813. * removed oldasm
  814. * plabel -> pasmlabel
  815. * -a switches to source writing automaticly
  816. * assembler readers OOPed
  817. * asmsymbol automaticly external
  818. * jumptables and other label fixes for asm readers
  819. Revision 1.94 1999/05/23 18:41:54 florian
  820. * better error recovering in typed constants
  821. * some problems with arrays of const fixed, some problems
  822. due my previous
  823. - the location type of array constructor is now LOC_MEM
  824. - the pushing of high fixed
  825. - parameter copying fixed
  826. - zero temp. allocation removed
  827. * small problem in the assembler writers fixed:
  828. ref to nil wasn't written correctly
  829. Revision 1.93 1999/05/21 13:54:39 peter
  830. * NEWLAB for label as symbol
  831. Revision 1.92 1999/05/16 17:03:05 peter
  832. * better file position info
  833. Revision 1.91 1999/05/12 00:19:36 peter
  834. * removed R_DEFAULT_SEG
  835. * uniform float names
  836. Revision 1.90 1999/05/08 19:52:31 peter
  837. + MessagePos() which is enhanced Message() function but also gets the
  838. position info
  839. * Removed comp warnings
  840. Revision 1.89 1999/05/07 00:38:22 pierre
  841. * comp fixes 2
  842. Revision 1.88 1999/05/07 00:09:35 pierre
  843. * better comp output
  844. Revision 1.87 1999/05/06 09:05:06 peter
  845. * generic write_float and str_float
  846. * fixed constant float conversions
  847. Revision 1.86 1999/05/04 21:44:29 florian
  848. * changes to compile it with Delphi 4.0
  849. Revision 1.85 1999/05/02 23:29:57 peter
  850. * readded condition, becuase it's needed for set<cond> and cmov<cond> !
  851. Revision 1.84 1999/05/02 22:41:47 peter
  852. * moved section names to systems
  853. * fixed nasm,intel writer
  854. Revision 1.83 1999/05/02 21:33:51 florian
  855. * several bugs regarding -Or fixed
  856. Revision 1.82 1999/05/01 13:47:51 peter
  857. * fix hack for fsub
  858. Revision 1.81 1999/05/01 13:23:56 peter
  859. * merged nasm compiler
  860. * old asm moved to oldasm/
  861. Revision 1.80 1999/04/17 22:17:04 pierre
  862. * ifdef USE_OP3 released (changed into ifndef NO_OP3)
  863. * SHRD and SHLD first operand (ATT syntax) can only be CL reg or immediate const
  864. Revision 1.79 1999/04/16 11:49:37 peter
  865. + tempalloc
  866. + -at to show temp alloc info in .s file
  867. Revision 1.78 1999/04/16 10:00:54 pierre
  868. + ifdef USE_OP3 code :
  869. added all missing op_... constructors for tai386 needed
  870. for SHRD,SHLD and IMUL code in assembler readers
  871. (check in tests/tbs0123.pp)
  872. Revision 1.77 1999/04/14 12:44:46 daniel
  873. * Proper fix for the .bss conflict
  874. Revision 1.76 1999/04/14 11:43:25 michael
  875. + reverted back to .section .bss
  876. Revision 1.75 1999/04/13 08:45:33 daniel
  877. * EMX assembler prefers .bss instead of .section .bss
  878. Revision 1.74 1999/04/10 16:14:59 peter
  879. * fixed browcol
  880. + -ar to show regalloc info in .s file
  881. Revision 1.73 1999/04/09 08:33:45 peter
  882. * write * before register with call for the stricter as versions
  883. Revision 1.72 1999/03/31 13:55:02 peter
  884. * assembler inlining working for ag386bin
  885. Revision 1.71 1999/03/29 16:05:42 peter
  886. * optimizer working for ag386bin
  887. Revision 1.70 1999/03/10 21:48:21 florian
  888. * bug0218 fixed, ag386att writes now all real types as byte
  889. sequences to minimize rouding error, in -al mode the
  890. value is written as comment
  891. Revision 1.69 1999/03/10 13:25:43 pierre
  892. section order changed to get closer output from coff writer
  893. Revision 1.68 1999/03/02 02:56:09 peter
  894. + stabs support for binary writers
  895. * more fixes and missing updates from the previous commit :(
  896. Revision 1.67 1999/03/01 15:46:15 peter
  897. * ag386bin finally make cycles correct
  898. * prefixes are now also normal opcodes
  899. Revision 1.66 1999/02/26 00:48:12 peter
  900. * assembler writers fixed for ag386bin
  901. Revision 1.65 1999/02/25 21:02:17 peter
  902. * ag386bin updates
  903. + coff writer
  904. Revision 1.64 1999/02/22 02:14:57 peter
  905. * updates for ag386bin
  906. Revision 1.63 1999/02/17 10:16:25 peter
  907. * small fixes for the binary writer
  908. Revision 1.62 1999/01/12 14:21:26 peter
  909. * fixed pushw warning
  910. Revision 1.61 1998/12/29 18:50:04 jonas
  911. * don't write debug info if not (cs_debuginfo in aktmoduleswitches)
  912. Revision 1.60 1998/12/23 22:53:43 peter
  913. * don't count ait_marker for lineinfo
  914. Revision 1.58 1998/12/11 00:02:38 peter
  915. + globtype,tokens,version unit splitted from globals
  916. Revision 1.57 1998/12/01 23:36:32 pierre
  917. * zero padded alignment was buggy
  918. Revision 1.56 1998/12/01 11:19:37 peter
  919. * fixed range problem with in [tasmop]
  920. Revision 1.55 1998/11/30 09:42:53 pierre
  921. * some range check bugs fixed (still not working !)
  922. + added DLL writing support for win32 (also accepts variables)
  923. + TempAnsi for code that could be used for Temporary ansi strings
  924. handling
  925. Revision 1.54 1998/11/17 10:04:13 pierre
  926. * zero indexed file not searched
  927. Revision 1.53 1998/11/17 00:26:08 peter
  928. * fixed for $H+
  929. Revision 1.52 1998/11/12 11:19:32 pierre
  930. * fix for first line of function break
  931. Revision 1.51 1998/11/09 09:21:18 pierre
  932. * fix for stabs line infos
  933. Revision 1.50 1998/11/06 09:49:25 pierre
  934. * n_line stuff cleaned
  935. Revision 1.49 1998/10/26 23:07:02 peter
  936. * fixpath fix
  937. Revision 1.48 1998/10/15 15:08:39 pierre
  938. * removed lots of unnecessary inputfile system.open calls
  939. (made a big speed decrease on go32v2 !)
  940. Revision 1.47 1998/10/13 14:01:05 peter
  941. * fixed -al
  942. Revision 1.46 1998/10/13 13:10:07 peter
  943. * new style for m68k/i386 infos and enums
  944. Revision 1.45 1998/10/12 12:20:39 pierre
  945. + added tai_const_symbol_offset
  946. for r : pointer = @var.field;
  947. * better message for different arg names on implementation
  948. of function
  949. Revision 1.44 1998/10/06 17:16:32 pierre
  950. * some memory leaks fixed (thanks to Peter for heaptrc !)
  951. Revision 1.43 1998/10/01 20:19:12 jonas
  952. + ait_marker support
  953. Revision 1.42 1998/09/28 16:57:08 pierre
  954. * changed all length(p^.value_str^) into str_length(p)
  955. to get it work with and without ansistrings
  956. * changed sourcefiles field of tmodule to a pointer
  957. Revision 1.41 1998/09/20 17:11:19 jonas
  958. * released REGALLOC
  959. Revision 1.40 1998/09/16 17:58:34 jonas
  960. * fixed -dRegAlloc and -dDRegalloc problems
  961. Revision 1.39 1998/09/11 11:30:41 pierre
  962. -al -g option bug corrected
  963. Revision 1.38.2.1 1998/09/11 10:49:09 pierre
  964. * bug with -g -al option removed
  965. Revision 1.38 1998/09/07 22:23:35 peter
  966. * fixed for no gdb compiler
  967. Revision 1.37 1998/09/07 18:33:34 peter
  968. + smartlinking for win95 imports
  969. Revision 1.36 1998/09/04 17:34:19 pierre
  970. * bug with datalabel corrected
  971. + assembler errors better commented
  972. * one nested record crash removed
  973. Revision 1.35 1998/09/03 17:08:38 pierre
  974. * better lines for stabs
  975. (no scroll back to if before else part
  976. no return to case line at jump outside case)
  977. + source lines also if not in order
  978. Revision 1.34 1998/09/03 11:22:41 peter
  979. + support for cs_asm_source
  980. Revision 1.33 1998/08/26 10:06:33 peter
  981. * reduce amount of asmfiles generated
  982. * no stabs are written in writefilelineinfo when debuginfo is off
  983. Revision 1.32 1998/08/20 09:26:35 pierre
  984. + funcret setting in underproc testing
  985. compile with _dTEST_FUNCRET
  986. Revision 1.31 1998/08/11 14:01:16 peter
  987. * @object type also for extended and comp
  988. Revision 1.30 1998/08/10 23:56:02 peter
  989. * fixed extended writing
  990. Revision 1.29 1998/08/10 14:49:35 peter
  991. + localswitches, moduleswitches, globalswitches splitting
  992. Revision 1.27 1998/08/08 12:30:07 florian
  993. * extended writing improved
  994. Revision 1.26 1998/08/08 10:19:16 florian
  995. * small fixes to write the extended type correct
  996. Revision 1.28 1998/08/10 10:01:33 peter
  997. * Fixed with GDB undefined
  998. Revision 1.25 1998/08/06 16:53:25 pierre
  999. * debugging info corrected
  1000. Revision 1.24 1998/07/14 14:46:37 peter
  1001. * released NEWINPUT
  1002. Revision 1.23 1998/07/07 11:19:51 peter
  1003. + NEWINPUT for a better inputfile and scanner object
  1004. Revision 1.22 1998/06/08 22:59:42 peter
  1005. * smartlinking works for win32
  1006. * some defines to exclude some compiler parts
  1007. Revision 1.21 1998/06/05 17:46:01 peter
  1008. * tp doesn't like comp() typecast
  1009. Revision 1.20 1998/06/04 23:51:27 peter
  1010. * m68k compiles
  1011. + .def file creation moved to gendef.pas so it could also be used
  1012. for win32
  1013. Revision 1.19 1998/05/31 14:13:29 peter
  1014. * fixed call bugs with assembler readers
  1015. + OPR_SYMBOL to hold a symbol in the asm parser
  1016. * fixed staticsymtable vars which were acessed through %ebp instead of
  1017. name
  1018. Revision 1.18 1998/05/28 17:24:25 peter
  1019. - $R- for tp to solve range errors with in[]
  1020. Revision 1.17 1998/05/25 17:11:34 pierre
  1021. * firstpasscount bug fixed
  1022. now all is already set correctly the first time
  1023. under EXTDEBUG try -gp to skip all other firstpasses
  1024. it works !!
  1025. * small bug fixes
  1026. - for smallsets with -dTESTSMALLSET
  1027. - some warnings removed (by correcting code !)
  1028. Revision 1.16 1998/05/23 01:20:54 peter
  1029. + aktasmmode, aktoptprocessor, aktoutputformat
  1030. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  1031. + $LIBNAME to set the library name where the unit will be put in
  1032. * splitted cgi386 a bit (codeseg to large for bp7)
  1033. * nasm, tasm works again. nasm moved to ag386nsm.pas
  1034. Revision 1.15 1998/05/11 13:07:53 peter
  1035. + $ifdef NEWPPU for the new ppuformat
  1036. + $define GDB not longer required
  1037. * removed all warnings and stripped some log comments
  1038. * no findfirst/findnext anymore to remove smartlink *.o files
  1039. Revision 1.14 1998/05/06 18:36:53 peter
  1040. * tai_section extended with code,data,bss sections and enumerated type
  1041. * ident 'compiled by FPC' moved to pmodules
  1042. * small fix for smartlink
  1043. Revision 1.13 1998/05/06 08:38:32 pierre
  1044. * better position info with UseTokenInfo
  1045. UseTokenInfo greatly simplified
  1046. + added check for changed tree after first time firstpass
  1047. (if we could remove all the cases were it happen
  1048. we could skip all firstpass if firstpasscount > 1)
  1049. Only with ExtDebug
  1050. Revision 1.12 1998/05/04 17:54:24 peter
  1051. + smartlinking works (only case jumptable left todo)
  1052. * redesign of systems.pas to support assemblers and linkers
  1053. + Unitname is now also in the PPU-file, increased version to 14
  1054. Revision 1.11 1998/05/01 07:43:52 florian
  1055. + basics for rtti implemented
  1056. + switch $m (generate rtti for published sections)
  1057. Revision 1.10 1998/04/30 15:59:39 pierre
  1058. * GDB works again better :
  1059. correct type info in one pass
  1060. + UseTokenInfo for better source position
  1061. * fixed one remaining bug in scanner for line counts
  1062. * several little fixes
  1063. Revision 1.9 1998/04/29 10:33:41 pierre
  1064. + added some code for ansistring (not complete nor working yet)
  1065. * corrected operator overloading
  1066. * corrected nasm output
  1067. + started inline procedures
  1068. + added starstarn : use ** for exponentiation (^ gave problems)
  1069. + started UseTokenInfo cond to get accurate positions
  1070. Revision 1.8 1998/04/28 08:23:58 pierre
  1071. * bug in stabn generation fixed
  1072. Revision 1.7 1998/04/27 23:10:27 peter
  1073. + new scanner
  1074. * $makelib -> if smartlink
  1075. * small filename fixes pmodule.setfilename
  1076. * moved import from files.pas -> import.pas
  1077. Revision 1.6 1998/04/21 11:30:13 peter
  1078. * fixed $ifdef regalloc
  1079. Revision 1.5 1998/04/16 16:53:24 jonas
  1080. * changed $ifdef regalloc to $ifdef dregalloc (= debugging info)
  1081. Revision 1.4 1998/04/09 15:46:38 florian
  1082. + register allocation tracing stuff added
  1083. Revision 1.3 1998/04/08 16:58:00 pierre
  1084. * several bugfixes
  1085. ADD ADC and AND are also sign extended
  1086. nasm output OK (program still crashes at end
  1087. and creates wrong assembler files !!)
  1088. procsym types sym in tdef removed !!
  1089. }