ag386bin.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements an binary assembler output class
  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 ag386bin;
  22. {$define MULTIPASS}
  23. {$define EXTERNALBSS}
  24. interface
  25. uses
  26. cpubase,cobjects,aasm,files,assemble;
  27. type
  28. togtype=(og_none,og_dbg,og_coff,og_pecoff);
  29. pi386binasmlist=^ti386binasmlist;
  30. ti386binasmlist=object
  31. SmartAsm : boolean;
  32. constructor init(t:togtype;smart:boolean);
  33. destructor done;
  34. procedure WriteBin;
  35. private
  36. { the aasmoutput lists that need to be processed }
  37. lists : byte;
  38. list : array[1..maxoutputlists] of paasmoutput;
  39. { current processing }
  40. currlistidx : byte;
  41. currlist : paasmoutput;
  42. currpass : byte;
  43. {$ifdef GDB}
  44. n_line : byte; { different types of source lines }
  45. linecount,
  46. includecount : longint;
  47. funcname : pasmsymbol;
  48. stabslastfileinfo : tfileposinfo;
  49. procedure convertstabs(p:pchar);
  50. {$ifdef unused}
  51. procedure emitsymbolstabs(s : string;nidx,nother,line : longint;firstasm,secondasm : pasmsymbol);
  52. {$endif}
  53. procedure emitlineinfostabs(nidx,line : longint);
  54. procedure emitstabs(s:string);
  55. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  56. procedure StartFileLineInfo;
  57. {$endif}
  58. function MaybeNextList(var hp:pai):boolean;
  59. function TreePass0(hp:pai):pai;
  60. function TreePass1(hp:pai):pai;
  61. function TreePass2(hp:pai):pai;
  62. procedure writetree;
  63. procedure writetreesmart;
  64. end;
  65. implementation
  66. uses
  67. strings,
  68. globtype,globals,systems,verbose,
  69. cpuasm,
  70. {$ifdef GDB}
  71. gdb,
  72. {$endif}
  73. og386,og386dbg,og386cff;
  74. {$ifdef GDB}
  75. procedure ti386binasmlist.convertstabs(p:pchar);
  76. var
  77. ofs,
  78. nidx,nother,ii,i,line,j : longint;
  79. code : integer;
  80. hp : pchar;
  81. reloc : boolean;
  82. sec : tsection;
  83. ps : pasmsymbol;
  84. s : string;
  85. begin
  86. ofs:=0;
  87. reloc:=true;
  88. ps:=nil;
  89. sec:=sec_none;
  90. if p[0]='"' then
  91. begin
  92. i:=1;
  93. { we can have \" inside the string !! PM }
  94. while not ((p[i]='"') and (p[i-1]<>'\')) do
  95. inc(i);
  96. p[i]:=#0;
  97. ii:=i;
  98. hp:=@p[1];
  99. s:=StrPas(@P[i+2]);
  100. end
  101. else
  102. begin
  103. hp:=nil;
  104. s:=StrPas(P);
  105. i:=-2; {needed below (PM) }
  106. end;
  107. { When in pass 1 then only alloc and leave }
  108. if currpass=1 then
  109. begin
  110. objectalloc^.staballoc(hp);
  111. if assigned(hp) then
  112. p[i]:='"';
  113. exit;
  114. end;
  115. { Parse the rest of the stabs }
  116. if s='' then
  117. internalerror(33000);
  118. j:=pos(',',s);
  119. if j=0 then
  120. internalerror(33001);
  121. Val(Copy(s,1,j-1),nidx,code);
  122. if code<>0 then
  123. internalerror(33002);
  124. i:=i+2+j;
  125. Delete(s,1,j);
  126. j:=pos(',',s);
  127. if (j=0) then
  128. internalerror(33003);
  129. Val(Copy(s,1,j-1),nother,code);
  130. if code<>0 then
  131. internalerror(33004);
  132. i:=i+j;
  133. Delete(s,1,j);
  134. j:=pos(',',s);
  135. if j=0 then
  136. begin
  137. j:=256;
  138. ofs:=-1;
  139. end;
  140. Val(Copy(s,1,j-1),line,code);
  141. if code<>0 then
  142. internalerror(33005);
  143. if ofs=0 then
  144. begin
  145. Delete(s,1,j);
  146. i:=i+j;
  147. Val(s,ofs,code);
  148. if code=0 then
  149. reloc:=false
  150. else
  151. begin
  152. ofs:=0;
  153. s:=strpas(@p[i]);
  154. { handle asmsymbol or
  155. asmsymbol - asmsymbol }
  156. j:=pos(' ',s);
  157. if j=0 then
  158. j:=pos('-',s);
  159. { single asmsymbol }
  160. if j=0 then
  161. j:=256;
  162. { the symbol can be external
  163. so we must use newasmsymbol and
  164. not getasmsymbol !! PM }
  165. ps:=newasmsymbol(copy(s,1,j-1));
  166. if not assigned(ps) then
  167. internalerror(33006)
  168. else
  169. begin
  170. sec:=ps^.section;
  171. ofs:=ps^.address;
  172. reloc:=true;
  173. end;
  174. if j<256 then
  175. begin
  176. i:=i+j;
  177. s:=strpas(@p[i]);
  178. if (s<>'') and (s[1]=' ') then
  179. begin
  180. j:=0;
  181. while (s[j+1]=' ') do
  182. inc(j);
  183. i:=i+j;
  184. s:=strpas(@p[i]);
  185. end;
  186. ps:=getasmsymbol(s);
  187. if not assigned(ps) then
  188. internalerror(33007)
  189. else
  190. begin
  191. if ps^.section<>sec then
  192. internalerror(33008);
  193. ofs:=ofs-ps^.address;
  194. reloc:=false;
  195. end;
  196. end;
  197. end;
  198. end;
  199. { external bss need speical handling (PM) }
  200. if assigned(ps) and (ps^.section=sec_none) then
  201. objectoutput^.WriteSymStabs(sec,ofs,hp,ps,nidx,nother,line,reloc)
  202. else
  203. objectoutput^.WriteStabs(sec,ofs,hp,nidx,nother,line,reloc);
  204. if assigned(hp) then
  205. p[ii]:='"';
  206. end;
  207. {$ifdef unused}
  208. procedure ti386binasmlist.emitsymbolstabs(s : string;nidx,nother,line : longint;
  209. firstasm,secondasm : pasmsymbol);
  210. var
  211. hp : pchar;
  212. begin
  213. if s='' then
  214. hp:=nil
  215. else
  216. begin
  217. s:=s+#0;
  218. hp:=@s[1];
  219. end;
  220. if not assigned(secondasm) then
  221. begin
  222. if not assigned(firstasm) then
  223. internalerror(33009);
  224. objectoutput^.WriteStabs(firstasm^.section,firstasm^.address,hp,nidx,nother,line,true);
  225. end
  226. else
  227. begin
  228. if firstasm^.section<>secondasm^.section then
  229. internalerror(33010);
  230. objectoutput^.WriteStabs(firstasm^.section,firstasm^.address-secondasm^.address,
  231. hp,nidx,nother,line,false);
  232. end;
  233. end;
  234. {$endif}
  235. procedure ti386binasmlist.emitlineinfostabs(nidx,line : longint);
  236. var
  237. sec : tsection;
  238. begin
  239. if currpass=1 then
  240. begin
  241. objectalloc^.staballoc(nil);
  242. exit;
  243. end;
  244. if (nidx=n_textline) and assigned(funcname) and
  245. (target_os.use_function_relative_addresses) then
  246. objectoutput^.WriteStabs(sec_code,pgenericcoffoutput(objectoutput)^.sects[sec_code]^.len-funcname^.address,
  247. nil,nidx,0,line,false)
  248. else
  249. begin
  250. if nidx=n_textline then
  251. sec:=sec_code
  252. else if nidx=n_dataline then
  253. sec:=sec_data
  254. else
  255. sec:=sec_bss;
  256. objectoutput^.WriteStabs(sec,pgenericcoffoutput(objectoutput)^.sects[sec]^.len,
  257. nil,nidx,0,line,true);
  258. end;
  259. end;
  260. procedure ti386binasmlist.emitstabs(s:string);
  261. begin
  262. s:=s+#0;
  263. ConvertStabs(@s[1]);
  264. end;
  265. procedure ti386binasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  266. var
  267. curr_n : byte;
  268. hp : pasmsymbol;
  269. infile : pinputfile;
  270. begin
  271. if not (cs_debuginfo in aktmoduleswitches) then
  272. exit;
  273. { file changed ? (must be before line info) }
  274. if (fileinfo.fileindex<>0) and
  275. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  276. begin
  277. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  278. if includecount=0 then
  279. curr_n:=n_sourcefile
  280. else
  281. curr_n:=n_includefile;
  282. { get symbol for this includefile }
  283. hp:=newasmsymbol('Ltext'+ToStr(IncludeCount));
  284. if currpass=1 then
  285. begin
  286. hp^.settyp(AS_LOCAL);
  287. hp^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  288. end
  289. else
  290. objectoutput^.writesymbol(hp);
  291. { emit stabs }
  292. if (infile^.path^<>'') then
  293. EmitStabs('"'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+tostr(curr_n)+
  294. ',0,0,Ltext'+ToStr(IncludeCount));
  295. EmitStabs('"'+lower(FixFileName(infile^.name^))+'",'+tostr(curr_n)+
  296. ',0,0,Ltext'+ToStr(IncludeCount));
  297. inc(includecount);
  298. end;
  299. { line changed ? }
  300. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  301. emitlineinfostabs(n_line,fileinfo.line);
  302. stabslastfileinfo:=fileinfo;
  303. end;
  304. procedure ti386binasmlist.StartFileLineInfo;
  305. var
  306. fileinfo : tfileposinfo;
  307. begin
  308. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  309. n_line:=n_textline;
  310. funcname:=nil;
  311. linecount:=1;
  312. includecount:=0;
  313. fileinfo.fileindex:=1;
  314. fileinfo.line:=1;
  315. WriteFileLineInfo(fileinfo);
  316. end;
  317. {$endif GDB}
  318. function ti386binasmlist.MaybeNextList(var hp:pai):boolean;
  319. begin
  320. { maybe end of list }
  321. while not assigned(hp) do
  322. begin
  323. if currlistidx<lists then
  324. begin
  325. inc(currlistidx);
  326. currlist:=list[currlistidx];
  327. hp:=pai(currlist^.first);
  328. end
  329. else
  330. begin
  331. MaybeNextList:=false;
  332. exit;
  333. end;
  334. end;
  335. MaybeNextList:=true;
  336. end;
  337. function ti386binasmlist.TreePass0(hp:pai):pai;
  338. var
  339. l : longint;
  340. begin
  341. while assigned(hp) do
  342. begin
  343. case hp^.typ of
  344. ait_align :
  345. begin
  346. { always use the maximum fillsize in this pass to avoid possible
  347. short jumps to become out of range }
  348. pai_align(hp)^.fillsize:=pai_align(hp)^.aligntype;
  349. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  350. end;
  351. ait_datablock :
  352. begin
  353. {$ifdef EXTERNALBSS}
  354. if not SmartAsm then
  355. begin
  356. if not pai_datablock(hp)^.is_global then
  357. begin
  358. l:=pai_datablock(hp)^.size;
  359. if l>2 then
  360. objectalloc^.sectionalign(4)
  361. else if l>1 then
  362. objectalloc^.sectionalign(2);
  363. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  364. end;
  365. end
  366. else
  367. begin
  368. {$endif}
  369. l:=pai_datablock(hp)^.size;
  370. if l>2 then
  371. objectalloc^.sectionalign(4)
  372. else if l>1 then
  373. objectalloc^.sectionalign(2);
  374. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  375. end;
  376. end;
  377. ait_const_32bit :
  378. objectalloc^.sectionalloc(4);
  379. ait_const_16bit :
  380. objectalloc^.sectionalloc(2);
  381. ait_const_8bit :
  382. objectalloc^.sectionalloc(1);
  383. ait_real_80bit :
  384. objectalloc^.sectionalloc(10);
  385. ait_real_64bit :
  386. objectalloc^.sectionalloc(8);
  387. ait_real_32bit :
  388. objectalloc^.sectionalloc(4);
  389. ait_comp_64bit :
  390. objectalloc^.sectionalloc(8);
  391. ait_const_rva,
  392. ait_const_symbol :
  393. objectalloc^.sectionalloc(4);
  394. ait_section:
  395. objectalloc^.setsection(pai_section(hp)^.sec);
  396. ait_symbol :
  397. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  398. ait_label :
  399. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  400. ait_string :
  401. objectalloc^.sectionalloc(pai_string(hp)^.len);
  402. ait_instruction :
  403. begin
  404. { reset instructions which could change in pass 2 }
  405. paicpu(hp)^.resetpass2;
  406. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  407. end;
  408. ait_cut :
  409. if SmartAsm then
  410. break;
  411. end;
  412. hp:=pai(hp^.next);
  413. end;
  414. TreePass0:=hp;
  415. end;
  416. function ti386binasmlist.TreePass1(hp:pai):pai;
  417. var
  418. l : longint;
  419. begin
  420. while assigned(hp) do
  421. begin
  422. {$ifdef GDB}
  423. { write stabs }
  424. if (cs_debuginfo in aktmoduleswitches) then
  425. begin
  426. if (objectalloc^.currsec<>sec_none) and
  427. not(hp^.typ in [
  428. ait_label,
  429. ait_regalloc,ait_tempalloc,
  430. ait_stabn,ait_stabs,ait_section,
  431. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  432. WriteFileLineInfo(hp^.fileinfo);
  433. end;
  434. {$endif GDB}
  435. case hp^.typ of
  436. ait_align :
  437. begin
  438. { here we must determine the fillsize which is used in pass2 }
  439. pai_align(hp)^.fillsize:=align(objectalloc^.sectionsize,pai_align(hp)^.aligntype)-
  440. objectalloc^.sectionsize;
  441. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  442. end;
  443. ait_datablock :
  444. begin
  445. if objectalloc^.currsec<>sec_bss then
  446. Message(asmw_e_alloc_data_only_in_bss);
  447. {$ifdef EXTERNALBSS}
  448. if not SmartAsm then
  449. begin
  450. if pai_datablock(hp)^.is_global then
  451. begin
  452. pai_datablock(hp)^.sym^.settyp(AS_EXTERNAL);
  453. pai_datablock(hp)^.sym^.setaddress(sec_none,pai_datablock(hp)^.size,pai_datablock(hp)^.size);
  454. end
  455. else
  456. begin
  457. l:=pai_datablock(hp)^.size;
  458. if l>2 then
  459. objectalloc^.sectionalign(4)
  460. else if l>1 then
  461. objectalloc^.sectionalign(2);
  462. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  463. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,
  464. pai_datablock(hp)^.size);
  465. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  466. end;
  467. end
  468. else
  469. {$endif}
  470. begin
  471. if pai_datablock(hp)^.is_global then
  472. pai_datablock(hp)^.sym^.settyp(AS_GLOBAL)
  473. else
  474. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  475. l:=pai_datablock(hp)^.size;
  476. if l>2 then
  477. objectalloc^.sectionalign(4)
  478. else if l>1 then
  479. objectalloc^.sectionalign(2);
  480. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,pai_datablock(hp)^.size);
  481. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  482. end;
  483. end;
  484. ait_const_32bit :
  485. objectalloc^.sectionalloc(4);
  486. ait_const_16bit :
  487. objectalloc^.sectionalloc(2);
  488. ait_const_8bit :
  489. objectalloc^.sectionalloc(1);
  490. ait_real_80bit :
  491. objectalloc^.sectionalloc(10);
  492. ait_real_64bit :
  493. objectalloc^.sectionalloc(8);
  494. ait_real_32bit :
  495. objectalloc^.sectionalloc(4);
  496. ait_comp_64bit :
  497. objectalloc^.sectionalloc(8);
  498. ait_const_rva,
  499. ait_const_symbol :
  500. objectalloc^.sectionalloc(4);
  501. ait_section:
  502. begin
  503. objectalloc^.setsection(pai_section(hp)^.sec);
  504. {$ifdef GDB}
  505. case pai_section(hp)^.sec of
  506. sec_code : n_line:=n_textline;
  507. sec_data : n_line:=n_dataline;
  508. sec_bss : n_line:=n_bssline;
  509. else
  510. n_line:=n_dataline;
  511. end;
  512. stabslastfileinfo.line:=-1;
  513. {$endif GDB}
  514. end;
  515. {$ifdef GDB}
  516. ait_stabn :
  517. convertstabs(pai_stabn(hp)^.str);
  518. ait_stabs :
  519. convertstabs(pai_stabs(hp)^.str);
  520. ait_stab_function_name :
  521. if assigned(pai_stab_function_name(hp)^.str) then
  522. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  523. else
  524. funcname:=nil;
  525. ait_force_line :
  526. stabslastfileinfo.line:=0;
  527. {$endif}
  528. ait_symbol :
  529. begin
  530. if pai_symbol(hp)^.is_global then
  531. pai_symbol(hp)^.sym^.settyp(AS_GLOBAL)
  532. else
  533. pai_symbol(hp)^.sym^.settyp(AS_LOCAL);
  534. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  535. end;
  536. ait_label :
  537. begin
  538. if pai_label(hp)^.is_global then
  539. pai_label(hp)^.l^.settyp(AS_GLOBAL)
  540. else
  541. pai_label(hp)^.l^.settyp(AS_LOCAL);
  542. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  543. end;
  544. ait_string :
  545. objectalloc^.sectionalloc(pai_string(hp)^.len);
  546. ait_instruction :
  547. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  548. ait_direct :
  549. Message(asmw_f_direct_not_supported);
  550. ait_cut :
  551. if SmartAsm then
  552. break;
  553. end;
  554. hp:=pai(hp^.next);
  555. end;
  556. TreePass1:=hp;
  557. end;
  558. function ti386binasmlist.TreePass2(hp:pai):pai;
  559. var
  560. l : longint;
  561. {$ifdef I386}
  562. co : comp;
  563. {$endif I386}
  564. begin
  565. { main loop }
  566. while assigned(hp) do
  567. begin
  568. {$ifdef GDB}
  569. { write stabs }
  570. if cs_debuginfo in aktmoduleswitches then
  571. begin
  572. if (objectoutput^.currsec<>sec_none) and
  573. not(hp^.typ in [
  574. ait_label,
  575. ait_regalloc,ait_tempalloc,
  576. ait_stabn,ait_stabs,ait_section,
  577. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  578. WriteFileLineInfo(hp^.fileinfo);
  579. end;
  580. {$endif GDB}
  581. case hp^.typ of
  582. ait_align :
  583. objectoutput^.writebytes(pai_align(hp)^.getfillbuf^,pai_align(hp)^.fillsize);
  584. ait_section :
  585. begin
  586. objectoutput^.defaultsection(pai_section(hp)^.sec);
  587. {$ifdef GDB}
  588. case pai_section(hp)^.sec of
  589. sec_code : n_line:=n_textline;
  590. sec_data : n_line:=n_dataline;
  591. sec_bss : n_line:=n_bssline;
  592. else
  593. n_line:=n_dataline;
  594. end;
  595. stabslastfileinfo.line:=-1;
  596. {$endif GDB}
  597. end;
  598. ait_symbol :
  599. objectoutput^.writesymbol(pai_symbol(hp)^.sym);
  600. ait_datablock :
  601. begin
  602. objectoutput^.writesymbol(pai_datablock(hp)^.sym);
  603. if SmartAsm
  604. {$ifdef EXTERNALBSS}
  605. or (not pai_datablock(hp)^.is_global)
  606. {$endif}
  607. then
  608. begin
  609. l:=pai_datablock(hp)^.size;
  610. if l>2 then
  611. objectoutput^.writealign(4)
  612. else if l>1 then
  613. objectoutput^.writealign(2);
  614. objectoutput^.writealloc(pai_datablock(hp)^.size);
  615. end;
  616. end;
  617. ait_const_32bit :
  618. objectoutput^.writebytes(pai_const(hp)^.value,4);
  619. ait_const_16bit :
  620. objectoutput^.writebytes(pai_const(hp)^.value,2);
  621. ait_const_8bit :
  622. objectoutput^.writebytes(pai_const(hp)^.value,1);
  623. ait_real_80bit :
  624. objectoutput^.writebytes(pai_real_80bit(hp)^.value,10);
  625. ait_real_64bit :
  626. objectoutput^.writebytes(pai_real_64bit(hp)^.value,8);
  627. ait_real_32bit :
  628. objectoutput^.writebytes(pai_real_32bit(hp)^.value,4);
  629. ait_comp_64bit :
  630. begin
  631. {$ifdef FPC}
  632. co:=comp(pai_comp_64bit(hp)^.value);
  633. {$else}
  634. co:=pai_comp_64bit(hp)^.value;
  635. {$endif}
  636. objectoutput^.writebytes(co,8);
  637. end;
  638. ait_string :
  639. objectoutput^.writebytes(pai_string(hp)^.str^,pai_string(hp)^.len);
  640. ait_const_rva :
  641. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  642. pai_const_symbol(hp)^.sym,relative_rva);
  643. ait_const_symbol :
  644. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  645. pai_const_symbol(hp)^.sym,relative_false);
  646. ait_label :
  647. objectoutput^.writesymbol(pai_label(hp)^.l);
  648. ait_instruction :
  649. paicpu(hp)^.Pass2;
  650. {$ifdef GDB}
  651. ait_stabn :
  652. convertstabs(pai_stabn(hp)^.str);
  653. ait_stabs :
  654. convertstabs(pai_stabs(hp)^.str);
  655. ait_stab_function_name :
  656. if assigned(pai_stab_function_name(hp)^.str) then
  657. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  658. else
  659. funcname:=nil;
  660. ait_force_line :
  661. stabslastfileinfo.line:=0;
  662. {$endif}
  663. ait_cut :
  664. if SmartAsm then
  665. break;
  666. end;
  667. hp:=pai(hp^.next);
  668. end;
  669. TreePass2:=hp;
  670. end;
  671. procedure ti386binasmlist.writetree;
  672. var
  673. hp : pai;
  674. begin
  675. { reset the asmsymbol list }
  676. ResetAsmsymbolList;
  677. objectoutput^.defaultsection(sec_code);
  678. {$ifdef MULTIPASS}
  679. { Pass 0 }
  680. currpass:=0;
  681. objectalloc^.setsection(sec_code);
  682. { start with list 1 }
  683. currlistidx:=1;
  684. currlist:=list[currlistidx];
  685. hp:=pai(currlist^.first);
  686. while assigned(hp) do
  687. begin
  688. hp:=TreePass0(hp);
  689. MaybeNextList(hp);
  690. end;
  691. { leave if errors have occured }
  692. if errorcount>0 then
  693. exit;
  694. {$endif}
  695. { Pass 1 }
  696. currpass:=1;
  697. objectalloc^.resetsections;
  698. objectalloc^.setsection(sec_code);
  699. {$ifdef GDB}
  700. StartFileLineInfo;
  701. {$endif GDB}
  702. { start with list 1 }
  703. currlistidx:=1;
  704. currlist:=list[currlistidx];
  705. hp:=pai(currlist^.first);
  706. while assigned(hp) do
  707. begin
  708. hp:=TreePass1(hp);
  709. MaybeNextList(hp);
  710. end;
  711. { check for undefined labels }
  712. CheckAsmSymbolListUndefined;
  713. { set section sizes }
  714. objectoutput^.setsectionsizes(objectalloc^.secsize);
  715. { leave if errors have occured }
  716. if errorcount>0 then
  717. exit;
  718. { Pass 2 }
  719. currpass:=2;
  720. {$ifdef GDB}
  721. StartFileLineInfo;
  722. {$endif GDB}
  723. { start with list 1 }
  724. currlistidx:=1;
  725. currlist:=list[currlistidx];
  726. hp:=pai(currlist^.first);
  727. while assigned(hp) do
  728. begin
  729. hp:=TreePass2(hp);
  730. MaybeNextList(hp);
  731. end;
  732. end;
  733. procedure ti386binasmlist.writetreesmart;
  734. var
  735. hp : pai;
  736. startsec : tsection;
  737. begin
  738. startsec:=sec_code;
  739. { start with list 1 }
  740. currlistidx:=1;
  741. currlist:=list[currlistidx];
  742. hp:=pai(currlist^.first);
  743. while assigned(hp) do
  744. begin
  745. { reset the asmsymbol list }
  746. ResetAsmsymbolList;
  747. {$ifdef MULTIPASS}
  748. { Pass 0 }
  749. currpass:=0;
  750. objectalloc^.resetsections;
  751. objectalloc^.setsection(startsec);
  752. TreePass0(hp);
  753. {$endif}
  754. { leave if errors have occured }
  755. if errorcount>0 then
  756. exit;
  757. { Pass 1 }
  758. currpass:=1;
  759. objectalloc^.resetsections;
  760. objectalloc^.setsection(startsec);
  761. {$ifdef GDB}
  762. StartFileLineInfo;
  763. {$endif GDB}
  764. TreePass1(hp);
  765. { check for undefined labels }
  766. CheckAsmSymbolListUndefined;
  767. { set section sizes }
  768. objectoutput^.setsectionsizes(objectalloc^.secsize);
  769. { leave if errors have occured }
  770. if errorcount>0 then
  771. exit;
  772. { Pass 2 }
  773. currpass:=2;
  774. objectoutput^.defaultsection(startsec);
  775. {$ifdef GDB}
  776. StartFileLineInfo;
  777. {$endif GDB}
  778. hp:=TreePass2(hp);
  779. { leave if errors have occured }
  780. if errorcount>0 then
  781. exit;
  782. { end of lists? }
  783. if not MaybeNextList(hp) then
  784. break;
  785. { if not end then write the current objectfile }
  786. objectoutput^.donewriting;
  787. { save section for next loop }
  788. startsec:=objectalloc^.currsec;
  789. { we will start a new objectfile so reset everything }
  790. if (hp^.typ=ait_cut) then
  791. objectoutput^.initwriting(pai_cut(hp)^.place)
  792. else
  793. objectoutput^.initwriting(cut_normal);
  794. { avoid empty files }
  795. while assigned(hp^.next) and
  796. (pai(hp^.next)^.typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  797. begin
  798. if pai(hp^.next)^.typ=ait_section then
  799. startsec:=pai_section(hp^.next)^.sec;
  800. hp:=pai(hp^.next);
  801. end;
  802. hp:=pai(hp^.next);
  803. if not MaybeNextList(hp) then
  804. break;
  805. end;
  806. end;
  807. procedure ti386binasmlist.writebin;
  808. procedure addlist(p:paasmoutput);
  809. begin
  810. inc(lists);
  811. list[lists]:=p;
  812. end;
  813. begin
  814. objectalloc^.resetsections;
  815. objectalloc^.setsection(sec_code);
  816. objectoutput^.initwriting(cut_normal);
  817. objectoutput^.defaultsection(sec_code);
  818. if cs_debuginfo in aktmoduleswitches then
  819. addlist(debuglist);
  820. addlist(codesegment);
  821. addlist(datasegment);
  822. addlist(consts);
  823. addlist(rttilist);
  824. if assigned(resourcestringlist) then
  825. addlist(resourcestringlist);
  826. addlist(bsssegment);
  827. if assigned(importssection) then
  828. addlist(importssection);
  829. if assigned(exportssection) and not UseDeffileForExport then
  830. addlist(exportssection);
  831. if assigned(resourcesection) then
  832. addlist(resourcesection);
  833. if SmartAsm then
  834. writetreesmart
  835. else
  836. writetree;
  837. { leave if errors have occured }
  838. if errorcount>0 then
  839. exit;
  840. { write last objectfile }
  841. objectoutput^.donewriting;
  842. end;
  843. constructor ti386binasmlist.init(t:togtype;smart:boolean);
  844. begin
  845. case t of
  846. og_none :
  847. Message(asmw_f_no_binary_writer_selected);
  848. og_dbg :
  849. objectoutput:=new(pdbgoutput,init(smart));
  850. og_coff :
  851. objectoutput:=new(pdjgppcoffoutput,init(smart));
  852. og_pecoff :
  853. objectoutput:=new(pwin32coffoutput,init(smart));
  854. end;
  855. objectalloc:=new(pobjectalloc,init);
  856. SmartAsm:=smart;
  857. currpass:=0;
  858. end;
  859. destructor ti386binasmlist.done;
  860. begin
  861. dispose(objectoutput,done);
  862. dispose(objectalloc,done);
  863. end;
  864. end.
  865. {
  866. $Log$
  867. Revision 1.34 2000-01-12 10:38:17 peter
  868. * smartlinking fixes for binary writer
  869. * release alignreg code and moved instruction writing align to cpuasm,
  870. but it doesn't use the specified register yet
  871. Revision 1.33 2000/01/07 01:14:18 peter
  872. * updated copyright to 2000
  873. Revision 1.32 1999/12/24 15:22:52 peter
  874. * reset insentry/lastinsoffset so writing smartlink works correct for
  875. short jmps
  876. Revision 1.31 1999/12/22 01:01:46 peter
  877. - removed freelabel()
  878. * added undefined label detection in internal assembler, this prevents
  879. a lot of ld crashes and wrong .o files
  880. * .o files aren't written anymore if errors have occured
  881. * inlining of assembler labels is now correct
  882. Revision 1.30 1999/12/08 10:39:59 pierre
  883. + allow use of unit var in exports of DLL for win32
  884. by using direct export writing by default instead of use of DEFFILE
  885. that does not allow assembler labels that do not
  886. start with an underscore.
  887. Use -WD to force use of Deffile for Win32 DLL
  888. Revision 1.29 1999/12/01 22:05:13 pierre
  889. * problem with unused external symbol in stabs solved
  890. Revision 1.28 1999/11/30 10:40:42 peter
  891. + ttype, tsymlist
  892. Revision 1.27 1999/11/06 14:34:16 peter
  893. * truncated log to 20 revs
  894. Revision 1.26 1999/11/02 15:06:56 peter
  895. * import library fixes for win32
  896. * alignment works again
  897. Revision 1.25 1999/09/26 21:13:40 peter
  898. * short jmp with alignment problems fixed
  899. Revision 1.24 1999/08/25 11:59:33 jonas
  900. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  901. Revision 1.23 1999/08/10 12:26:21 pierre
  902. * avoid double .edata section if using DLLTOOL
  903. Revision 1.22 1999/08/04 00:22:35 florian
  904. * renamed i386asm and i386base to cpuasm and cpubase
  905. Revision 1.21 1999/08/01 18:28:09 florian
  906. * modifications for the new code generator
  907. Revision 1.20 1999/07/31 12:33:11 peter
  908. * fixed smartlinking
  909. Revision 1.19 1999/07/22 09:37:30 florian
  910. + resourcestring implemented
  911. + start of longstring support
  912. Revision 1.18 1999/07/03 00:26:02 peter
  913. * ag386bin doesn't destroy the aasmoutput lists anymore
  914. Revision 1.17 1999/06/10 23:52:34 pierre
  915. * merged from fixes branch
  916. Revision 1.16.2.1 1999/06/10 23:33:35 pierre
  917. * pchar memory loss and .bss size problem solved
  918. Revision 1.16 1999/06/03 16:39:10 pierre
  919. * EXTERNALBSS fixed for stabs and default again
  920. Revision 1.15 1999/06/02 22:43:59 pierre
  921. * previous wrong log corrected
  922. Revision 1.14 1999/06/02 22:25:25 pierre
  923. * changed $ifdef FPC @ into $ifndef TP
  924. Revision 1.13 1999/06/01 10:24:09 pierre
  925. * ts010021.pp problem solved for ag386bin !
  926. Revision 1.12 1999/05/27 19:43:59 peter
  927. * removed oldasm
  928. * plabel -> pasmlabel
  929. * -a switches to source writing automaticly
  930. * assembler readers OOPed
  931. * asmsymbol automaticly external
  932. * jumptables and other label fixes for asm readers
  933. Revision 1.11 1999/05/21 13:54:41 peter
  934. * NEWLAB for label as symbol
  935. Revision 1.10 1999/05/19 11:54:17 pierre
  936. + experimental code for externalbss and stabs problem
  937. Revision 1.9 1999/05/12 00:19:37 peter
  938. * removed R_DEFAULT_SEG
  939. * uniform float names
  940. Revision 1.8 1999/05/09 11:38:04 peter
  941. * don't write .o and link if errors occure during assembling
  942. }