agz80asm.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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 z80asm assembler:
  18. http://savannah.nongnu.org/projects/z80asm
  19. }
  20. unit agz80asm;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,systems,
  25. aasmtai,aasmdata,
  26. assemble,
  27. cpubase;
  28. type
  29. TZ80AsmAssembler=class(TExternalAssembler)
  30. procedure WriteTree(p : TAsmList); override;
  31. procedure WriteAsmList;override;
  32. function MakeCmdLine: TCmdStr; override;
  33. end;
  34. implementation
  35. uses
  36. cutils,globals,verbose,
  37. aasmbase,aasmcpu,
  38. cpuinfo,
  39. cgbase,cgutils;
  40. const
  41. line_length = 70;
  42. procedure TZ80AsmAssembler.WriteTree(p: TAsmList);
  43. function getreferencestring(var ref : treference) : string;
  44. var
  45. s : string;
  46. begin
  47. s:='';
  48. with ref do
  49. begin
  50. {$ifdef extdebug}
  51. // if base=NR_NO then
  52. // internalerror(200308292);
  53. // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
  54. // internalerror(200308293);
  55. {$endif extdebug}
  56. if index<>NR_NO then
  57. internalerror(2011021701)
  58. else if base<>NR_NO then
  59. begin
  60. // if addressmode=AM_PREDRECEMENT then
  61. // s:='-';
  62. //case base of
  63. // NR_R26:
  64. // s:=s+'X';
  65. // NR_R28:
  66. // s:=s+'Y';
  67. // NR_R30:
  68. // s:=s+'Z';
  69. // else
  70. // s:=gas_regname(base);
  71. //end;
  72. //if addressmode=AM_POSTINCREMENT then
  73. // s:=s+'+';
  74. //
  75. //if offset>0 then
  76. // s:=s+'+'+tostr(offset)
  77. //else if offset<0 then
  78. // s:=s+tostr(offset)
  79. end
  80. else if assigned(symbol) or (offset<>0) then
  81. begin
  82. //if assigned(symbol) then
  83. // s:=ReplaceForbiddenAsmSymbolChars(symbol.name);
  84. //
  85. //if offset<0 then
  86. // s:=s+tostr(offset)
  87. //else if offset>0 then
  88. // s:=s+'+'+tostr(offset);
  89. //case refaddr of
  90. // addr_hi8:
  91. // s:='hi8('+s+')';
  92. // addr_hi8_gs:
  93. // s:='hi8(gs('+s+'))';
  94. // addr_lo8:
  95. // s:='lo8('+s+')';
  96. // addr_lo8_gs:
  97. // s:='lo8(gs('+s+'))';
  98. // else
  99. // s:='('+s+')';
  100. //end;
  101. end;
  102. end;
  103. getreferencestring:=s;
  104. end;
  105. function getopstr(const o:toper) : string;
  106. var
  107. hs : string;
  108. first : boolean;
  109. r : tsuperregister;
  110. begin
  111. //case o.typ of
  112. // top_reg:
  113. // getopstr:=gas_regname(o.reg);
  114. // top_const:
  115. // getopstr:=tostr(longint(o.val));
  116. // top_ref:
  117. // if o.ref^.refaddr=addr_full then
  118. // begin
  119. // hs:=ReplaceForbiddenAsmSymbolChars(o.ref^.symbol.name);
  120. // if o.ref^.offset>0 then
  121. // hs:=hs+'+'+tostr(o.ref^.offset)
  122. // else
  123. // if o.ref^.offset<0 then
  124. // hs:=hs+tostr(o.ref^.offset);
  125. // getopstr:=hs;
  126. // end
  127. // else
  128. // getopstr:=getreferencestring(o.ref^);
  129. // else
  130. // internalerror(2002070604);
  131. //end;
  132. end;
  133. //var op: TAsmOp;
  134. // s: string;
  135. // i: byte;
  136. // sep: string[3];
  137. var
  138. hp: tai;
  139. s: string;
  140. counter,lines,i,j: longint;
  141. quoted: Boolean;
  142. begin
  143. if not assigned(p) then
  144. exit;
  145. hp:=tai(p.first);
  146. while assigned(hp) do
  147. begin
  148. prefetch(pointer(hp.next)^);
  149. case hp.typ of
  150. ait_comment :
  151. begin
  152. writer.AsmWrite(asminfo^.comment);
  153. writer.AsmWritePChar(tai_comment(hp).str);
  154. writer.AsmLn;
  155. end;
  156. ait_label :
  157. begin
  158. if tai_label(hp).labsym.is_used then
  159. begin
  160. writer.AsmWrite(tai_label(hp).labsym.name);
  161. writer.AsmWriteLn(':');
  162. end;
  163. end;
  164. ait_string :
  165. begin
  166. counter := 0;
  167. lines := tai_string(hp).len div line_length;
  168. { separate lines in different parts }
  169. if tai_string(hp).len > 0 then
  170. Begin
  171. for j := 0 to lines-1 do
  172. begin
  173. writer.AsmWrite(#9#9'DB'#9);
  174. quoted:=false;
  175. for i:=counter to counter+line_length-1 do
  176. begin
  177. { it is an ascii character. }
  178. if (ord(tai_string(hp).str[i])>31) and
  179. (ord(tai_string(hp).str[i])<127) and
  180. (tai_string(hp).str[i]<>'"') then
  181. begin
  182. if not(quoted) then
  183. begin
  184. if i>counter then
  185. writer.AsmWrite(',');
  186. writer.AsmWrite('"');
  187. end;
  188. writer.AsmWrite(tai_string(hp).str[i]);
  189. quoted:=true;
  190. end { if > 31 and < 127 and ord('"') }
  191. else
  192. begin
  193. if quoted then
  194. writer.AsmWrite('"');
  195. if i>counter then
  196. writer.AsmWrite(',');
  197. quoted:=false;
  198. writer.AsmWrite(tostr(ord(tai_string(hp).str[i])));
  199. end;
  200. end; { end for i:=0 to... }
  201. if quoted then writer.AsmWrite('"');
  202. writer.AsmWrite(target_info.newline);
  203. counter := counter+line_length;
  204. end; { end for j:=0 ... }
  205. { do last line of lines }
  206. if counter<tai_string(hp).len then
  207. writer.AsmWrite(#9#9'DB'#9);
  208. quoted:=false;
  209. for i:=counter to tai_string(hp).len-1 do
  210. begin
  211. { it is an ascii character. }
  212. if (ord(tai_string(hp).str[i])>31) and
  213. (ord(tai_string(hp).str[i])<128) and
  214. (tai_string(hp).str[i]<>'"') then
  215. begin
  216. if not(quoted) then
  217. begin
  218. if i>counter then
  219. writer.AsmWrite(',');
  220. writer.AsmWrite('"');
  221. end;
  222. writer.AsmWrite(tai_string(hp).str[i]);
  223. quoted:=true;
  224. end { if > 31 and < 128 and " }
  225. else
  226. begin
  227. if quoted then
  228. writer.AsmWrite('"');
  229. if i>counter then
  230. writer.AsmWrite(',');
  231. quoted:=false;
  232. writer.AsmWrite(tostr(ord(tai_string(hp).str[i])));
  233. end;
  234. end; { end for i:=0 to... }
  235. if quoted then
  236. writer.AsmWrite('"');
  237. end;
  238. writer.AsmLn;
  239. end;
  240. else
  241. begin
  242. writer.AsmWrite(asminfo^.comment);
  243. writer.AsmWrite('WARNING: not yet implemented in assembler output: ');
  244. Str(hp.typ,s);
  245. writer.AsmWriteLn(s);
  246. end;
  247. end;
  248. hp:=tai(hp.next);
  249. end;
  250. //op:=taicpu(hp).opcode;
  251. //s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition];
  252. //if taicpu(hp).ops<>0 then
  253. // begin
  254. // sep:=#9;
  255. // for i:=0 to taicpu(hp).ops-1 do
  256. // begin
  257. // s:=s+sep+getopstr(taicpu(hp).oper[i]^);
  258. // sep:=',';
  259. // end;
  260. // end;
  261. //owner.writer.AsmWriteLn(s);
  262. end;
  263. procedure TZ80AsmAssembler.WriteAsmList;
  264. var
  265. hal: TAsmListType;
  266. begin
  267. for hal:=low(TasmlistType) to high(TasmlistType) do
  268. begin
  269. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmListTypeStr[hal]);
  270. writetree(current_asmdata.asmlists[hal]);
  271. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmListTypeStr[hal]);
  272. end;
  273. end;
  274. function TZ80AsmAssembler.MakeCmdLine: TCmdStr;
  275. begin
  276. result := {'-mmcu='+lower(cputypestr[current_settings.cputype])+' '+}inherited MakeCmdLine;
  277. end;
  278. const
  279. as_Z80_asm_info : tasminfo =
  280. (
  281. id : as_z80asm;
  282. idtxt : 'Z80Asm';
  283. asmbin : 'z80asm';
  284. asmcmd : '-o $OBJ $EXTRAOPT $ASM';
  285. supported_targets : [system_Z80_embedded];
  286. flags : [af_needar,af_smartlink_sections];
  287. labelprefix : '.L';
  288. comment : '; ';
  289. dollarsign: 's';
  290. );
  291. begin
  292. RegisterAssembler(as_Z80_asm_info,TZ80AsmAssembler);
  293. end.