agx86nsm.pas 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements an asmoutput class for the Nasm assembler with
  4. Intel syntax for the i386+
  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. unit agx86nsm;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,cpubase,globtype,
  23. aasmbase,aasmtai,aasmdata,aasmcpu,assemble,cgutils;
  24. type
  25. { TX86NasmAssembler }
  26. TX86NasmAssembler = class(texternalassembler)
  27. strict private
  28. type
  29. { TX86NasmSection }
  30. TX86NasmSection=class(TFPHashObject)
  31. end;
  32. { TX86NasmGroup }
  33. TX86NasmGroup=class(TFPHashObject)
  34. Sections: TFPHashObjectList;
  35. constructor Create(HashObjectList:TFPHashObjectList;const s:TSymStr);
  36. destructor Destroy;override;
  37. end;
  38. private
  39. FSections: TFPHashObjectList;
  40. FGroups: TFPHashObjectList;
  41. using_relative : boolean;
  42. function CodeSectionName(const aname:string): string;
  43. procedure WriteReference(var ref : treference);
  44. procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
  45. procedure WriteOper_jmp(const o:toper; ai : taicpu);
  46. procedure WriteSection(atype:TAsmSectiontype;const aname:string;alignment : longint);
  47. procedure ResetSectionsList;
  48. procedure AddGroup(const grpname: string);
  49. procedure AddSegmentToGroup(const grpname,segname: string);
  50. procedure WriteGroup(data:TObject;arg:pointer);
  51. procedure WriteGroups;
  52. protected
  53. function single2str(d: single): string; override;
  54. function double2str(d: double): string; override;
  55. function extended2str(e: extended): string; override;
  56. public
  57. destructor Destroy;override;
  58. procedure WriteTree(p:TAsmList);override;
  59. procedure WriteAsmList;override;
  60. procedure WriteExternals;
  61. procedure WriteSmartExternals;
  62. procedure WriteHeader;
  63. function MakeCmdLine: TCmdStr;override;
  64. end;
  65. implementation
  66. uses
  67. cutils,globals,systems,
  68. fmodule,finput,verbose,cpuinfo,cgbase,omfbase
  69. ;
  70. const
  71. line_length = 64;
  72. nasm_regname_table : array[tregisterindex] of string[13] = (
  73. {r386nasm.inc contains the Nasm name of each register.}
  74. {$if defined(x86_64)}
  75. {$i r8664nasm.inc}
  76. {$elseif defined(i386)}
  77. {$i r386nasm.inc}
  78. {$elseif defined(i8086)}
  79. {$i r8086nasm.inc}
  80. {$endif}
  81. );
  82. { nasm 2.13 expects lowercase cpu names }
  83. nasm_cpu_name : array[tcputype] of string = (
  84. {$if defined(x86_64)}
  85. 'ia64', // cpu_none,
  86. 'x64', // cpu_athlon64,
  87. 'ia64', // cpu_core_i,
  88. 'ia64', // cpu_core_avx,
  89. 'ia64' // cpu_core_avx2
  90. {$elseif defined(i386)}
  91. 'ia64', // cpu_none,
  92. '386', // cpu_386,
  93. '486', // cpu_486,
  94. 'pentium', // cpu_Pentium,
  95. 'p2', // cpu_Pentium2,
  96. 'p3', // cpu_Pentium3,
  97. 'p4', // cpu_Pentium4,
  98. 'p4', // cpu_PentiumM,
  99. 'ia64', // cpu_core_i,
  100. 'ia64', // cpu_core_avx,
  101. 'ia64' // cpu_core_avx2
  102. {$elseif defined(i8086)}
  103. 'ia64', // cpu_none
  104. '8086', // cpu_8086
  105. '186', // cpu_186
  106. '286', // cpu_286
  107. '386', // cpu_386
  108. '486', // cpu_486
  109. 'pentium', // cpu_Pentium
  110. 'p2', // cpu_Pentium2
  111. 'p3', // cpu_Pentium3
  112. 'p4', // cpu_Pentium4
  113. 'p4' // cpu_PentiumM
  114. {$endif}
  115. );
  116. function nasm_regname(r:Tregister):string;
  117. var
  118. p : tregisterindex;
  119. begin
  120. p:=findreg_by_number(r);
  121. if p<>0 then
  122. result:=nasm_regname_table[p]
  123. else
  124. result:=generic_regname(r);
  125. end;
  126. function TX86NasmAssembler.single2str(d: single): string;
  127. var
  128. hs : string;
  129. p : longint;
  130. begin
  131. str(d,hs);
  132. { nasm expects a lowercase e }
  133. p:=pos('E',hs);
  134. if p>0 then
  135. hs[p]:='e';
  136. p:=pos('+',hs);
  137. if p>0 then
  138. delete(hs,p,1);
  139. single2str:=lower(hs);
  140. end;
  141. function TX86NasmAssembler.double2str(d: double): string;
  142. var
  143. hs : string;
  144. p : longint;
  145. begin
  146. str(d,hs);
  147. { nasm expects a lowercase e }
  148. p:=pos('E',hs);
  149. if p>0 then
  150. hs[p]:='e';
  151. p:=pos('+',hs);
  152. if p>0 then
  153. delete(hs,p,1);
  154. double2str:=lower(hs);
  155. end;
  156. function TX86NasmAssembler.extended2str(e: extended): string;
  157. var
  158. hs : string;
  159. p : longint;
  160. begin
  161. str(e,hs);
  162. { nasm expects a lowercase e }
  163. p:=pos('E',hs);
  164. if p>0 then
  165. hs[p]:='e';
  166. p:=pos('+',hs);
  167. if p>0 then
  168. delete(hs,p,1);
  169. extended2str:=lower(hs);
  170. end;
  171. destructor TX86NasmAssembler.Destroy;
  172. begin
  173. FSections.Free;
  174. FGroups.Free;
  175. inherited Destroy;
  176. end;
  177. function sizestr(s:topsize;dest:boolean):string;
  178. begin
  179. case s of
  180. S_B : sizestr:='byte ';
  181. S_W : sizestr:='word ';
  182. S_L : sizestr:='dword ';
  183. S_Q : sizestr:='qword ';
  184. S_IS : sizestr:='word ';
  185. S_IL : sizestr:='dword ';
  186. S_IQ : sizestr:='qword ';
  187. S_FS : sizestr:='dword ';
  188. S_FL : sizestr:='qword ';
  189. S_FX : sizestr:='tword ';
  190. S_BW : if dest then
  191. sizestr:='word '
  192. else
  193. sizestr:='byte ';
  194. S_BL : if dest then
  195. sizestr:='dword '
  196. else
  197. sizestr:='byte ';
  198. S_WL : if dest then
  199. sizestr:='dword '
  200. else
  201. sizestr:='word ';
  202. {$ifdef x86_64}
  203. S_BQ : if dest then
  204. sizestr:='qword '
  205. else
  206. sizestr:='byte ';
  207. S_WQ : if dest then
  208. sizestr:='qword '
  209. else
  210. sizestr:='word ';
  211. S_LQ : if dest then
  212. sizestr:='qword '
  213. else
  214. sizestr:='dword ';
  215. { Nothing needed for XMM registers }
  216. S_XMM: sizestr:='';
  217. {$endif x86_64}
  218. else { S_NO }
  219. sizestr:='';
  220. end;
  221. end;
  222. Function PadTabs(const p:string;addch:char):string;
  223. var
  224. s : string;
  225. i : longint;
  226. begin
  227. i:=length(p);
  228. if addch<>#0 then
  229. begin
  230. inc(i);
  231. s:=p+addch;
  232. end
  233. else
  234. s:=p;
  235. if i<8 then
  236. PadTabs:=s+#9#9
  237. else
  238. PadTabs:=s+#9;
  239. end;
  240. {****************************************************************************
  241. TX86NasmAssembler.TX86NasmGroup
  242. ****************************************************************************}
  243. constructor TX86NasmAssembler.TX86NasmGroup.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  244. begin
  245. inherited;
  246. Sections:=TFPHashObjectList.Create;
  247. end;
  248. destructor TX86NasmAssembler.TX86NasmGroup.Destroy;
  249. begin
  250. Sections.Free;
  251. inherited Destroy;
  252. end;
  253. {****************************************************************************
  254. TX86NasmAssembler
  255. ****************************************************************************}
  256. function TX86NasmAssembler.CodeSectionName(const aname:string): string;
  257. begin
  258. {$ifdef i8086}
  259. if current_settings.x86memorymodel in x86_far_code_models then
  260. begin
  261. if cs_huge_code in current_settings.moduleswitches then
  262. result:=aname + '_TEXT'
  263. else
  264. result:=current_module.modulename^ + '_TEXT';
  265. end
  266. else
  267. result:='_TEXT';
  268. {$else i8086}
  269. result:='.text';
  270. {$endif}
  271. end;
  272. procedure TX86NasmAssembler.WriteReference(var ref : treference);
  273. var
  274. first : boolean;
  275. base_done : boolean;
  276. begin
  277. with ref do
  278. begin
  279. writer.AsmWrite('[');
  280. first:=true;
  281. base_done:=false;
  282. if (segment<>NR_NO) then
  283. writer.AsmWrite(nasm_regname(segment)+':');
  284. {$ifdef x86_64}
  285. if (base=NR_RIP) then
  286. begin
  287. { nasm RIP is implicit for pic }
  288. if not (ref.refaddr in [addr_pic,addr_pic_no_got]) and not using_relative then
  289. writer.AsmWrite('$ + ');
  290. base_done:=true;
  291. end;
  292. {$endif x86_64}
  293. if assigned(symbol) then
  294. begin
  295. writer.AsmWrite(symbol.name);
  296. if SmartAsm then
  297. AddSymbol(symbol.name,false);
  298. first:=false;
  299. end;
  300. if (base<>NR_NO) and not base_done then
  301. begin
  302. if not(first) then
  303. writer.AsmWrite('+')
  304. else
  305. first:=false;
  306. writer.AsmWrite(nasm_regname(base))
  307. end;
  308. if (index<>NR_NO) then
  309. begin
  310. if not(first) then
  311. writer.AsmWrite('+')
  312. else
  313. first:=false;
  314. writer.AsmWrite(nasm_regname(index));
  315. if scalefactor<>0 then
  316. writer.AsmWrite('*'+tostr(scalefactor));
  317. end;
  318. if offset<0 then
  319. begin
  320. writer.AsmWrite(tostr(offset));
  321. first:=false;
  322. end
  323. else if (offset>0) then
  324. begin
  325. writer.AsmWrite('+'+tostr(offset));
  326. first:=false;
  327. end;
  328. if first then
  329. writer.AsmWrite('0');
  330. writer.AsmWrite(']');
  331. end;
  332. end;
  333. procedure TX86NasmAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
  334. begin
  335. case o.typ of
  336. top_reg :
  337. writer.AsmWrite(nasm_regname(o.reg));
  338. top_const :
  339. begin
  340. if (ops=1) and (opcode<>A_RET) then
  341. writer.AsmWrite(sizestr(s,dest));
  342. writer.AsmWrite(tostr(longint(o.val)));
  343. end;
  344. top_ref :
  345. begin
  346. if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got] then
  347. begin
  348. if not ((opcode = A_LEA) or (opcode = A_LGS) or
  349. (opcode = A_LSS) or (opcode = A_LFS) or
  350. {$ifndef x86_64}
  351. (opcode = A_LES) or (opcode = A_LDS) or
  352. {$endif x86_64}
  353. // (opcode = A_SHR) or (opcode = A_SHL) or
  354. // (opcode = A_SAR) or (opcode = A_SAL) or
  355. (opcode = A_OUT) or (opcode = A_IN)) then
  356. writer.AsmWrite(sizestr(s,dest));
  357. WriteReference(o.ref^);
  358. end
  359. {$ifdef i8086}
  360. else if o.ref^.refaddr=addr_dgroup then
  361. begin
  362. writer.AsmWrite('DGROUP');
  363. { Make sure GROUP DGROUP is generated }
  364. AddGroup('DGROUP');
  365. end
  366. else if o.ref^.refaddr=addr_fardataseg then
  367. begin
  368. writer.AsmWrite(current_module.modulename^+'_DATA');
  369. end
  370. {$endif i8086}
  371. else
  372. begin
  373. {$ifdef x86_64}
  374. if s=S_L then
  375. writer.AsmWrite('dword ')
  376. else
  377. writer.AsmWrite('qword ');
  378. {$endif}
  379. {$ifdef i386}
  380. writer.AsmWrite('dword ');
  381. {$endif i386}
  382. {$ifdef i8086}
  383. if o.ref^.refaddr=addr_seg then
  384. writer.AsmWrite('SEG ')
  385. else
  386. writer.AsmWrite('word ');
  387. {$endif i8086}
  388. if assigned(o.ref^.symbol) then
  389. begin
  390. if SmartAsm then
  391. AddSymbol(o.ref^.symbol.name,false);
  392. writer.AsmWrite(o.ref^.symbol.name);
  393. if o.ref^.offset=0 then
  394. exit;
  395. end;
  396. if o.ref^.offset>0 then
  397. writer.AsmWrite('+');
  398. writer.AsmWrite(tostr(o.ref^.offset));
  399. end;
  400. end;
  401. else
  402. internalerror(10001);
  403. end;
  404. end;
  405. procedure TX86NasmAssembler.WriteOper_jmp(const o:toper; ai : taicpu);
  406. begin
  407. case o.typ of
  408. top_reg :
  409. writer.AsmWrite(nasm_regname(o.reg));
  410. top_ref :
  411. if o.ref^.refaddr=addr_no then
  412. begin
  413. if ai.opsize=S_FAR then
  414. writer.AsmWrite('far ');
  415. WriteReference(o.ref^);
  416. end
  417. else
  418. begin
  419. if ai.opsize=S_FAR then
  420. writer.AsmWrite('far ');
  421. { else
  422. writer.AsmWrite('near ') just disables short branches, increasing code size.
  423. Omitting it does not cause any bad effects, tested with nasm 2.11. }
  424. writer.AsmWrite(o.ref^.symbol.name);
  425. if SmartAsm then
  426. AddSymbol(o.ref^.symbol.name,false);
  427. if o.ref^.offset>0 then
  428. writer.AsmWrite('+'+tostr(o.ref^.offset))
  429. else
  430. if o.ref^.offset<0 then
  431. writer.AsmWrite(tostr(o.ref^.offset));
  432. end;
  433. top_const :
  434. writer.AsmWrite(tostr(aint(o.val)));
  435. else
  436. internalerror(10001);
  437. end;
  438. end;
  439. const
  440. ait_const2str : array[aitconst_128bit..aitconst_64bit_unaligned] of string[30]=(
  441. #9'FIXME_128BIT'#9,#9'DQ'#9,#9'DD'#9,#9'DW'#9,#9'DB'#9,
  442. #9'FIXME_SLEB128BIT'#9,#9'FIXME_ULEB128BIT'#9,
  443. #9'RVA'#9,#9'SECREL32'#9,#9'FIXME_darwin_dwarf_delta64'#9,
  444. #9'FIXME_darwin_dwarf_delta32'#9,#9'FIXME_half16bit'#9,#9'FIXME_gs'#9,
  445. #9'DW'#9,#9'DD'#9,#9'FIXME_64BIT_UNALIGNED'#9
  446. );
  447. procedure TX86NasmAssembler.WriteSection(atype : TAsmSectiontype;
  448. const aname : string; alignment : longint);
  449. const
  450. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  451. '.text',
  452. '.data',
  453. '.data',
  454. '.rodata',
  455. '.bss',
  456. '.tbss',
  457. '.pdata',
  458. '.text','.data','.data','.data','.data',
  459. '.stab',
  460. '.stabstr',
  461. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  462. '.eh_frame',
  463. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  464. '.fpc',
  465. '',
  466. '.init',
  467. '.fini',
  468. '.objc_class',
  469. '.objc_meta_class',
  470. '.objc_cat_cls_meth',
  471. '.objc_cat_inst_meth',
  472. '.objc_protocol',
  473. '.objc_string_object',
  474. '.objc_cls_meth',
  475. '.objc_inst_meth',
  476. '.objc_cls_refs',
  477. '.objc_message_refs',
  478. '.objc_symbols',
  479. '.objc_category',
  480. '.objc_class_vars',
  481. '.objc_instance_vars',
  482. '.objc_module_info',
  483. '.objc_class_names',
  484. '.objc_meth_var_types',
  485. '.objc_meth_var_names',
  486. '.objc_selector_strs',
  487. '.objc_protocol_ext',
  488. '.objc_class_ext',
  489. '.objc_property',
  490. '.objc_image_info',
  491. '.objc_cstring_object',
  492. '.objc_sel_fixup',
  493. '__DATA,__objc_data',
  494. '__DATA,__objc_const',
  495. '.objc_superrefs',
  496. '__DATA, __datacoal_nt,coalesced',
  497. '.objc_classlist',
  498. '.objc_nlclasslist',
  499. '.objc_catlist',
  500. '.obcj_nlcatlist',
  501. '.objc_protolist',
  502. '.stack',
  503. '.heap',
  504. ',gcc_except_table'
  505. );
  506. var
  507. secname,secgroup: string;
  508. begin
  509. writer.AsmLn;
  510. writer.AsmWrite('SECTION ');
  511. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  512. Thus, data which normally goes into .rodata and .rodata_norel sections must
  513. end up in .data section }
  514. if (atype in [sec_rodata,sec_rodata_norel]) and
  515. (target_info.system=system_i386_go32v2) then
  516. writer.AsmWrite('.data')
  517. else if (atype=sec_user) then
  518. writer.AsmWrite(aname)
  519. else if (atype=sec_threadvar) and
  520. (target_info.system in (systems_windows+systems_wince)) then
  521. writer.AsmWrite('.tls'#9'bss')
  522. else if target_info.system in [system_i8086_msdos,system_i8086_win16,system_i8086_embedded] then
  523. begin
  524. if secnames[atype]='.text' then
  525. secname:=CodeSectionName(aname)
  526. else if omf_segclass(atype)='FAR_DATA' then
  527. secname:=current_module.modulename^ + '_DATA'
  528. else
  529. secname:=omf_secnames[atype];
  530. writer.AsmWrite(secname);
  531. { first use of this section in the object file? }
  532. if FSections.Find(secname)=nil then
  533. begin
  534. { yes -> write the section attributes as well }
  535. if atype=sec_stack then
  536. writer.AsmWrite(' stack');
  537. if atype in [sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev,sec_debug_aranges,sec_debug_ranges] then
  538. writer.AsmWrite(' use32')
  539. else
  540. writer.AsmWrite(' use16');
  541. writer.AsmWrite(' class='+omf_segclass(atype)+
  542. ' align='+tostr(omf_sectiontype2align(atype)));
  543. TX86NasmSection.Create(FSections,secname);
  544. secgroup:=omf_section_primary_group(atype,aname);
  545. if secgroup<>'' then
  546. AddSegmentToGroup(secgroup,secname);
  547. end;
  548. end
  549. else if secnames[atype]='.text' then
  550. writer.AsmWrite(CodeSectionName(aname))
  551. else
  552. writer.AsmWrite(secnames[atype]);
  553. if create_smartlink_sections and
  554. (atype<>sec_bss) and
  555. (aname<>'') then
  556. begin
  557. writer.AsmWrite('.');
  558. writer.AsmWrite(aname);
  559. if atype in [sec_init, sec_fini, sec_stub, sec_code] then
  560. writer.AsmWrite(' code align='+tostr(alignment))
  561. else if atype in [sec_rodata, sec_rodata_norel] then
  562. writer.AsmWrite(' rdata align='+tostr(alignment))
  563. else
  564. writer.AsmWrite(' data align='+tostr(alignment))
  565. end;
  566. writer.AsmLn;
  567. LastSecType:=atype;
  568. end;
  569. procedure TX86NasmAssembler.ResetSectionsList;
  570. begin
  571. FSections.Free;
  572. FSections:=TFPHashObjectList.Create;
  573. FGroups.Free;
  574. FGroups:=TFPHashObjectList.Create;
  575. end;
  576. procedure TX86NasmAssembler.AddGroup(const grpname: string);
  577. begin
  578. if FGroups.Find(grpname)=nil then
  579. TX86NasmGroup.Create(FGroups,grpname);
  580. end;
  581. procedure TX86NasmAssembler.AddSegmentToGroup(const grpname, segname: string);
  582. var
  583. grp: TX86NasmGroup;
  584. begin
  585. grp:=TX86NasmGroup(FGroups.Find(grpname));
  586. if grp=nil then
  587. grp:=TX86NasmGroup.Create(FGroups,grpname);
  588. TX86NasmSection.Create(grp.Sections,segname);
  589. end;
  590. procedure TX86NasmAssembler.WriteGroup(data: TObject; arg: pointer);
  591. var
  592. grp: TX86NasmGroup;
  593. i: Integer;
  594. begin
  595. grp:=TX86NasmGroup(data);
  596. writer.AsmWrite('GROUP '+grp.Name);
  597. for i:=0 to grp.Sections.Count-1 do
  598. writer.AsmWrite(' '+grp.Sections.NameOfIndex(i));
  599. writer.AsmLn;
  600. end;
  601. procedure TX86NasmAssembler.WriteGroups;
  602. {$ifdef i8086}
  603. var
  604. i: Integer;
  605. {$endif i8086}
  606. begin
  607. {$ifdef i8086}
  608. if target_info.system in [system_i8086_msdos,system_i8086_win16,system_i8086_embedded] then
  609. begin
  610. if current_settings.x86memorymodel=mm_huge then
  611. WriteSection(sec_data,'',2);
  612. writer.AsmLn;
  613. FGroups.ForEachCall(@WriteGroup,nil);
  614. end;
  615. {$endif i8086}
  616. end;
  617. procedure TX86NasmAssembler.WriteTree(p:TAsmList);
  618. {$ifdef cpuextended}
  619. type
  620. t80bitarray = array[0..9] of byte;
  621. {$endif cpuextended}
  622. var
  623. s : string;
  624. hp : tai;
  625. counter,
  626. lines,
  627. i,j,l : longint;
  628. InlineLevel : longint;
  629. consttype : taiconst_type;
  630. do_line, SkipNewLine,
  631. quoted : boolean;
  632. fixed_opcode: TAsmOp;
  633. prefix, LastSecName : string;
  634. LastAlign : LongInt;
  635. cpu: tcputype;
  636. prevfileinfo : tfileposinfo;
  637. previnfile : tinputfile;
  638. NewObject : boolean;
  639. begin
  640. if not assigned(p) then
  641. exit;
  642. InlineLevel:=0;
  643. NewObject:=true;
  644. { lineinfo is only needed for al_procedures (PFV) }
  645. do_line:=(cs_asm_source in current_settings.globalswitches) or
  646. ((cs_lineinfo in current_settings.moduleswitches)
  647. and (p=current_asmdata.asmlists[al_procedures]));
  648. hp:=tai(p.first);
  649. while assigned(hp) do
  650. begin
  651. prefetch(pointer(hp.next)^);
  652. if not(hp.typ in SkipLineInfo) then
  653. begin
  654. previnfile:=lastinfile;
  655. prevfileinfo:=lastfileinfo;
  656. current_filepos:=tailineinfo(hp).fileinfo;
  657. { no line info for inlined code }
  658. if do_line and (inlinelevel=0) then
  659. WriteSourceLine(hp as tailineinfo);
  660. if (lastfileinfo.line<>prevfileinfo.line) or
  661. (previnfile<>lastinfile) then
  662. begin
  663. { +0 postfix means no line increment per assembler instruction }
  664. writer.AsmWrite('%LINE '+tostr(current_filepos.line)+'+0');
  665. if assigned(lastinfile) and ((previnfile<>lastinfile) or NewObject) then
  666. writer.AsmWriteLn(' '+lastinfile.name)
  667. else
  668. writer.AsmLn;
  669. NewObject:=false;
  670. end;
  671. end;
  672. case hp.typ of
  673. ait_comment :
  674. Begin
  675. writer.AsmWrite(asminfo^.comment);
  676. writer.AsmWritePChar(tai_comment(hp).str);
  677. writer.AsmLn;
  678. End;
  679. ait_regalloc :
  680. begin
  681. if (cs_asm_regalloc in current_settings.globalswitches) then
  682. writer.AsmWriteLn(#9#9+asminfo^.comment+'Register '+nasm_regname(tai_regalloc(hp).reg)+' '+
  683. regallocstr[tai_regalloc(hp).ratype]);
  684. end;
  685. ait_tempalloc :
  686. begin
  687. if (cs_asm_tempalloc in current_settings.globalswitches) then
  688. WriteTempalloc(tai_tempalloc(hp));
  689. end;
  690. ait_section :
  691. begin
  692. if tai_section(hp).sectype<>sec_none then
  693. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secalign);
  694. LastSecType:=tai_section(hp).sectype;
  695. end;
  696. ait_align :
  697. begin
  698. if (tai_align(hp).aligntype>1) then
  699. begin
  700. if (LastSecType=sec_bss) or (
  701. (LastSecType=sec_threadvar) and
  702. (target_info.system in (systems_windows+systems_wince))
  703. ) then
  704. writer.AsmWriteLn(#9'ALIGNB '+tostr(tai_align(hp).aligntype))
  705. else if tai_align_abstract(hp).use_op then
  706. writer.AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype)+',DB '+tostr(tai_align_abstract(hp).fillop))
  707. else if LastSecType in [sec_code,sec_stub,sec_init,sec_fini] then
  708. writer.AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype))
  709. else
  710. writer.AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype)+',DB 0');
  711. end;
  712. end;
  713. ait_datablock :
  714. begin
  715. if tai_datablock(hp).is_global or SmartAsm then
  716. begin
  717. writer.AsmWrite(#9'GLOBAL ');
  718. writer.AsmWriteLn(tai_datablock(hp).sym.name);
  719. end;
  720. writer.AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
  721. if SmartAsm then
  722. AddSymbol(tai_datablock(hp).sym.name,true);
  723. writer.AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
  724. end;
  725. ait_const:
  726. begin
  727. consttype:=tai_const(hp).consttype;
  728. case consttype of
  729. aitconst_uleb128bit,
  730. aitconst_sleb128bit,
  731. aitconst_128bit:
  732. begin
  733. writer.AsmWriteLn(asminfo^.comment+'Unsupported const type '+
  734. ait_const2str[consttype]);
  735. end;
  736. {$ifdef i8086}
  737. aitconst_farptr:
  738. begin
  739. writer.AsmWrite(ait_const2str[aitconst_16bit]);
  740. if assigned(tai_const(hp).sym) then
  741. begin
  742. if SmartAsm then
  743. AddSymbol(tai_const(hp).sym.name,false);
  744. writer.AsmWrite(tai_const(hp).sym.name);
  745. if tai_const(hp).value<>0 then
  746. writer.AsmWrite(tostr_with_plus(tai_const(hp).value));
  747. writer.AsmLn;
  748. writer.AsmWrite(ait_const2str[aitconst_16bit]);
  749. writer.AsmWrite('SEG ');
  750. writer.AsmWrite(tai_const(hp).sym.name);
  751. end
  752. else
  753. writer.AsmWrite(tostr(lo(longint(tai_const(hp).value)))+','+
  754. tostr(hi(longint(tai_const(hp).value))));
  755. writer.AsmLn;
  756. end;
  757. aitconst_seg:
  758. begin
  759. writer.AsmWrite(ait_const2str[aitconst_16bit]);
  760. if assigned(tai_const(hp).sym) then
  761. begin
  762. if SmartAsm then
  763. AddSymbol(tai_const(hp).sym.name,false);
  764. writer.AsmWrite('SEG ');
  765. writer.AsmWrite(tai_const(hp).sym.name);
  766. end
  767. else
  768. internalerror(2015110501);
  769. writer.AsmLn;
  770. end;
  771. aitconst_dgroup:
  772. writer.AsmWriteLn(#9'DW'#9'DGROUP');
  773. aitconst_fardataseg:
  774. writer.AsmWriteLn(#9'DW'#9+current_module.modulename^+'_DATA');
  775. {$endif i8086}
  776. {$ifdef x86_64}
  777. aitconst_rva_symbol,
  778. aitconst_secrel32_symbol: ;
  779. {$endif x86_64}
  780. {$ifdef i386}
  781. aitconst_rva_symbol,
  782. aitconst_secrel32_symbol,
  783. {$endif i386}
  784. aitconst_64bit,
  785. aitconst_32bit,
  786. aitconst_16bit,
  787. aitconst_8bit,
  788. aitconst_16bit_unaligned,
  789. aitconst_32bit_unaligned,
  790. aitconst_64bit_unaligned:
  791. begin
  792. writer.AsmWrite(ait_const2str[tai_const(hp).consttype]);
  793. l:=0;
  794. repeat
  795. if assigned(tai_const(hp).sym) then
  796. begin
  797. if SmartAsm then
  798. begin
  799. AddSymbol(tai_const(hp).sym.name,false);
  800. if assigned(tai_const(hp).endsym) then
  801. AddSymbol(tai_const(hp).endsym.name,false);
  802. end;
  803. if assigned(tai_const(hp).endsym) then
  804. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  805. else
  806. s:=tai_const(hp).sym.name;
  807. if tai_const(hp).value<>0 then
  808. s:=s+tostr_with_plus(tai_const(hp).value);
  809. end
  810. else
  811. s:=tostr(tai_const(hp).value);
  812. writer.AsmWrite(s);
  813. inc(l,length(s));
  814. if (l>line_length) or
  815. (hp.next=nil) or
  816. (tai(hp.next).typ<>ait_const) or
  817. (tai_const(hp.next).consttype<>consttype) then
  818. break;
  819. hp:=tai(hp.next);
  820. writer.AsmWrite(',');
  821. until false;
  822. writer.AsmLn;
  823. end;
  824. else
  825. internalerror(200704252);
  826. end;
  827. end;
  828. ait_realconst:
  829. begin
  830. WriteRealConstAsBytes(tai_realconst(hp),#9#9'DB'#9,do_line);
  831. end;
  832. ait_string :
  833. begin
  834. counter := 0;
  835. lines := tai_string(hp).len div line_length;
  836. { separate lines in different parts }
  837. if tai_string(hp).len > 0 then
  838. Begin
  839. for j := 0 to lines-1 do
  840. begin
  841. writer.AsmWrite(#9#9'DB'#9);
  842. quoted:=false;
  843. for i:=counter to counter+line_length-1 do
  844. begin
  845. { it is an ascii character. }
  846. if (ord(tai_string(hp).str[i])>31) and
  847. (ord(tai_string(hp).str[i])<128) and
  848. (tai_string(hp).str[i]<>'"') then
  849. begin
  850. if not(quoted) then
  851. begin
  852. if i>counter then
  853. writer.AsmWrite(',');
  854. writer.AsmWrite('"');
  855. end;
  856. writer.AsmWrite(tai_string(hp).str[i]);
  857. quoted:=true;
  858. end { if > 31 and < 128 and ord('"') }
  859. else
  860. begin
  861. if quoted then
  862. writer.AsmWrite('"');
  863. if i>counter then
  864. writer.AsmWrite(',');
  865. quoted:=false;
  866. writer.AsmWrite(tostr(ord(tai_string(hp).str[i])));
  867. end;
  868. end; { end for i:=0 to... }
  869. if quoted then writer.AsmWrite('"');
  870. writer.AsmWrite(target_info.newline);
  871. inc(counter,line_length);
  872. end; { end for j:=0 ... }
  873. { do last line of lines }
  874. if counter<tai_string(hp).len then
  875. writer.AsmWrite(#9#9'DB'#9);
  876. quoted:=false;
  877. for i:=counter to tai_string(hp).len-1 do
  878. begin
  879. { it is an ascii character. }
  880. if (ord(tai_string(hp).str[i])>31) and
  881. (ord(tai_string(hp).str[i])<128) and
  882. (tai_string(hp).str[i]<>'"') then
  883. begin
  884. if not(quoted) then
  885. begin
  886. if i>counter then
  887. writer.AsmWrite(',');
  888. writer.AsmWrite('"');
  889. end;
  890. writer.AsmWrite(tai_string(hp).str[i]);
  891. quoted:=true;
  892. end { if > 31 and < 128 and " }
  893. else
  894. begin
  895. if quoted then
  896. writer.AsmWrite('"');
  897. if i>counter then
  898. writer.AsmWrite(',');
  899. quoted:=false;
  900. writer.AsmWrite(tostr(ord(tai_string(hp).str[i])));
  901. end;
  902. end; { end for i:=0 to... }
  903. if quoted then
  904. writer.AsmWrite('"');
  905. end;
  906. writer.AsmLn;
  907. end;
  908. ait_label :
  909. begin
  910. if tai_label(hp).labsym.is_used then
  911. begin
  912. if SmartAsm and (tai_label(hp).labsym.bind=AB_GLOBAL) then
  913. begin
  914. writer.AsmWrite(#9'GLOBAL ');
  915. writer.AsmWriteLn(tai_label(hp).labsym.name);
  916. end;
  917. writer.AsmWriteLn(tai_label(hp).labsym.name+':');
  918. end;
  919. if SmartAsm then
  920. AddSymbol(tai_label(hp).labsym.name,true);
  921. end;
  922. ait_symbol :
  923. begin
  924. if tai_symbol(hp).has_value then
  925. internalerror(2009090803);
  926. if tai_symbol(hp).is_global or SmartAsm then
  927. begin
  928. writer.AsmWrite(#9'GLOBAL ');
  929. writer.AsmWriteLn(tai_symbol(hp).sym.name);
  930. end;
  931. writer.AsmWrite(tai_symbol(hp).sym.name);
  932. if SmartAsm then
  933. AddSymbol(tai_symbol(hp).sym.name,true);
  934. if (not assigned(hp.next)) or (assigned(hp.next) and not(tai(hp.next).typ in
  935. [ait_const,ait_realconst,ait_string])) then
  936. writer.AsmWriteLn(':')
  937. end;
  938. ait_symbol_end : ;
  939. ait_instruction :
  940. begin
  941. fixed_opcode:=taicpu(hp).FixNonCommutativeOpcodes;
  942. { We need intel order, no At&t }
  943. taicpu(hp).SetOperandOrder(op_intel);
  944. { LOCK must be on same line as opcode }
  945. if (taicpu(hp).ops = 0) and
  946. (fixed_opcode = A_LOCK) then
  947. SkipNewLine:=true
  948. else
  949. SkipNewLine:=false;
  950. s:='';
  951. if ((fixed_opcode=A_FADDP) or
  952. (fixed_opcode=A_FMULP))
  953. and (taicpu(hp).ops=0) then
  954. begin
  955. taicpu(hp).allocate_oper(2);
  956. taicpu(hp).oper[0]^.typ:=top_reg;
  957. taicpu(hp).oper[0]^.reg:=NR_ST1;
  958. taicpu(hp).oper[1]^.typ:=top_reg;
  959. taicpu(hp).oper[1]^.reg:=NR_ST;
  960. end;
  961. { NASM only accepts move for loading of
  962. simple symbol address }
  963. if ((taicpu(hp).opcode=A_LEA) and
  964. (taicpu(hp).ops=2) and
  965. (taicpu(hp).oper[0]^.typ=top_reg) and
  966. (reg2opsize(taicpu(hp).oper[0]^.reg) in [S_NO,S_Q]) and
  967. (taicpu(hp).oper[1]^.typ=top_ref) and
  968. (taicpu(hp).oper[1]^.ref^.refaddr<>addr_no) and
  969. assigned(taicpu(hp).oper[1]^.ref^.symbol) and
  970. (taicpu(hp).oper[1]^.ref^.base=NR_NO)) then
  971. begin
  972. writer.AsmWrite(asminfo^.comment);
  973. writer.AsmWriteln('Converting LEA to MOV instruction');
  974. taicpu(hp).opcode:=A_MOV;
  975. end;
  976. if fixed_opcode=A_FWAIT then
  977. writer.AsmWriteln(#9#9'DB'#9'09bh')
  978. else if (fixed_opcode=A_XLAT) and (taicpu(hp).ops=1) and
  979. (taicpu(hp).oper[0]^.typ=top_ref) then
  980. begin
  981. writer.AsmWrite(#9#9);
  982. if (taicpu(hp).oper[0]^.ref^.segment<>NR_NO) and
  983. (taicpu(hp).oper[0]^.ref^.segment<>NR_DS) then
  984. writer.AsmWrite(std_regname(taicpu(hp).oper[0]^.ref^.segment)+' ');
  985. case get_ref_address_size(taicpu(hp).oper[0]^.ref^) of
  986. 16:
  987. writer.AsmWrite('a16 ');
  988. 32:
  989. writer.AsmWrite('a32 ');
  990. 64:
  991. writer.AsmWrite('a64 ');
  992. end;
  993. writer.AsmWriteLn('xlatb');
  994. end
  995. else if is_x86_parameterized_string_op(fixed_opcode) then
  996. begin
  997. writer.AsmWrite(#9#9);
  998. i:=get_x86_string_op_si_param(fixed_opcode);
  999. if (i<>-1) and (taicpu(hp).oper[i]^.typ=top_ref) and
  1000. (taicpu(hp).oper[i]^.ref^.segment<>NR_NO) and
  1001. (taicpu(hp).oper[i]^.ref^.segment<>NR_DS) then
  1002. writer.AsmWrite(std_regname(taicpu(hp).oper[i]^.ref^.segment)+' ');
  1003. for i:=0 to taicpu(hp).ops-1 do
  1004. if taicpu(hp).oper[i]^.typ=top_ref then
  1005. begin
  1006. case get_ref_address_size(taicpu(hp).oper[i]^.ref^) of
  1007. 16:
  1008. writer.AsmWrite('a16 ');
  1009. 32:
  1010. writer.AsmWrite('a32 ');
  1011. 64:
  1012. writer.AsmWrite('a64 ');
  1013. end;
  1014. break;
  1015. end;
  1016. writer.AsmWrite(std_op2str[fixed_opcode]);
  1017. case taicpu(hp).opsize of
  1018. S_B:
  1019. writer.AsmWrite('b');
  1020. S_W:
  1021. writer.AsmWrite('w');
  1022. S_L:
  1023. writer.AsmWrite('d');
  1024. S_Q:
  1025. writer.AsmWrite('q');
  1026. else
  1027. internalerror(2017101101);
  1028. end;
  1029. writer.AsmLn;
  1030. end
  1031. else
  1032. begin
  1033. prefix:='';
  1034. {$ifndef i8086}
  1035. { We need to explicitely set
  1036. word prefix to get selectors
  1037. to be pushed in 2 bytes PM }
  1038. if (taicpu(hp).opsize=S_W) and
  1039. ((fixed_opcode=A_PUSH) or
  1040. (fixed_opcode=A_POP)) and
  1041. (taicpu(hp).oper[0]^.typ=top_reg) and
  1042. (is_segment_reg(taicpu(hp).oper[0]^.reg)) then
  1043. writer.AsmWriteln(#9#9'DB'#9'066h');
  1044. {$endif not i8086}
  1045. if (fixed_opcode=A_RETW) or (fixed_opcode=A_RETNW) or (fixed_opcode=A_RETFW) or
  1046. {$ifdef x86_64}
  1047. (fixed_opcode=A_RETQ) or (fixed_opcode=A_RETNQ) or (fixed_opcode=A_RETFQ) or
  1048. {$else x86_64}
  1049. (fixed_opcode=A_RETD) or (fixed_opcode=A_RETND) or
  1050. {$endif x86_64}
  1051. (fixed_opcode=A_RETFD) then
  1052. begin
  1053. case fixed_opcode of
  1054. A_RETW:
  1055. writer.AsmWrite(#9#9'o16 ret');
  1056. A_RETNW:
  1057. writer.AsmWrite(#9#9'o16 retn');
  1058. A_RETFW:
  1059. writer.AsmWrite(#9#9'o16 retf');
  1060. {$ifdef x86_64}
  1061. A_RETQ,
  1062. A_RETNQ:
  1063. writer.AsmWrite(#9#9'ret');
  1064. A_RETFQ:
  1065. writer.AsmWrite(#9#9'o64 retf');
  1066. {$else x86_64}
  1067. A_RETD:
  1068. writer.AsmWrite(#9#9'o32 ret');
  1069. A_RETND:
  1070. writer.AsmWrite(#9#9'o32 retn');
  1071. {$endif x86_64}
  1072. A_RETFD:
  1073. writer.AsmWrite(#9#9'o32 retf');
  1074. else
  1075. internalerror(2017111001);
  1076. end;
  1077. end
  1078. else if (fixed_opcode=A_SEGCS) or (fixed_opcode=A_SEGDS) or
  1079. (fixed_opcode=A_SEGSS) or (fixed_opcode=A_SEGES) or
  1080. (fixed_opcode=A_SEGFS) or (fixed_opcode=A_SEGGS) then
  1081. begin
  1082. case fixed_opcode of
  1083. A_SEGCS:
  1084. writer.AsmWrite(#9#9'cs');
  1085. A_SEGDS:
  1086. writer.AsmWrite(#9#9'ds');
  1087. A_SEGSS:
  1088. writer.AsmWrite(#9#9'ss');
  1089. A_SEGES:
  1090. writer.AsmWrite(#9#9'es');
  1091. A_SEGFS:
  1092. writer.AsmWrite(#9#9'fs');
  1093. A_SEGGS:
  1094. writer.AsmWrite(#9#9'gs');
  1095. else
  1096. internalerror(2018020101);
  1097. end;
  1098. end
  1099. else
  1100. writer.AsmWrite(#9#9+prefix+std_op2str[fixed_opcode]+cond2str[taicpu(hp).condition]);
  1101. if taicpu(hp).ops<>0 then
  1102. begin
  1103. if is_calljmp(fixed_opcode) then
  1104. begin
  1105. writer.AsmWrite(#9);
  1106. WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp));
  1107. end
  1108. else
  1109. begin
  1110. for i:=0 to taicpu(hp).ops-1 do
  1111. begin
  1112. if i=0 then
  1113. writer.AsmWrite(#9)
  1114. else
  1115. writer.AsmWrite(',');
  1116. WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,fixed_opcode,taicpu(hp).ops,(i=2));
  1117. end;
  1118. end;
  1119. end;
  1120. if not SkipNewLine then
  1121. writer.AsmLn;
  1122. end;
  1123. end;
  1124. ait_stab,
  1125. ait_force_line,
  1126. ait_function_name : ;
  1127. ait_cutobject :
  1128. begin
  1129. if SmartAsm then
  1130. begin
  1131. { only reset buffer if nothing has changed }
  1132. if not writer.ClearIfEmpty then
  1133. begin
  1134. if SmartAsm then
  1135. begin
  1136. WriteSmartExternals;
  1137. FreeExternChainList;
  1138. end;
  1139. WriteGroups;
  1140. writer.AsmClose;
  1141. DoAssemble;
  1142. writer.AsmCreate(tai_cutobject(hp).place);
  1143. ResetSectionsList;
  1144. WriteHeader;
  1145. end;
  1146. { avoid empty files }
  1147. LastSecType:=sec_none;
  1148. LastSecName:='';
  1149. LastAlign:=4;
  1150. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1151. begin
  1152. if tai(hp.next).typ=ait_section then
  1153. begin
  1154. LastSecType:=tai_section(hp.next).sectype;
  1155. LastSecName:=tai_section(hp.next).name^;
  1156. LastAlign:=tai_section(hp.next).secalign;
  1157. end;
  1158. hp:=tai(hp.next);
  1159. end;
  1160. if LastSecType<>sec_none then
  1161. WriteSection(LastSecType,LastSecName,LastAlign);
  1162. writer.MarkEmpty;
  1163. NewObject:=true;
  1164. end;
  1165. end;
  1166. ait_marker :
  1167. if tai_marker(hp).kind=mark_NoLineInfoStart then
  1168. inc(InlineLevel)
  1169. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  1170. dec(InlineLevel);
  1171. ait_directive :
  1172. begin
  1173. case tai_directive(hp).directive of
  1174. asd_nasm_import,
  1175. asd_extern :
  1176. begin
  1177. case tai_directive(hp).directive of
  1178. asd_nasm_import :
  1179. writer.AsmWrite('import ');
  1180. asd_extern :
  1181. writer.AsmWrite('EXTERN ');
  1182. else
  1183. internalerror(200509191);
  1184. end;
  1185. if tai_directive(hp).name<>'' then
  1186. begin
  1187. if SmartAsm then
  1188. AddSymbol(tai_directive(hp).name,false);
  1189. writer.AsmWrite(tai_directive(hp).name);
  1190. end;
  1191. end;
  1192. asd_cpu :
  1193. begin
  1194. writer.AsmWrite('CPU ');
  1195. for cpu:=low(tcputype) to high(tcputype) do
  1196. begin
  1197. if tai_directive(hp).name=CPUTypeStr[CPU] then
  1198. begin
  1199. writer.AsmWriteLn(nasm_cpu_name[cpu]);
  1200. break;
  1201. end;
  1202. end;
  1203. end;
  1204. {$ifdef OMFOBJSUPPORT}
  1205. asd_omf_linnum_line :
  1206. writer.AsmWriteLn('; OMF LINNUM Line '+tai_directive(hp).name);
  1207. {$endif OMFOBJSUPPORT}
  1208. else
  1209. internalerror(200509191);
  1210. end;
  1211. writer.AsmLn;
  1212. end;
  1213. ait_seh_directive :
  1214. { Ignore for now };
  1215. ait_varloc:
  1216. begin
  1217. if tai_varloc(hp).newlocationhi<>NR_NO then
  1218. writer.AsmWriteLn(asminfo^.comment+'Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1219. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation))
  1220. else
  1221. writer.AsmWriteLn(asminfo^.comment+'Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1222. std_regname(tai_varloc(hp).newlocation));
  1223. end;
  1224. else
  1225. internalerror(10000);
  1226. end;
  1227. hp:=tai(hp.next);
  1228. end;
  1229. end;
  1230. procedure TX86NasmAssembler.WriteExternals;
  1231. var
  1232. sym : TAsmSymbol;
  1233. i : longint;
  1234. begin
  1235. for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
  1236. begin
  1237. sym:=TAsmSymbol(current_asmdata.AsmSymbolDict[i]);
  1238. if sym.bind in [AB_EXTERNAL,AB_EXTERNAL_INDIRECT] then
  1239. writer.AsmWriteln('EXTERN'#9+sym.name);
  1240. end;
  1241. end;
  1242. procedure TX86NasmAssembler.WriteSmartExternals;
  1243. var
  1244. EC : PExternChain;
  1245. begin
  1246. EC:=FEC;
  1247. while assigned(EC) do
  1248. begin
  1249. if not EC^.is_defined then
  1250. writer.AsmWriteln('EXTERN'#9+EC^.psym^);
  1251. EC:=EC^.next;
  1252. end;
  1253. end;
  1254. procedure TX86NasmAssembler.WriteHeader;
  1255. begin
  1256. {$if defined(i8086)}
  1257. writer.AsmWriteLn('BITS 16');
  1258. {$elseif defined(i386)}
  1259. writer.AsmWriteLn('BITS 32');
  1260. using_relative:=false;
  1261. {$elseif defined(x86_64)}
  1262. writer.AsmWriteLn('BITS 64');
  1263. writer.AsmWriteLn('default rel');
  1264. using_relative:=true;
  1265. {$endif}
  1266. writer.AsmWriteLn('CPU '+nasm_cpu_name[current_settings.cputype]);
  1267. end;
  1268. procedure TX86NasmAssembler.WriteAsmList;
  1269. var
  1270. hal : tasmlisttype;
  1271. begin
  1272. {$ifdef EXTDEBUG}
  1273. if current_module.mainsource<>'' then
  1274. comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource);
  1275. {$endif}
  1276. ResetSectionsList;
  1277. WriteHeader;
  1278. writer.AsmLn;
  1279. WriteExternals;
  1280. for hal:=low(TasmlistType) to high(TasmlistType) do
  1281. begin
  1282. if not (current_asmdata.asmlists[hal].empty) then
  1283. begin
  1284. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmListTypeStr[hal]);
  1285. writetree(current_asmdata.asmlists[hal]);
  1286. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmListTypeStr[hal]);
  1287. end;
  1288. end;
  1289. writer.AsmLn;
  1290. if SmartAsm then
  1291. begin
  1292. WriteSmartExternals;
  1293. FreeExternChainList;
  1294. end;
  1295. WriteGroups;
  1296. {$ifdef EXTDEBUG}
  1297. if current_module.mainsource<>'' then
  1298. comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource);
  1299. {$endif EXTDEBUG}
  1300. end;
  1301. function TX86NasmAssembler.MakeCmdLine: TCmdStr;
  1302. var
  1303. FormatName : string;
  1304. begin
  1305. result:=Inherited MakeCmdLine;
  1306. {$ifdef i8086}
  1307. case target_info.system of
  1308. system_i8086_msdos,
  1309. system_i8086_win16,
  1310. system_i8086_embedded:
  1311. begin
  1312. FormatName:='obj';
  1313. if (cs_debuginfo in current_settings.moduleswitches) or
  1314. (cs_asm_source in current_settings.globalswitches) then
  1315. Replace(result,'$DEBUG','-g')
  1316. else
  1317. Replace(result,'$DEBUG','');
  1318. end
  1319. else
  1320. internalerror(2014082060);
  1321. end;
  1322. {$endif i8086}
  1323. {$ifdef i386}
  1324. case target_info.system of
  1325. system_i386_go32v2:
  1326. FormatName:='coff';
  1327. system_i386_wdosx,
  1328. system_i386_win32:
  1329. FormatName:='win32';
  1330. system_i386_embedded:
  1331. FormatName:='obj';
  1332. system_i386_linux,
  1333. system_i386_beos:
  1334. FormatName:='elf';
  1335. system_i386_darwin:
  1336. FormatName:='macho32';
  1337. else
  1338. FormatName:='elf';
  1339. end;
  1340. {$endif i386}
  1341. {$ifdef x86_64}
  1342. case target_info.system of
  1343. system_x86_64_win64:
  1344. FormatName:='win64';
  1345. system_x86_64_darwin:
  1346. FormatName:='macho64';
  1347. system_x86_64_embedded:
  1348. FormatName:='obj';
  1349. system_x86_64_linux:
  1350. FormatName:='elf64';
  1351. else
  1352. FormatName:='elf64';
  1353. end;
  1354. {$endif x86_64}
  1355. Replace(result,'$FORMAT',FormatName);
  1356. end;
  1357. {*****************************************************************************
  1358. Initialize
  1359. *****************************************************************************}
  1360. {$ifdef i8086}
  1361. const
  1362. as_i8086_nasm_info : tasminfo =
  1363. (
  1364. id : as_i8086_nasm;
  1365. idtxt : 'NASM';
  1366. asmbin : 'nasm';
  1367. asmcmd : '-f $FORMAT $DEBUG -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1368. supported_targets : [system_i8086_msdos,system_i8086_win16,system_i8086_embedded];
  1369. flags : [af_needar,af_no_debug];
  1370. labelprefix : '..@';
  1371. comment : '; ';
  1372. dollarsign: '$';
  1373. );
  1374. as_i8086_nasmobj_info : tasminfo =
  1375. (
  1376. id : as_i8086_nasmobj;
  1377. idtxt : 'NASMOBJ';
  1378. asmbin : 'nasm';
  1379. asmcmd : '-f obj -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1380. supported_targets : [system_i8086_msdos,system_i8086_win16,system_i8086_embedded];
  1381. flags : [af_needar,af_no_debug];
  1382. labelprefix : '..@';
  1383. comment : '; ';
  1384. dollarsign: '$';
  1385. );
  1386. {$endif i8086}
  1387. {$ifdef i386}
  1388. const
  1389. as_i386_nasmcoff_info : tasminfo =
  1390. (
  1391. id : as_i386_nasmcoff;
  1392. idtxt : 'NASMCOFF';
  1393. asmbin : 'nasm';
  1394. asmcmd : '-f coff -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1395. supported_targets : [system_i386_go32v2];
  1396. flags : [af_needar,af_no_debug];
  1397. labelprefix : '..@';
  1398. comment : '; ';
  1399. dollarsign: '$';
  1400. );
  1401. as_i386_nasmwin32_info : tasminfo =
  1402. (
  1403. id : as_i386_nasmwin32;
  1404. idtxt : 'NASMWIN32';
  1405. asmbin : 'nasm';
  1406. asmcmd : '-f win32 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1407. supported_targets : [system_i386_win32];
  1408. flags : [af_needar,af_no_debug,af_smartlink_sections];
  1409. labelprefix : '..@';
  1410. comment : '; ';
  1411. dollarsign: '$';
  1412. );
  1413. as_i386_nasmobj_info : tasminfo =
  1414. (
  1415. id : as_i386_nasmobj;
  1416. idtxt : 'NASMOBJ';
  1417. asmbin : 'nasm';
  1418. asmcmd : '-f obj -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1419. supported_targets : [system_i386_embedded, system_i8086_msdos];
  1420. flags : [af_needar,af_no_debug];
  1421. labelprefix : '..@';
  1422. comment : '; ';
  1423. dollarsign: '$';
  1424. );
  1425. as_i386_nasmwdosx_info : tasminfo =
  1426. (
  1427. id : as_i386_nasmwdosx;
  1428. idtxt : 'NASMWDOSX';
  1429. asmbin : 'nasm';
  1430. asmcmd : '-f win32 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1431. supported_targets : [system_i386_wdosx];
  1432. flags : [af_needar,af_no_debug];
  1433. labelprefix : '..@';
  1434. comment : '; ';
  1435. dollarsign: '$';
  1436. );
  1437. as_i386_nasmelf_info : tasminfo =
  1438. (
  1439. id : as_i386_nasmelf;
  1440. idtxt : 'NASMELF';
  1441. asmbin : 'nasm';
  1442. asmcmd : '-f elf -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1443. supported_targets : [system_i386_linux];
  1444. flags : [af_needar,af_no_debug];
  1445. labelprefix : '..@';
  1446. comment : '; ';
  1447. dollarsign: '$';
  1448. );
  1449. {
  1450. as_i386_nasmdarwin_info : tasminfo =
  1451. (
  1452. id : as_i386_nasmdarwin;
  1453. idtxt : 'NASMDARWIN';
  1454. asmbin : 'nasm';
  1455. asmcmd : '-f macho32 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1456. supported_targets : [system_i386_darwin];
  1457. flags : [af_needar,af_no_debug];
  1458. labelprefix : '..@';
  1459. comment : '; ';
  1460. dollarsign: '$';
  1461. );
  1462. }
  1463. as_i386_nasmbeos_info : tasminfo =
  1464. (
  1465. id : as_i386_nasmbeos;
  1466. idtxt : 'NASMELF';
  1467. asmbin : 'nasm';
  1468. asmcmd : '-f elf -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1469. supported_targets : [system_i386_beos];
  1470. flags : [af_needar,af_no_debug];
  1471. labelprefix : '..@';
  1472. comment : '; ';
  1473. dollarsign: '$';
  1474. );
  1475. as_i386_nasmhaiku_info : tasminfo =
  1476. (
  1477. id : as_i386_nasmhaiku;
  1478. idtxt : 'NASMELF';
  1479. asmbin : 'nasm';
  1480. asmcmd : '-f elf -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1481. supported_targets : [system_i386_haiku];
  1482. flags : [af_needar,af_no_debug];
  1483. labelprefix : '..@';
  1484. comment : '; ';
  1485. dollarsign: '$';
  1486. );
  1487. as_i386_nasm_info : tasminfo =
  1488. (
  1489. id : as_i386_nasm;
  1490. idtxt : 'NASM';
  1491. asmbin : 'nasm';
  1492. asmcmd : '-f $FORMAT -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1493. supported_targets : [system_any];
  1494. flags : [af_needar,af_no_debug];
  1495. labelprefix : '..@';
  1496. comment : '; ';
  1497. dollarsign: '$';
  1498. );
  1499. {$endif i386}
  1500. {$ifdef x86_64}
  1501. const
  1502. as_x86_64_nasm_info : tasminfo =
  1503. (
  1504. id : as_x86_64_nasm;
  1505. idtxt : 'NASM';
  1506. asmbin : 'nasm';
  1507. asmcmd : '-f $FORMAT -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1508. supported_targets : [system_any];
  1509. flags : [af_needar{,af_no_debug}];
  1510. labelprefix : '..@';
  1511. comment : '; ';
  1512. dollarsign: '$';
  1513. );
  1514. as_x86_64_nasmwin64_info : tasminfo =
  1515. (
  1516. id : as_x86_64_nasmwin64;
  1517. idtxt : 'NASMWIN64';
  1518. asmbin : 'nasm';
  1519. asmcmd : '-f win64 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1520. supported_targets : [system_x86_64_win64];
  1521. flags : [af_needar,af_no_debug];
  1522. labelprefix : '..@';
  1523. comment : '; ';
  1524. dollarsign: '$';
  1525. );
  1526. as_x86_64_nasmelf_info : tasminfo =
  1527. (
  1528. id : as_x86_64_nasmelf;
  1529. idtxt : 'NASMELF';
  1530. asmbin : 'nasm';
  1531. asmcmd : '-f elf64 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1532. supported_targets : [system_x86_64_linux];
  1533. flags : [af_needar,af_no_debug];
  1534. labelprefix : '..@';
  1535. comment : '; ';
  1536. dollarsign: '$';
  1537. );
  1538. as_x86_64_nasmdarwin_info : tasminfo =
  1539. (
  1540. id : as_x86_64_nasmdarwin;
  1541. idtxt : 'NASMDARWIN';
  1542. asmbin : 'nasm';
  1543. asmcmd : '-f macho64 -o $OBJ -w-orphan-labels $EXTRAOPT $ASM';
  1544. supported_targets : [system_x86_64_darwin];
  1545. flags : [af_needar,af_no_debug];
  1546. labelprefix : '..@';
  1547. comment : '; ';
  1548. dollarsign: '$';
  1549. );
  1550. {$endif x86_64}
  1551. initialization
  1552. {$ifdef i8086}
  1553. RegisterAssembler(as_i8086_nasm_info,TX86NasmAssembler);
  1554. RegisterAssembler(as_i8086_nasmobj_info,TX86NasmAssembler);
  1555. {$endif i8086}
  1556. {$ifdef i386}
  1557. RegisterAssembler(as_i386_nasmcoff_info,TX86NasmAssembler);
  1558. RegisterAssembler(as_i386_nasmwin32_info,TX86NasmAssembler);
  1559. RegisterAssembler(as_i386_nasmwdosx_info,TX86NasmAssembler);
  1560. RegisterAssembler(as_i386_nasmobj_info,TX86NasmAssembler);
  1561. RegisterAssembler(as_i386_nasmbeos_info,TX86NasmAssembler);
  1562. RegisterAssembler(as_i386_nasmhaiku_info,TX86NasmAssembler);
  1563. RegisterAssembler(as_i386_nasmelf_info,TX86NasmAssembler);
  1564. RegisterAssembler(as_i386_nasm_info,TX86NasmAssembler);
  1565. {$endif i386}
  1566. {$ifdef x86_64}
  1567. RegisterAssembler(as_x86_64_nasm_info,TX86NasmAssembler);
  1568. RegisterAssembler(as_x86_64_nasmwin64_info,TX86NasmAssembler);
  1569. RegisterAssembler(as_x86_64_nasmelf_info,TX86NasmAssembler);
  1570. RegisterAssembler(as_x86_64_nasmdarwin_info,TX86NasmAssembler);
  1571. {$endif x86_64}
  1572. end.