ag386bin.pas 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  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^.typ:=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. lastsec : tsection;
  340. l : longint;
  341. begin
  342. while assigned(hp) do
  343. begin
  344. case hp^.typ of
  345. ait_align :
  346. begin
  347. { always use the maximum fillsize in this pass to avoid possible
  348. short jumps to become out of range }
  349. pai_align(hp)^.fillsize:=pai_align(hp)^.aligntype;
  350. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  351. end;
  352. ait_datablock :
  353. begin
  354. {$ifdef EXTERNALBSS}
  355. if not SmartAsm then
  356. begin
  357. if not pai_datablock(hp)^.is_global then
  358. begin
  359. l:=pai_datablock(hp)^.size;
  360. if l>2 then
  361. objectalloc^.sectionalign(4)
  362. else if l>1 then
  363. objectalloc^.sectionalign(2);
  364. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  365. end;
  366. end
  367. else
  368. begin
  369. {$endif}
  370. l:=pai_datablock(hp)^.size;
  371. if l>2 then
  372. objectalloc^.sectionalign(4)
  373. else if l>1 then
  374. objectalloc^.sectionalign(2);
  375. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  376. end;
  377. end;
  378. ait_const_32bit :
  379. objectalloc^.sectionalloc(4);
  380. ait_const_16bit :
  381. objectalloc^.sectionalloc(2);
  382. ait_const_8bit :
  383. objectalloc^.sectionalloc(1);
  384. ait_real_80bit :
  385. objectalloc^.sectionalloc(10);
  386. ait_real_64bit :
  387. objectalloc^.sectionalloc(8);
  388. ait_real_32bit :
  389. objectalloc^.sectionalloc(4);
  390. ait_comp_64bit :
  391. objectalloc^.sectionalloc(8);
  392. ait_const_rva,
  393. ait_const_symbol :
  394. objectalloc^.sectionalloc(4);
  395. ait_section:
  396. begin
  397. objectalloc^.setsection(pai_section(hp)^.sec);
  398. lastsec:=pai_section(hp)^.sec;
  399. end;
  400. ait_symbol :
  401. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  402. ait_label :
  403. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  404. ait_string :
  405. objectalloc^.sectionalloc(pai_string(hp)^.len);
  406. ait_instruction :
  407. begin
  408. { reset instructions which could change in pass 2 }
  409. paicpu(hp)^.resetpass2;
  410. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  411. end;
  412. ait_cut :
  413. if SmartAsm then
  414. begin
  415. objectalloc^.resetsections;
  416. objectalloc^.setsection(lastsec);
  417. end;
  418. end;
  419. hp:=pai(hp^.next);
  420. end;
  421. TreePass0:=hp;
  422. end;
  423. function ti386binasmlist.TreePass1(hp:pai):pai;
  424. var
  425. l : longint;
  426. begin
  427. while assigned(hp) do
  428. begin
  429. {$ifdef GDB}
  430. { write stabs }
  431. if (cs_debuginfo in aktmoduleswitches) then
  432. begin
  433. if (objectalloc^.currsec<>sec_none) and
  434. not(hp^.typ in [
  435. ait_label,
  436. ait_regalloc,ait_tempalloc,
  437. ait_stabn,ait_stabs,ait_section,
  438. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  439. WriteFileLineInfo(hp^.fileinfo);
  440. end;
  441. {$endif GDB}
  442. case hp^.typ of
  443. ait_align :
  444. begin
  445. { here we must determine the fillsize which is used in pass2 }
  446. pai_align(hp)^.fillsize:=align(objectalloc^.sectionsize,pai_align(hp)^.aligntype)-
  447. objectalloc^.sectionsize;
  448. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  449. end;
  450. ait_datablock :
  451. begin
  452. if objectalloc^.currsec<>sec_bss then
  453. Message(asmw_e_alloc_data_only_in_bss);
  454. {$ifdef EXTERNALBSS}
  455. if not SmartAsm then
  456. begin
  457. if pai_datablock(hp)^.is_global then
  458. begin
  459. pai_datablock(hp)^.sym^.typ:=AS_EXTERNAL;
  460. pai_datablock(hp)^.sym^.setaddress(sec_none,pai_datablock(hp)^.size,pai_datablock(hp)^.size);
  461. end
  462. else
  463. begin
  464. l:=pai_datablock(hp)^.size;
  465. if l>2 then
  466. objectalloc^.sectionalign(4)
  467. else if l>1 then
  468. objectalloc^.sectionalign(2);
  469. pai_datablock(hp)^.sym^.typ:=AS_LOCAL;
  470. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,
  471. pai_datablock(hp)^.size);
  472. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  473. end;
  474. end
  475. else
  476. {$endif}
  477. begin
  478. if pai_datablock(hp)^.is_global then
  479. pai_datablock(hp)^.sym^.typ:=AS_GLOBAL
  480. else
  481. pai_datablock(hp)^.sym^.typ:=AS_LOCAL;
  482. l:=pai_datablock(hp)^.size;
  483. if l>2 then
  484. objectalloc^.sectionalign(4)
  485. else if l>1 then
  486. objectalloc^.sectionalign(2);
  487. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,pai_datablock(hp)^.size);
  488. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  489. end;
  490. end;
  491. ait_const_32bit :
  492. objectalloc^.sectionalloc(4);
  493. ait_const_16bit :
  494. objectalloc^.sectionalloc(2);
  495. ait_const_8bit :
  496. objectalloc^.sectionalloc(1);
  497. ait_real_80bit :
  498. objectalloc^.sectionalloc(10);
  499. ait_real_64bit :
  500. objectalloc^.sectionalloc(8);
  501. ait_real_32bit :
  502. objectalloc^.sectionalloc(4);
  503. ait_comp_64bit :
  504. objectalloc^.sectionalloc(8);
  505. ait_const_rva,
  506. ait_const_symbol :
  507. objectalloc^.sectionalloc(4);
  508. ait_section:
  509. begin
  510. objectalloc^.setsection(pai_section(hp)^.sec);
  511. {$ifdef GDB}
  512. case pai_section(hp)^.sec of
  513. sec_code : n_line:=n_textline;
  514. sec_data : n_line:=n_dataline;
  515. sec_bss : n_line:=n_bssline;
  516. else
  517. n_line:=n_dataline;
  518. end;
  519. stabslastfileinfo.line:=-1;
  520. {$endif GDB}
  521. end;
  522. {$ifdef GDB}
  523. ait_stabn :
  524. convertstabs(pai_stabn(hp)^.str);
  525. ait_stabs :
  526. convertstabs(pai_stabs(hp)^.str);
  527. ait_stab_function_name :
  528. if assigned(pai_stab_function_name(hp)^.str) then
  529. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  530. else
  531. funcname:=nil;
  532. ait_force_line :
  533. stabslastfileinfo.line:=0;
  534. {$endif}
  535. ait_symbol :
  536. begin
  537. if pai_symbol(hp)^.is_global then
  538. pai_symbol(hp)^.sym^.typ:=AS_GLOBAL
  539. else
  540. pai_symbol(hp)^.sym^.typ:=AS_LOCAL;
  541. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  542. end;
  543. ait_label :
  544. begin
  545. if pai_label(hp)^.is_global then
  546. pai_label(hp)^.l^.typ:=AS_GLOBAL
  547. else
  548. pai_label(hp)^.l^.typ:=AS_LOCAL;
  549. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  550. end;
  551. ait_string :
  552. objectalloc^.sectionalloc(pai_string(hp)^.len);
  553. ait_instruction :
  554. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  555. ait_direct :
  556. Message(asmw_f_direct_not_supported);
  557. ait_cut :
  558. if SmartAsm then
  559. break;
  560. end;
  561. hp:=pai(hp^.next);
  562. end;
  563. TreePass1:=hp;
  564. end;
  565. function ti386binasmlist.TreePass2(hp:pai):pai;
  566. const
  567. alignarray:array[0..5] of string[8]=(
  568. #$8D#$B4#$26#$00#$00#$00#$00,
  569. #$8D#$B6#$00#$00#$00#$00,
  570. #$8D#$74#$26#$00,
  571. #$8D#$76#$00,
  572. #$89#$F6,
  573. #$90
  574. );
  575. var
  576. l,j : longint;
  577. alignoparray:array[0..63] of byte;
  578. {$ifdef I386}
  579. co : comp;
  580. {$endif I386}
  581. begin
  582. { main loop }
  583. while assigned(hp) do
  584. begin
  585. {$ifdef GDB}
  586. { write stabs }
  587. if cs_debuginfo in aktmoduleswitches then
  588. begin
  589. if (objectoutput^.currsec<>sec_none) and
  590. not(hp^.typ in [
  591. ait_label,
  592. ait_regalloc,ait_tempalloc,
  593. ait_stabn,ait_stabs,ait_section,
  594. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  595. WriteFileLineInfo(hp^.fileinfo);
  596. end;
  597. {$endif GDB}
  598. case hp^.typ of
  599. ait_align :
  600. begin
  601. if not pai_align(hp)^.use_op then
  602. begin
  603. l:=pai_align(hp)^.fillsize;
  604. while (l>0) do
  605. begin
  606. for j:=0to 5 do
  607. if (l>=length(alignarray[j])) then
  608. break;
  609. objectoutput^.writebytes(alignarray[j][1],length(alignarray[j]));
  610. dec(l,length(alignarray[j]));
  611. end;
  612. end
  613. else
  614. begin
  615. fillchar(alignoparray,pai_align(hp)^.fillsize,pai_align(hp)^.fillop);
  616. objectoutput^.writebytes(alignoparray,pai_align(hp)^.fillsize);
  617. end;
  618. end;
  619. ait_section :
  620. begin
  621. objectoutput^.defaultsection(pai_section(hp)^.sec);
  622. {$ifdef GDB}
  623. case pai_section(hp)^.sec of
  624. sec_code : n_line:=n_textline;
  625. sec_data : n_line:=n_dataline;
  626. sec_bss : n_line:=n_bssline;
  627. else
  628. n_line:=n_dataline;
  629. end;
  630. stabslastfileinfo.line:=-1;
  631. {$endif GDB}
  632. end;
  633. ait_symbol :
  634. objectoutput^.writesymbol(pai_symbol(hp)^.sym);
  635. ait_datablock :
  636. begin
  637. objectoutput^.writesymbol(pai_datablock(hp)^.sym);
  638. if SmartAsm
  639. {$ifdef EXTERNALBSS}
  640. or (not pai_datablock(hp)^.is_global)
  641. {$endif}
  642. then
  643. begin
  644. l:=pai_datablock(hp)^.size;
  645. if l>2 then
  646. objectoutput^.writealign(4)
  647. else if l>1 then
  648. objectoutput^.writealign(2);
  649. objectoutput^.writealloc(pai_datablock(hp)^.size);
  650. end;
  651. end;
  652. ait_const_32bit :
  653. objectoutput^.writebytes(pai_const(hp)^.value,4);
  654. ait_const_16bit :
  655. objectoutput^.writebytes(pai_const(hp)^.value,2);
  656. ait_const_8bit :
  657. objectoutput^.writebytes(pai_const(hp)^.value,1);
  658. ait_real_80bit :
  659. objectoutput^.writebytes(pai_real_80bit(hp)^.value,10);
  660. ait_real_64bit :
  661. objectoutput^.writebytes(pai_real_64bit(hp)^.value,8);
  662. ait_real_32bit :
  663. objectoutput^.writebytes(pai_real_32bit(hp)^.value,4);
  664. ait_comp_64bit :
  665. begin
  666. {$ifdef FPC}
  667. co:=comp(pai_comp_64bit(hp)^.value);
  668. {$else}
  669. co:=pai_comp_64bit(hp)^.value;
  670. {$endif}
  671. objectoutput^.writebytes(co,8);
  672. end;
  673. ait_string :
  674. objectoutput^.writebytes(pai_string(hp)^.str^,pai_string(hp)^.len);
  675. ait_const_rva :
  676. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  677. pai_const_symbol(hp)^.sym,relative_rva);
  678. ait_const_symbol :
  679. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  680. pai_const_symbol(hp)^.sym,relative_false);
  681. ait_label :
  682. objectoutput^.writesymbol(pai_label(hp)^.l);
  683. ait_instruction :
  684. paicpu(hp)^.Pass2;
  685. {$ifdef GDB}
  686. ait_stabn :
  687. convertstabs(pai_stabn(hp)^.str);
  688. ait_stabs :
  689. convertstabs(pai_stabs(hp)^.str);
  690. ait_stab_function_name :
  691. if assigned(pai_stab_function_name(hp)^.str) then
  692. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  693. else
  694. funcname:=nil;
  695. ait_force_line :
  696. stabslastfileinfo.line:=0;
  697. {$endif}
  698. ait_cut :
  699. if SmartAsm then
  700. break;
  701. end;
  702. hp:=pai(hp^.next);
  703. end;
  704. TreePass2:=hp;
  705. end;
  706. procedure ti386binasmlist.writetree;
  707. var
  708. hp : pai;
  709. begin
  710. objectalloc^.setsection(sec_code);
  711. objectoutput^.defaultsection(sec_code);
  712. { Pass 1 }
  713. currpass:=1;
  714. {$ifdef GDB}
  715. StartFileLineInfo;
  716. {$endif GDB}
  717. { start with list 1 }
  718. currlistidx:=1;
  719. currlist:=list[currlistidx];
  720. hp:=pai(currlist^.first);
  721. while assigned(hp) do
  722. begin
  723. hp:=TreePass1(hp);
  724. MaybeNextList(hp);
  725. end;
  726. { check for undefined labels }
  727. CheckAsmSymbolListUndefined;
  728. { set section sizes }
  729. objectoutput^.setsectionsizes(objectalloc^.secsize);
  730. { leave if errors have occured }
  731. if errorcount>0 then
  732. exit;
  733. { Pass 2 }
  734. currpass:=2;
  735. {$ifdef GDB}
  736. StartFileLineInfo;
  737. {$endif GDB}
  738. { start with list 1 }
  739. currlistidx:=1;
  740. currlist:=list[currlistidx];
  741. hp:=pai(currlist^.first);
  742. while assigned(hp) do
  743. begin
  744. hp:=TreePass2(hp);
  745. MaybeNextList(hp);
  746. end;
  747. end;
  748. procedure ti386binasmlist.writetreesmart;
  749. var
  750. hp : pai;
  751. begin
  752. objectalloc^.setsection(sec_code);
  753. objectoutput^.defaultsection(sec_code);
  754. { start with list 1 }
  755. currlistidx:=1;
  756. currlist:=list[currlistidx];
  757. hp:=pai(currlist^.first);
  758. while assigned(hp) do
  759. begin
  760. { Pass 1 }
  761. currpass:=1;
  762. {$ifdef GDB}
  763. StartFileLineInfo;
  764. {$endif GDB}
  765. TreePass1(hp);
  766. { check for undefined labels }
  767. CheckAsmSymbolListUndefined;
  768. { set section sizes }
  769. objectoutput^.setsectionsizes(objectalloc^.secsize);
  770. { leave if errors have occured }
  771. if errorcount>0 then
  772. exit;
  773. { Pass 2 }
  774. currpass:=2;
  775. {$ifdef GDB}
  776. StartFileLineInfo;
  777. {$endif GDB}
  778. hp:=TreePass2(hp);
  779. if not MaybeNextList(hp) then
  780. break;
  781. { leave if errors have occured }
  782. if errorcount>0 then
  783. exit;
  784. { write the current objectfile }
  785. objectoutput^.donewriting;
  786. { we will start a new objectfile so reset everything }
  787. if (hp^.typ=ait_cut) then
  788. objectoutput^.initwriting(pai_cut(hp)^.place)
  789. else
  790. objectoutput^.initwriting(cut_normal);
  791. objectalloc^.resetsections;
  792. ResetAsmsymbolList;
  793. { avoid empty files }
  794. while assigned(hp^.next) and
  795. (pai(hp^.next)^.typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  796. begin
  797. if pai(hp^.next)^.typ=ait_section then
  798. begin
  799. objectalloc^.setsection(pai_section(hp^.next)^.sec);
  800. objectoutput^.defaultsection(pai_section(hp^.next)^.sec);
  801. end;
  802. hp:=pai(hp^.next);
  803. end;
  804. hp:=pai(hp^.next);
  805. if not MaybeNextList(hp) then
  806. break;
  807. end;
  808. end;
  809. procedure ti386binasmlist.writebin;
  810. procedure addlist(p:paasmoutput);
  811. begin
  812. inc(lists);
  813. list[lists]:=p;
  814. end;
  815. begin
  816. {$ifdef MULTIPASS}
  817. { Process the codesegment twice so the short jmp instructions can
  818. be optimized }
  819. currpass:=0;
  820. TreePass0(pai(codesegment^.first));
  821. {$endif}
  822. objectalloc^.resetsections;
  823. objectalloc^.setsection(sec_code);
  824. objectoutput^.initwriting(cut_normal);
  825. objectoutput^.defaultsection(sec_code);
  826. if cs_debuginfo in aktmoduleswitches then
  827. addlist(debuglist);
  828. addlist(codesegment);
  829. addlist(datasegment);
  830. addlist(consts);
  831. addlist(rttilist);
  832. if assigned(resourcestringlist) then
  833. addlist(resourcestringlist);
  834. addlist(bsssegment);
  835. if assigned(importssection) then
  836. addlist(importssection);
  837. if assigned(exportssection) and not UseDeffileForExport then
  838. addlist(exportssection);
  839. if assigned(resourcesection) then
  840. addlist(resourcesection);
  841. if SmartAsm then
  842. writetreesmart
  843. else
  844. writetree;
  845. { leave if errors have occured }
  846. if errorcount>0 then
  847. exit;
  848. { write last objectfile }
  849. objectoutput^.donewriting;
  850. end;
  851. constructor ti386binasmlist.init(t:togtype;smart:boolean);
  852. begin
  853. case t of
  854. og_none :
  855. Message(asmw_f_no_binary_writer_selected);
  856. og_dbg :
  857. objectoutput:=new(pdbgoutput,init(smart));
  858. og_coff :
  859. objectoutput:=new(pdjgppcoffoutput,init(smart));
  860. og_pecoff :
  861. objectoutput:=new(pwin32coffoutput,init(smart));
  862. end;
  863. objectalloc:=new(pobjectalloc,init);
  864. SmartAsm:=smart;
  865. currpass:=0;
  866. end;
  867. destructor ti386binasmlist.done;
  868. begin
  869. dispose(objectoutput,done);
  870. dispose(objectalloc,done);
  871. end;
  872. end.
  873. {
  874. $Log$
  875. Revision 1.33 2000-01-07 01:14:18 peter
  876. * updated copyright to 2000
  877. Revision 1.32 1999/12/24 15:22:52 peter
  878. * reset insentry/lastinsoffset so writing smartlink works correct for
  879. short jmps
  880. Revision 1.31 1999/12/22 01:01:46 peter
  881. - removed freelabel()
  882. * added undefined label detection in internal assembler, this prevents
  883. a lot of ld crashes and wrong .o files
  884. * .o files aren't written anymore if errors have occured
  885. * inlining of assembler labels is now correct
  886. Revision 1.30 1999/12/08 10:39:59 pierre
  887. + allow use of unit var in exports of DLL for win32
  888. by using direct export writing by default instead of use of DEFFILE
  889. that does not allow assembler labels that do not
  890. start with an underscore.
  891. Use -WD to force use of Deffile for Win32 DLL
  892. Revision 1.29 1999/12/01 22:05:13 pierre
  893. * problem with unused external symbol in stabs solved
  894. Revision 1.28 1999/11/30 10:40:42 peter
  895. + ttype, tsymlist
  896. Revision 1.27 1999/11/06 14:34:16 peter
  897. * truncated log to 20 revs
  898. Revision 1.26 1999/11/02 15:06:56 peter
  899. * import library fixes for win32
  900. * alignment works again
  901. Revision 1.25 1999/09/26 21:13:40 peter
  902. * short jmp with alignment problems fixed
  903. Revision 1.24 1999/08/25 11:59:33 jonas
  904. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  905. Revision 1.23 1999/08/10 12:26:21 pierre
  906. * avoid double .edata section if using DLLTOOL
  907. Revision 1.22 1999/08/04 00:22:35 florian
  908. * renamed i386asm and i386base to cpuasm and cpubase
  909. Revision 1.21 1999/08/01 18:28:09 florian
  910. * modifications for the new code generator
  911. Revision 1.20 1999/07/31 12:33:11 peter
  912. * fixed smartlinking
  913. Revision 1.19 1999/07/22 09:37:30 florian
  914. + resourcestring implemented
  915. + start of longstring support
  916. Revision 1.18 1999/07/03 00:26:02 peter
  917. * ag386bin doesn't destroy the aasmoutput lists anymore
  918. Revision 1.17 1999/06/10 23:52:34 pierre
  919. * merged from fixes branch
  920. Revision 1.16.2.1 1999/06/10 23:33:35 pierre
  921. * pchar memory loss and .bss size problem solved
  922. Revision 1.16 1999/06/03 16:39:10 pierre
  923. * EXTERNALBSS fixed for stabs and default again
  924. Revision 1.15 1999/06/02 22:43:59 pierre
  925. * previous wrong log corrected
  926. Revision 1.14 1999/06/02 22:25:25 pierre
  927. * changed $ifdef FPC @ into $ifndef TP
  928. Revision 1.13 1999/06/01 10:24:09 pierre
  929. * ts010021.pp problem solved for ag386bin !
  930. Revision 1.12 1999/05/27 19:43:59 peter
  931. * removed oldasm
  932. * plabel -> pasmlabel
  933. * -a switches to source writing automaticly
  934. * assembler readers OOPed
  935. * asmsymbol automaticly external
  936. * jumptables and other label fixes for asm readers
  937. Revision 1.11 1999/05/21 13:54:41 peter
  938. * NEWLAB for label as symbol
  939. Revision 1.10 1999/05/19 11:54:17 pierre
  940. + experimental code for externalbss and stabs problem
  941. Revision 1.9 1999/05/12 00:19:37 peter
  942. * removed R_DEFAULT_SEG
  943. * uniform float names
  944. Revision 1.8 1999/05/09 11:38:04 peter
  945. * don't write .o and link if errors occure during assembling
  946. }