2
0

ag386att.pas 39 KB

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