agz80vasm.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. {
  2. Copyright (c) 2003 by Florian Klaempfl
  3. This unit implements an asm for the Z80
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { This unit implements the assembler writer for the vasm assembler:
  18. http://sun.hasenbraten.de/vasm/
  19. }
  20. unit agz80vasm;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,systems,
  25. aasmbase,aasmtai,aasmdata,aasmcpu,
  26. assemble,
  27. cpubase;
  28. type
  29. { TZ80vasm }
  30. TZ80Vasm=class(TExternalAssembler)
  31. private
  32. procedure WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  33. function sectionattrs(atype:TAsmSectiontype):string;
  34. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  35. procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint;
  36. secflags:TSectionFlags=[];secprogbits:TSectionProgbits=SPB_None);
  37. procedure WriteInstruction(hp: taicpu);
  38. procedure WriteOper(const o:toper; opcode: tasmop;ops:longint;dest : boolean);
  39. procedure WriteOper_jmp(const o:toper; ai : taicpu);
  40. procedure WriteExternals;
  41. public
  42. procedure WriteTree(p : TAsmList); override;
  43. procedure WriteAsmList;override;
  44. function MakeCmdLine: TCmdStr; override;
  45. end;
  46. implementation
  47. uses
  48. cutils,globals,verbose,
  49. cpuinfo,
  50. cgbase,cgutils,
  51. {$ifdef FPC_SOFT_FPUX80}
  52. sfpux80,
  53. {$endif FPC_SOFT_FPUX80}
  54. finput;
  55. const
  56. line_length = 70;
  57. max_tokens : longint = 25;
  58. ait_const2str : array[aitconst_128bit..aitconst_64bit_unaligned] of string[20]=(
  59. #9''#9,#9'FIXMEDQ'#9,#9'FIXMEDD'#9,#9'.word'#9,#9'.byte'#9,
  60. #9'FIXMESLEB',#9'FIXEMEULEB',
  61. #9'FIXMEDD RVA'#9,#9'FIXMEDD SECREL32'#9,
  62. #9'FIXME',#9'FIXME',#9'FIXME',#9'FIXME',
  63. #9'.uahalf'#9,#9'FIXMEDD'#9,#9'FIXMEDQ'#9
  64. );
  65. procedure TZ80vasm.WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  66. var
  67. pdata: pbyte;
  68. index, step, swapmask, count: longint;
  69. ssingle: single;
  70. ddouble: double;
  71. ccomp: comp;
  72. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  73. eextended: extended;
  74. {$else}
  75. {$ifdef FPC_SOFT_FPUX80}
  76. eextended: floatx80;
  77. {$endif}
  78. {$endif cpuextended}
  79. begin
  80. if do_line then
  81. begin
  82. case tai_realconst(hp).realtyp of
  83. aitrealconst_s32bit:
  84. writer.AsmWriteLn(asminfo^.comment+'value: '+single2str(tai_realconst(hp).value.s32val));
  85. aitrealconst_s64bit:
  86. writer.AsmWriteLn(asminfo^.comment+'value: '+double2str(tai_realconst(hp).value.s64val));
  87. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  88. { can't write full 80 bit floating point constants yet on non-x86 }
  89. aitrealconst_s80bit:
  90. writer.AsmWriteLn(asminfo^.comment+'value: '+extended2str(tai_realconst(hp).value.s80val));
  91. {$else}
  92. {$ifdef FPC_SOFT_FPUX80}
  93. {$push}{$warn 6018 off} { Unreachable code due to compile time evaluation }
  94. aitrealconst_s80bit:
  95. begin
  96. if sizeof(tai_realconst(hp).value.s80val) = sizeof(double) then
  97. writer.AsmWriteLn(asminfo^.comment+'value: '+double2str(tai_realconst(hp).value.s80val))
  98. else if sizeof(tai_realconst(hp).value.s80val) = sizeof(single) then
  99. writer.AsmWriteLn(asminfo^.comment+'value: '+single2str(tai_realconst(hp).value.s80val))
  100. else
  101. internalerror(2017091906);
  102. end;
  103. {$pop}
  104. {$endif}
  105. {$endif cpuextended}
  106. aitrealconst_s64comp:
  107. writer.AsmWriteLn(asminfo^.comment+'value: '+extended2str(tai_realconst(hp).value.s64compval));
  108. else
  109. internalerror(2014050602);
  110. end;
  111. end;
  112. writer.AsmWrite(dbdir);
  113. { generic float writing code: get start address of value, then write
  114. byte by byte. Can't use fields directly, because e.g ts64comp is
  115. defined as extended on x86 }
  116. case tai_realconst(hp).realtyp of
  117. aitrealconst_s32bit:
  118. begin
  119. ssingle:=single(tai_realconst(hp).value.s32val);
  120. pdata:=@ssingle;
  121. end;
  122. aitrealconst_s64bit:
  123. begin
  124. ddouble:=double(tai_realconst(hp).value.s64val);
  125. pdata:=@ddouble;
  126. end;
  127. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  128. { can't write full 80 bit floating point constants yet on non-x86 }
  129. aitrealconst_s80bit:
  130. begin
  131. eextended:=extended(tai_realconst(hp).value.s80val);
  132. pdata:=@eextended;
  133. end;
  134. {$else}
  135. {$ifdef FPC_SOFT_FPUX80}
  136. {$push}{$warn 6018 off} { Unreachable code due to compile time evaluation }
  137. aitrealconst_s80bit:
  138. begin
  139. if sizeof(tai_realconst(hp).value.s80val) = sizeof(double) then
  140. eextended:=float64_to_floatx80(float64(double(tai_realconst(hp).value.s80val)))
  141. else if sizeof(tai_realconst(hp).value.s80val) = sizeof(single) then
  142. eextended:=float32_to_floatx80(float32(single(tai_realconst(hp).value.s80val)))
  143. else
  144. internalerror(2017091907);
  145. pdata:=@eextended;
  146. end;
  147. {$pop}
  148. {$endif}
  149. {$endif cpuextended}
  150. aitrealconst_s64comp:
  151. begin
  152. ccomp:=comp(tai_realconst(hp).value.s64compval);
  153. pdata:=@ccomp;
  154. end;
  155. else
  156. internalerror(2014051003);
  157. end;
  158. count:=tai_realconst(hp).datasize;
  159. { write bytes in inverse order if source and target endianess don't
  160. match }
  161. if source_info.endian<>target_info.endian then
  162. begin
  163. { go from back to front }
  164. index:=count-1;
  165. step:=-1;
  166. end
  167. else
  168. begin
  169. index:=0;
  170. step:=1;
  171. end;
  172. {$ifdef ARM}
  173. { ARM-specific: low and high dwords of a double may be swapped }
  174. if tai_realconst(hp).formatoptions=fo_hiloswapped then
  175. begin
  176. { only supported for double }
  177. if tai_realconst(hp).datasize<>8 then
  178. internalerror(2014050609);
  179. { switch bit of the index so that the words are written in
  180. the opposite order }
  181. swapmask:=4;
  182. end
  183. else
  184. {$endif ARM}
  185. swapmask:=0;
  186. repeat
  187. writer.AsmWrite(tostr(pdata[index xor swapmask]));
  188. inc(index,step);
  189. dec(count);
  190. if count<>0 then
  191. writer.AsmWrite(',');
  192. until count=0;
  193. { padding }
  194. for count:=tai_realconst(hp).datasize+1 to tai_realconst(hp).savesize do
  195. writer.AsmWrite(',0');
  196. writer.AsmLn;
  197. end;
  198. function TZ80vasm.sectionattrs(atype:TAsmSectiontype):string;
  199. begin
  200. case atype of
  201. sec_code, sec_fpc, sec_init, sec_fini:
  202. result:='acrx';
  203. sec_data, sec_rodata, sec_rodata_norel, sec_bss, sec_threadvar:
  204. result:='adrw';
  205. sec_stab, sec_stabstr:
  206. result:='dr';
  207. else
  208. result:='';
  209. end;
  210. end;
  211. function TZ80vasm.sectionname(atype: TAsmSectiontype;
  212. const aname: string; aorder: TAsmSectionOrder): string;
  213. const
  214. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  215. '.text',
  216. '.data',
  217. '.data',
  218. '.rodata',
  219. '.bss',
  220. '.threadvar',
  221. '.pdata',
  222. '', { stubs }
  223. '__DATA,__nl_symbol_ptr',
  224. '__DATA,__la_symbol_ptr',
  225. '__DATA,__mod_init_func',
  226. '__DATA,__mod_term_func',
  227. '.stab',
  228. '.stabstr',
  229. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  230. '.eh_frame',
  231. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges','.debug_loc','.debug_loclists',
  232. '.fpc',
  233. '.toc',
  234. '.init',
  235. '.fini',
  236. '.objc_class',
  237. '.objc_meta_class',
  238. '.objc_cat_cls_meth',
  239. '.objc_cat_inst_meth',
  240. '.objc_protocol',
  241. '.objc_string_object',
  242. '.objc_cls_meth',
  243. '.objc_inst_meth',
  244. '.objc_cls_refs',
  245. '.objc_message_refs',
  246. '.objc_symbols',
  247. '.objc_category',
  248. '.objc_class_vars',
  249. '.objc_instance_vars',
  250. '.objc_module_info',
  251. '.objc_class_names',
  252. '.objc_meth_var_types',
  253. '.objc_meth_var_names',
  254. '.objc_selector_strs',
  255. '.objc_protocol_ext',
  256. '.objc_class_ext',
  257. '.objc_property',
  258. '.objc_image_info',
  259. '.objc_cstring_object',
  260. '.objc_sel_fixup',
  261. '__DATA,__objc_data',
  262. '__DATA,__objc_const',
  263. '.objc_superrefs',
  264. '__DATA, __datacoal_nt,coalesced',
  265. '.objc_classlist',
  266. '.objc_nlclasslist',
  267. '.objc_catlist',
  268. '.obcj_nlcatlist',
  269. '.objc_protolist',
  270. '.stack',
  271. '.heap',
  272. '.gcc_except_table',
  273. '.ARM.attributes',
  274. '.note'
  275. );
  276. var
  277. sep: string[3];
  278. begin
  279. if atype=sec_user then
  280. result:=aname
  281. else
  282. result:=secnames[atype];
  283. if (aname<>'') then
  284. begin
  285. case aorder of
  286. secorder_begin :
  287. sep:='.b_';
  288. secorder_end :
  289. sep:='.z_';
  290. else
  291. sep:='.n_';
  292. end;
  293. result:=result+sep+aname;
  294. end;
  295. { else
  296. result:=secname;}
  297. end;
  298. procedure TZ80vasm.WriteSection(atype: TAsmSectiontype;
  299. const aname: string; aorder: TAsmSectionOrder; secalign: longint;
  300. secflags: TSectionFlags; secprogbits: TSectionProgbits);
  301. var
  302. s : string;
  303. secflag: TSectionFlag;
  304. sectionprogbits,
  305. sectionflags: boolean;
  306. begin
  307. writer.AsmLn;
  308. sectionflags:=false;
  309. sectionprogbits:=false;
  310. writer.AsmWrite(#9'.section ');
  311. { sectionname may rename those sections, so we do not write flags/progbits for them,
  312. the assembler will ignore them/spite out a warning anyways }
  313. if not(atype in [sec_data,sec_rodata,sec_rodata_norel]) then
  314. begin
  315. sectionflags:=true;
  316. sectionprogbits:=true;
  317. end;
  318. s:=sectionname(atype,aname,aorder);
  319. writer.AsmWrite(s);
  320. s:=sectionattrs(atype);
  321. if (s<>'') then
  322. writer.AsmWrite(',"'+s+'"');
  323. writer.AsmLn;
  324. LastSecType:=atype;
  325. end;
  326. procedure TZ80vasm.WriteInstruction(hp: taicpu);
  327. var
  328. i: Integer;
  329. begin
  330. if hp.opcode=A_JRJP then
  331. writer.AsmWrite(#9#9'jp')
  332. else
  333. writer.AsmWrite(#9#9+std_op2str[hp.opcode]);
  334. if (taicpu(hp).ops<>0) or (hp.condition<>C_None) then
  335. begin
  336. writer.AsmWrite(#9);
  337. if hp.condition<>C_None then
  338. begin
  339. writer.AsmWrite(uppercond2str[hp.condition]);
  340. if taicpu(hp).ops<>0 then
  341. writer.AsmWrite(',');
  342. end;
  343. for i:=0 to taicpu(hp).ops-1 do
  344. begin
  345. if i<>0 then
  346. writer.AsmWrite(',');
  347. if is_calljmp(hp.opcode) then
  348. WriteOper_jmp(taicpu(hp).oper[i]^,hp)
  349. else
  350. WriteOper(taicpu(hp).oper[i]^,hp.opcode,taicpu(hp).ops,(i=2));
  351. end;
  352. end;
  353. writer.AsmLn;
  354. end;
  355. procedure TZ80vasm.WriteOper(const o: toper; opcode: tasmop; ops: longint; dest: boolean);
  356. var
  357. need_plus: Boolean;
  358. begin
  359. case o.typ of
  360. top_reg :
  361. writer.AsmWrite(std_regname(o.reg));
  362. top_const :
  363. begin
  364. writer.AsmWrite(tostr(longint(o.val)));
  365. end;
  366. top_ref:
  367. begin
  368. if assigned(o.ref^.symbol) and (o.ref^.refaddr in [addr_lo8,addr_hi8,addr_full]) then
  369. begin
  370. {if SmartAsm then
  371. AddSymbol(o.ref^.symbol.name,false);}
  372. if (o.ref^.base<>NR_NO) or (o.ref^.index<>NR_NO) then
  373. internalerror(2020041102);
  374. // writer.AsmWrite('#');
  375. case o.ref^.refaddr of
  376. addr_lo8:
  377. writer.AsmWrite('<');
  378. addr_hi8:
  379. writer.AsmWrite('>');
  380. addr_full:
  381. {nothing};
  382. else
  383. ;
  384. end;
  385. if o.ref^.offset<>0 then
  386. writer.AsmWrite('('+ApplyAsmSymbolRestrictions(o.ref^.symbol.name)+'+'+tostr(o.ref^.offset)+')')
  387. else
  388. writer.AsmWrite(ApplyAsmSymbolRestrictions(o.ref^.symbol.name));
  389. end
  390. else if not assigned(o.ref^.symbol) and
  391. ((o.ref^.base<>NR_NO) or (o.ref^.index<>NR_NO)) and
  392. (o.ref^.offset<>0) then
  393. begin
  394. //writer.AsmWrite(tostr(o.ref^.offset));
  395. writer.AsmWrite('(');
  396. if o.ref^.base<>NR_NO then
  397. begin
  398. if o.ref^.index<>NR_NO then
  399. internalerror(2020040204);
  400. writer.AsmWrite(std_regname(o.ref^.base));
  401. end
  402. else if o.ref^.index<>NR_NO then
  403. begin
  404. if o.ref^.scalefactor>1 then
  405. internalerror(2020040207);
  406. writer.AsmWrite(std_regname(o.ref^.index));
  407. end;
  408. if o.ref^.offset > 0 then
  409. writer.AsmWrite('+'+tostr(o.ref^.offset))
  410. else
  411. if o.ref^.offset < 0 then
  412. writer.AsmWrite(tostr(o.ref^.offset));
  413. writer.AsmWrite(')');
  414. end
  415. else
  416. begin
  417. writer.AsmWrite('(');
  418. need_plus:=false;
  419. if o.ref^.base<>NR_NO then
  420. begin
  421. if o.ref^.index<>NR_NO then
  422. internalerror(2020040205);
  423. writer.AsmWrite(std_regname(o.ref^.base));
  424. need_plus:=true;
  425. end
  426. else if o.ref^.index<>NR_NO then
  427. begin
  428. if o.ref^.scalefactor>1 then
  429. internalerror(2020040208);
  430. writer.AsmWrite(std_regname(o.ref^.index));
  431. need_plus:=true;
  432. end;
  433. if assigned(o.ref^.symbol) then
  434. begin
  435. {if SmartAsm then
  436. AddSymbol(o.ref^.symbol.name,false);}
  437. if need_plus then
  438. writer.AsmWrite('+');
  439. writer.AsmWrite(ApplyAsmSymbolRestrictions(o.ref^.symbol.name));
  440. need_plus:=true;
  441. end;
  442. if o.ref^.offset<>0 then
  443. begin
  444. if need_plus and (o.ref^.offset>0) then
  445. writer.AsmWrite('+');
  446. writer.AsmWrite(tostr(o.ref^.offset));
  447. need_plus:=true;
  448. end;
  449. if not need_plus then
  450. writer.AsmWrite('0');
  451. writer.AsmWrite(')');
  452. end;
  453. end;
  454. else
  455. internalerror(2020100805);
  456. end;
  457. end;
  458. procedure TZ80vasm.WriteOper_jmp(const o: toper; ai: taicpu);
  459. begin
  460. case o.typ of
  461. top_reg :
  462. writer.AsmWrite(std_regname(o.reg));
  463. top_const :
  464. begin
  465. writer.AsmWrite(tostr(longint(o.val)));
  466. end;
  467. top_ref:
  468. begin
  469. if o.ref^.refaddr=addr_no then
  470. begin
  471. writer.AsmWrite('TODO:indirect jump ref');
  472. //WriteReference(o.ref^);
  473. end
  474. else
  475. begin
  476. writer.AsmWrite(ApplyAsmSymbolRestrictions(o.ref^.symbol.name));
  477. //if SmartAsm then
  478. // AddSymbol(o.ref^.symbol.name,false);
  479. if o.ref^.offset>0 then
  480. writer.AsmWrite('+'+tostr(o.ref^.offset))
  481. else
  482. if o.ref^.offset<0 then
  483. writer.AsmWrite(tostr(o.ref^.offset));
  484. end;
  485. end;
  486. else
  487. internalerror(2020100806);
  488. end;
  489. end;
  490. procedure TZ80vasm.WriteExternals;
  491. var
  492. sym : TAsmSymbol;
  493. i : longint;
  494. begin
  495. writer.AsmWriteln('; Begin externals');
  496. for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
  497. begin
  498. sym:=TAsmSymbol(current_asmdata.AsmSymbolDict[i]);
  499. if sym.bind in [AB_EXTERNAL,AB_EXTERNAL_INDIRECT] then
  500. writer.AsmWriteln(#9'.globl'#9+ApplyAsmSymbolRestrictions(sym.name));
  501. end;
  502. writer.AsmWriteln('; End externals');
  503. end;
  504. procedure TZ80vasm.WriteTree(p: TAsmList);
  505. procedure doalign(alignment: byte; use_op: boolean; fillop: byte; maxbytes: byte; out last_align: longint;lasthp:tai);
  506. var
  507. i: longint;
  508. alignment64 : int64;
  509. begin
  510. last_align:=alignment;
  511. if alignment>1 then
  512. writer.AsmWriteLn(#9'.balign '+tostr(alignment));
  513. end;
  514. var
  515. lasthp,
  516. hp: tai;
  517. s, LastSecName: string;
  518. counter,lines,i,j,l,tokens,pos,last_align: longint;
  519. quoted, do_line: Boolean;
  520. consttype: taiconst_type;
  521. ch: Char;
  522. InlineLevel : longint;
  523. prevfileinfo : tfileposinfo;
  524. previnfile : tinputfile;
  525. LastAlign: Integer;
  526. LastSecOrder: TAsmSectionOrder;
  527. begin
  528. if not assigned(p) then
  529. exit;
  530. InlineLevel:=0;
  531. last_align:=1;
  532. lasthp:=nil;
  533. { lineinfo is only needed for al_procedures (PFV) }
  534. do_line:=(cs_asm_source in current_settings.globalswitches) or
  535. ((cs_lineinfo in current_settings.moduleswitches)
  536. and (p=current_asmdata.asmlists[al_procedures]));
  537. hp:=tai(p.first);
  538. while assigned(hp) do
  539. begin
  540. prefetch(pointer(hp.next)^);
  541. if not(hp.typ in SkipLineInfo) then
  542. begin
  543. previnfile:=lastinfile;
  544. prevfileinfo:=lastfileinfo;
  545. current_filepos:=tailineinfo(hp).fileinfo;
  546. { no line info for inlined code }
  547. if do_line and (inlinelevel=0) then
  548. WriteSourceLine(hp as tailineinfo);
  549. (*if (lastfileinfo.line<>prevfileinfo.line) or
  550. (previnfile<>lastinfile) then
  551. begin
  552. { +0 postfix means no line increment per assembler instruction }
  553. writer.AsmWrite('%LINE '+tostr(current_filepos.line)+'+0');
  554. if assigned(lastinfile) and ((previnfile<>lastinfile) or NewObject) then
  555. writer.AsmWriteLn(' '+lastinfile.name)
  556. else
  557. writer.AsmLn;
  558. NewObject:=false;
  559. end;*)
  560. end;
  561. case hp.typ of
  562. ait_section :
  563. begin
  564. ResetSourceLines;
  565. if tai_section(hp).sectype<>sec_none then
  566. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder,
  567. tai_section(hp).secalign,tai_section(hp).secflags,tai_section(hp).secprogbits)
  568. else
  569. begin
  570. {$ifdef EXTDEBUG}
  571. writer.AsmWrite(asminfo^.comment);
  572. writer.AsmWriteln(' sec_none');
  573. {$endif EXTDEBUG}
  574. end;
  575. end;
  576. ait_align :
  577. begin
  578. doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,tai_align_abstract(hp).maxbytes,last_align,lasthp);
  579. end;
  580. ait_label :
  581. begin
  582. if tai_label(hp).labsym.is_used then
  583. begin
  584. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_label(hp).labsym.name));
  585. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  586. writer.AsmWriteLn(':')
  587. else
  588. writer.AsmWriteLn(':');
  589. end;
  590. end;
  591. ait_symbol :
  592. begin
  593. if not(tai_symbol(hp).has_value) then
  594. begin
  595. if tai_symbol(hp).is_global then
  596. writer.AsmWriteLn(#9'.globl '+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name));
  597. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name) + ':');
  598. end
  599. else
  600. begin
  601. if tai_symbol(hp).is_global then
  602. writer.AsmWriteLn(#9'.globl '+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name));
  603. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name) + '=' + tostr(tai_symbol(hp).value));
  604. end;
  605. end;
  606. ait_symbol_end :
  607. begin
  608. end;
  609. ait_datablock :
  610. begin
  611. if tai_datablock(hp).is_global or SmartAsm then
  612. writer.AsmWriteLn(#9'.globl '+ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  613. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name) + ':');
  614. {if SmartAsm then
  615. AddSymbol(tai_datablock(hp).sym.name,true);}
  616. writer.AsmWriteLn(#9'.zero'#9+tostr(tai_datablock(hp).size));
  617. end;
  618. ait_realconst:
  619. WriteRealConstAsBytes(tai_realconst(hp),#9'.byte'#9,do_line);
  620. ait_const:
  621. begin
  622. consttype:=tai_const(hp).consttype;
  623. case consttype of
  624. aitconst_uleb128bit:
  625. writer.AsmWriteLn(ait_const2str[aitconst_8bit]+uleb128tostr(qword(tai_const(hp).value)));
  626. aitconst_sleb128bit:
  627. writer.AsmWriteLn(ait_const2str[aitconst_8bit]+sleb128tostr(tai_const(hp).value));
  628. aitconst_64bit,
  629. aitconst_64bit_unaligned,
  630. aitconst_32bit,
  631. aitconst_32bit_unaligned:
  632. begin
  633. writer.AsmWrite(#9'.uahalf'#9);
  634. l:=0;
  635. tokens:=1;
  636. repeat
  637. if assigned(tai_const(hp).sym) then
  638. begin
  639. if assigned(tai_const(hp).endsym) then
  640. s:=ApplyAsmSymbolRestrictions(tai_const(hp).endsym.name)+'-'+ApplyAsmSymbolRestrictions(tai_const(hp).sym.name)
  641. else
  642. s:=ApplyAsmSymbolRestrictions(tai_const(hp).sym.name);
  643. if tai_const(hp).value<>0 then
  644. s:=s+tostr_with_plus(tai_const(hp).value);
  645. if consttype in [aitconst_64bit,aitconst_64bit_unaligned] then
  646. s:=s+',0,0,0'
  647. else
  648. s:=s+',0';
  649. end
  650. else
  651. if consttype in [aitconst_64bit,aitconst_64bit_unaligned] then
  652. s:=tostr(Word(tai_const(hp).value)) +','+tostr(Word(tai_const(hp).value shr 16))+','+
  653. tostr(Word(tai_const(hp).value shr 32))+','+tostr(Word(tai_const(hp).value shr 48))
  654. else
  655. s:=tostr(Word(tai_const(hp).value))+','+tostr(Word(tai_const(hp).value shr 16));
  656. writer.AsmWrite(s);
  657. inc(l,length(s));
  658. inc(tokens);
  659. if (l>line_length) or
  660. (tokens>max_tokens) or
  661. (hp.next=nil) or
  662. (tai(hp.next).typ<>ait_const) or
  663. (tai_const(hp.next).consttype<>consttype) then
  664. break;
  665. hp:=tai(hp.next);
  666. writer.AsmWrite(',');
  667. until false;
  668. { Substract section start for secrel32 type }
  669. {if consttype=aitconst_secrel32_symbol then
  670. writer.AsmWrite(' - $$');}
  671. writer.AsmLn;
  672. end;
  673. {aitconst_128bit,}
  674. aitconst_16bit,
  675. aitconst_8bit,
  676. aitconst_16bit_unaligned{,
  677. aitconst_rva_symbol,
  678. aitconst_secrel32_symbol} :
  679. begin
  680. writer.AsmWrite(ait_const2str[consttype]);
  681. l:=0;
  682. tokens:=1;
  683. repeat
  684. if assigned(tai_const(hp).sym) then
  685. begin
  686. if assigned(tai_const(hp).endsym) then
  687. s:=ApplyAsmSymbolRestrictions(tai_const(hp).endsym.name)+'-'+ApplyAsmSymbolRestrictions(tai_const(hp).sym.name)
  688. else
  689. s:=ApplyAsmSymbolRestrictions(tai_const(hp).sym.name);
  690. if tai_const(hp).value<>0 then
  691. s:=s+tostr_with_plus(tai_const(hp).value);
  692. end
  693. else
  694. s:=tostr(tai_const(hp).value);
  695. writer.AsmWrite(s);
  696. inc(l,length(s));
  697. inc(tokens);
  698. if (l>line_length) or
  699. (tokens>max_tokens) or
  700. (hp.next=nil) or
  701. (tai(hp.next).typ<>ait_const) or
  702. (tai_const(hp.next).consttype<>consttype) then
  703. break;
  704. hp:=tai(hp.next);
  705. writer.AsmWrite(',');
  706. until false;
  707. { Substract section start for secrel32 type }
  708. if consttype=aitconst_secrel32_symbol then
  709. writer.AsmWrite(' - $$');
  710. writer.AsmLn;
  711. end;
  712. else
  713. begin
  714. writer.AsmWrite(asminfo^.comment);
  715. writer.AsmWrite('WARNING: not yet implemented in assembler output: ');
  716. Str(consttype,s);
  717. writer.AsmWriteLn(s);
  718. end;
  719. end;
  720. end;
  721. ait_string :
  722. begin
  723. pos:=0;
  724. for i:=1 to tai_string(hp).len do
  725. begin
  726. if pos=0 then
  727. begin
  728. writer.AsmWrite(#9'.ascii'#9'"');
  729. pos:=20;
  730. end;
  731. ch:=tai_string(hp).str[i-1];
  732. case ch of
  733. #0, {This can't be done by range, because a bug in FPC}
  734. #1..#31,
  735. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  736. '"' : s:='\"';
  737. '\' : s:='\\';
  738. else
  739. s:=ch;
  740. end;
  741. writer.AsmWrite(s);
  742. inc(pos,length(s));
  743. if (pos>line_length) or (i=tai_string(hp).len) then
  744. begin
  745. writer.AsmWriteLn('"');
  746. pos:=0;
  747. end;
  748. end;
  749. end;
  750. ait_instruction :
  751. begin
  752. WriteInstruction(taicpu(hp));
  753. end;
  754. ait_directive :
  755. begin
  756. case tai_directive(hp).directive of
  757. asd_cpu :
  758. writer.AsmWriteLn('; CPU '+tai_directive(hp).name);
  759. else
  760. begin
  761. writer.AsmWrite(asminfo^.comment);
  762. writer.AsmWrite('WARNING: not yet implemented in assembler output: ait_directive.');
  763. Str(tai_directive(hp).directive,s);
  764. writer.AsmWriteLn(s);
  765. end;
  766. end;
  767. end;
  768. ait_cutobject :
  769. begin
  770. if SmartAsm then
  771. begin
  772. { only reset buffer if nothing has changed }
  773. if not writer.ClearIfEmpty then
  774. begin
  775. {if SmartAsm then
  776. begin
  777. WriteSmartExternals;
  778. FreeExternChainList;
  779. end;
  780. WriteGroups;}
  781. writer.AsmClose;
  782. DoAssemble;
  783. writer.AsmCreate(tai_cutobject(hp).place);
  784. {ResetSectionsList;
  785. WriteHeader;}
  786. end;
  787. { avoid empty files }
  788. LastSecType:=sec_none;
  789. LastSecName:='';
  790. LastSecOrder:=secorder_default;
  791. LastAlign:=1;
  792. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  793. begin
  794. if tai(hp.next).typ=ait_section then
  795. begin
  796. LastSecType:=tai_section(hp.next).sectype;
  797. LastSecName:=tai_section(hp.next).name^;
  798. LastSecOrder:=tai_section(hp.next).secorder;
  799. LastAlign:=tai_section(hp.next).secalign;
  800. end;
  801. hp:=tai(hp.next);
  802. end;
  803. if LastSecType<>sec_none then
  804. WriteSection(LastSecType,LastSecName,LastSecOrder,LastAlign);
  805. writer.MarkEmpty;
  806. //NewObject:=true;
  807. end;
  808. end;
  809. ait_marker :
  810. if tai_marker(hp).kind=mark_NoLineInfoStart then
  811. inc(InlineLevel)
  812. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  813. dec(InlineLevel);
  814. ait_stab,
  815. ait_force_line,
  816. ait_function_name : ;
  817. else
  818. if not WriteComments(hp) then
  819. begin
  820. writer.AsmWrite(asminfo^.comment);
  821. writer.AsmWrite('WARNING: not yet implemented in assembler output: ');
  822. Str(hp.typ,s);
  823. writer.AsmWriteLn(s);
  824. end;
  825. end;
  826. lasthp:=hp;
  827. hp:=tai(hp.next);
  828. end;
  829. end;
  830. procedure TZ80vasm.WriteAsmList;
  831. var
  832. hal: TAsmListType;
  833. begin
  834. WriteExternals;
  835. for hal:=low(TasmlistType) to high(TasmlistType) do
  836. begin
  837. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmListTypeStr[hal]);
  838. writetree(current_asmdata.asmlists[hal]);
  839. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmListTypeStr[hal]);
  840. end;
  841. end;
  842. function TZ80vasm.MakeCmdLine: TCmdStr;
  843. begin
  844. result := {'-mmcu='+lower(cputypestr[current_settings.cputype])+' '+}inherited MakeCmdLine;
  845. end;
  846. const
  847. as_z80_vasm_info : tasminfo =
  848. (
  849. id : as_z80_vasm;
  850. idtxt : 'VASM';
  851. asmbin : 'vasmz80_std';
  852. asmcmd : '-quiet -Fvobj -o $OBJ $EXTRAOPT $ASM';
  853. supported_targets : [system_z80_embedded, system_z80_zxspectrum, system_z80_msxdos];
  854. flags : [af_needar,af_smartlink_sections];
  855. labelprefix : '.L';
  856. labelmaxlen : -1;
  857. comment : '; ';
  858. dollarsign: '$';
  859. );
  860. begin
  861. RegisterAssembler(as_z80_vasm_info,TZ80vasm);
  862. end.