agx86nsm.pas 59 KB

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