ag386att.pas 39 KB

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