t_zxspectrum.pas 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. {
  2. Copyright (c) 2005-2020 by Free Pascal Compiler team
  3. This unit implements support import, export, link routines
  4. for the ZX Spectrum Target
  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 t_zxspectrum;
  19. {$i fpcdefs.inc}
  20. interface
  21. implementation
  22. uses
  23. SysUtils,
  24. cutils,cfileutl,cclasses,
  25. globtype,globals,systems,verbose,comphook,cscript,fmodule,i_zxspectrum,link,
  26. cpuinfo;
  27. type
  28. { sdld - the sdld linker from the SDCC project ( http://sdcc.sourceforge.net/ ) }
  29. { vlink - the vlink linker by Frank Wille (http://sun.hasenbraten.de/vlink/ ) }
  30. TLinkerZXSpectrum=class(texternallinker)
  31. private
  32. FOrigin: Word;
  33. Function WriteResponseFile_Sdld: Boolean;
  34. Function WriteResponseFile_Vlink: Boolean;
  35. procedure SetDefaultInfo_Sdld;
  36. procedure SetDefaultInfo_Vlink;
  37. function MakeExecutable_Sdld: boolean;
  38. function MakeExecutable_Vlink: boolean;
  39. public
  40. procedure SetDefaultInfo; override;
  41. function MakeExecutable: boolean; override;
  42. procedure InitSysInitUnitName; override;
  43. function postprocessexecutable(const fn : string;isdll:boolean): boolean;
  44. end;
  45. {*****************************************************************************
  46. TLinkerZXSpectrum
  47. *****************************************************************************}
  48. function TLinkerZXSpectrum.WriteResponseFile_Sdld: Boolean;
  49. Var
  50. linkres : TLinkRes;
  51. s : TCmdStr;
  52. prtobj: string[80];
  53. begin
  54. result:=False;
  55. prtobj:='prt0';
  56. { Open link.res file }
  57. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  58. { Write the origin (i.e. the program load address) }
  59. LinkRes.Add('-b _CODE='+tostr(FOrigin));
  60. if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then
  61. begin
  62. s:=FindObjectFile(prtobj,'',false);
  63. LinkRes.AddFileName(s);
  64. end;
  65. while not ObjectFiles.Empty do
  66. begin
  67. s:=ObjectFiles.GetFirst;
  68. if s<>'' then
  69. begin
  70. if not(cs_link_on_target in current_settings.globalswitches) then
  71. s:=FindObjectFile(s,'',false);
  72. LinkRes.AddFileName((maybequoted(s)));
  73. end;
  74. end;
  75. { Write staticlibraries }
  76. if not StaticLibFiles.Empty then
  77. begin
  78. while not StaticLibFiles.Empty do
  79. begin
  80. S:=StaticLibFiles.GetFirst;
  81. LinkRes.Add('-l'+maybequoted(s));
  82. end;
  83. end;
  84. { Write and Close response }
  85. linkres.writetodisk;
  86. linkres.free;
  87. result:=True;
  88. end;
  89. function TLinkerZXSpectrum.WriteResponseFile_Vlink: Boolean;
  90. Var
  91. linkres : TLinkRes;
  92. s : TCmdStr;
  93. prtobj: string[80];
  94. begin
  95. result:=false;
  96. prtobj:='prt0';
  97. { Open link.res file }
  98. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  99. LinkRes.Add('INPUT (');
  100. if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then
  101. begin
  102. s:=FindObjectFile(prtobj,'',false);
  103. LinkRes.AddFileName(maybequoted(s));
  104. end;
  105. while not ObjectFiles.Empty do
  106. begin
  107. s:=ObjectFiles.GetFirst;
  108. if s<>'' then
  109. begin
  110. s:=FindObjectFile(s,'',false);
  111. LinkRes.AddFileName(maybequoted(s));
  112. end;
  113. end;
  114. while not StaticLibFiles.Empty do
  115. begin
  116. S:=StaticLibFiles.GetFirst;
  117. LinkRes.AddFileName(maybequoted(s));
  118. end;
  119. LinkRes.Add(')');
  120. with LinkRes do
  121. begin
  122. Add('');
  123. Add('SECTIONS');
  124. Add('{');
  125. Add(' . = 0x'+hexstr(FOrigin,4)+';');
  126. Add(' .text : { *(.text .text.* ) }');
  127. Add(' .data : { *(.data .data.* .rodata .rodata.* .bss .bss.* .fpc.* .stack .stack.* ) }');
  128. Add('}');
  129. end;
  130. { Write and Close response }
  131. linkres.writetodisk;
  132. linkres.free;
  133. result:=true;
  134. end;
  135. procedure TLinkerZXSpectrum.SetDefaultInfo_Sdld;
  136. const
  137. ExeName='sdldz80';
  138. begin
  139. FOrigin:={32768}23800;
  140. with Info do
  141. begin
  142. ExeCmd[1]:=ExeName+' -n $OPT -i $MAP $EXE -f $RES'
  143. end;
  144. end;
  145. procedure TLinkerZXSpectrum.SetDefaultInfo_Vlink;
  146. const
  147. ExeName='vlink';
  148. begin
  149. FOrigin:={32768}23800;
  150. with Info do
  151. begin
  152. ExeCmd[1]:=ExeName+' -bihex $GCSECTIONS -e $STARTSYMBOL $STRIP $OPT -o $EXE -T $RES'
  153. end;
  154. end;
  155. procedure TLinkerZXSpectrum.SetDefaultInfo;
  156. begin
  157. if not (cs_link_vlink in current_settings.globalswitches) then
  158. SetDefaultInfo_Sdld
  159. else
  160. SetDefaultInfo_Vlink;
  161. end;
  162. function TLinkerZXSpectrum.MakeExecutable_Sdld: boolean;
  163. var
  164. binstr,
  165. cmdstr,
  166. mapstr: TCmdStr;
  167. success : boolean;
  168. StaticStr,
  169. //GCSectionsStr,
  170. DynLinkStr,
  171. StripStr,
  172. FixedExeFileName: string;
  173. begin
  174. { for future use }
  175. StaticStr:='';
  176. StripStr:='';
  177. mapstr:='';
  178. DynLinkStr:='';
  179. FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));
  180. if (cs_link_map in current_settings.globalswitches) then
  181. mapstr:='-mw';
  182. { Write used files and libraries }
  183. WriteResponseFile_Sdld();
  184. { Call linker }
  185. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  186. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  187. Replace(cmdstr,'$EXE',FixedExeFileName);
  188. Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
  189. Replace(cmdstr,'$STATIC',StaticStr);
  190. Replace(cmdstr,'$STRIP',StripStr);
  191. Replace(cmdstr,'$MAP',mapstr);
  192. //Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  193. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  194. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  195. { Remove ReponseFile }
  196. if success and not(cs_link_nolink in current_settings.globalswitches) then
  197. DeleteFile(outputexedir+Info.ResName);
  198. { Post process }
  199. if success and not(cs_link_nolink in current_settings.globalswitches) then
  200. success:=PostProcessExecutable(FixedExeFileName,false);
  201. result:=success; { otherwise a recursive call to link method }
  202. end;
  203. function TLinkerZXSpectrum.MakeExecutable_Vlink: boolean;
  204. var
  205. binstr,
  206. cmdstr: TCmdStr;
  207. success: boolean;
  208. GCSectionsStr,
  209. StripStr,
  210. StartSymbolStr,
  211. FixedExeFilename: string;
  212. begin
  213. GCSectionsStr:='-gc-all -mtype';
  214. StripStr:='';
  215. StartSymbolStr:='start';
  216. FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));
  217. { Write used files and libraries }
  218. WriteResponseFile_Vlink();
  219. { Call linker }
  220. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  221. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  222. Replace(cmdstr,'$EXE',FixedExeFileName);
  223. Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
  224. Replace(cmdstr,'$STRIP',StripStr);
  225. Replace(cmdstr,'$STARTSYMBOL',StartSymbolStr);
  226. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  227. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  228. { Remove ReponseFile }
  229. if success and not(cs_link_nolink in current_settings.globalswitches) then
  230. DeleteFile(outputexedir+Info.ResName);
  231. { Post process }
  232. if success and not(cs_link_nolink in current_settings.globalswitches) then
  233. success:=PostProcessExecutable(FixedExeFileName,false);
  234. result:=success;
  235. end;
  236. function TLinkerZXSpectrum.MakeExecutable: boolean;
  237. begin
  238. if not (cs_link_vlink in current_settings.globalswitches) then
  239. result:=MakeExecutable_Sdld
  240. else
  241. result:=MakeExecutable_Vlink;
  242. end;
  243. procedure TLinkerZXSpectrum.InitSysInitUnitName;
  244. begin
  245. sysinitunit:='si_prc';
  246. end;
  247. function TLinkerZXSpectrum.postprocessexecutable(const fn: string; isdll: boolean): boolean;
  248. begin
  249. result:=DoExec(FindUtil(utilsprefix+'ihx2tzx'),' '+fn,true,false);
  250. end;
  251. {*****************************************************************************
  252. Initialize
  253. *****************************************************************************}
  254. initialization
  255. {$ifdef z80}
  256. RegisterLinker(ld_zxspectrum,TLinkerZXSpectrum);
  257. RegisterTarget(system_z80_zxspectrum_info);
  258. {$endif z80}
  259. end.