2
0

t_zxspectrum.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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,ogrel,owar;
  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. { TInternalLinkerZXSpectrum }
  46. TInternalLinkerZXSpectrum=class(tinternallinker)
  47. protected
  48. procedure DefaultLinkScript;override;
  49. public
  50. constructor create;override;
  51. procedure InitSysInitUnitName;override;
  52. end;
  53. {*****************************************************************************
  54. TLinkerZXSpectrum
  55. *****************************************************************************}
  56. function TLinkerZXSpectrum.WriteResponseFile_Sdld: Boolean;
  57. Var
  58. linkres : TLinkRes;
  59. s : TCmdStr;
  60. prtobj: string[80];
  61. begin
  62. result:=False;
  63. prtobj:='prt0';
  64. { Open link.res file }
  65. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  66. { Write the origin (i.e. the program load address) }
  67. LinkRes.Add('-b _CODE='+tostr(FOrigin));
  68. if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then
  69. begin
  70. s:=FindObjectFile(prtobj,'',false);
  71. LinkRes.AddFileName(s);
  72. end;
  73. while not ObjectFiles.Empty do
  74. begin
  75. s:=ObjectFiles.GetFirst;
  76. if s<>'' then
  77. begin
  78. if not(cs_link_on_target in current_settings.globalswitches) then
  79. s:=FindObjectFile(s,'',false);
  80. LinkRes.AddFileName((maybequoted(s)));
  81. end;
  82. end;
  83. { Write staticlibraries }
  84. if not StaticLibFiles.Empty then
  85. begin
  86. while not StaticLibFiles.Empty do
  87. begin
  88. S:=StaticLibFiles.GetFirst;
  89. LinkRes.Add('-l'+maybequoted(s));
  90. end;
  91. end;
  92. { Write and Close response }
  93. linkres.writetodisk;
  94. linkres.free;
  95. result:=True;
  96. end;
  97. function TLinkerZXSpectrum.WriteResponseFile_Vlink: Boolean;
  98. Var
  99. linkres : TLinkRes;
  100. s : TCmdStr;
  101. prtobj: string[80];
  102. begin
  103. result:=false;
  104. prtobj:='prt0';
  105. { Open link.res file }
  106. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  107. LinkRes.Add('INPUT (');
  108. if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then
  109. begin
  110. s:=FindObjectFile(prtobj,'',false);
  111. LinkRes.AddFileName(maybequoted(s));
  112. end;
  113. while not ObjectFiles.Empty do
  114. begin
  115. s:=ObjectFiles.GetFirst;
  116. if s<>'' then
  117. begin
  118. s:=FindObjectFile(s,'',false);
  119. LinkRes.AddFileName(maybequoted(s));
  120. end;
  121. end;
  122. while not StaticLibFiles.Empty do
  123. begin
  124. S:=StaticLibFiles.GetFirst;
  125. LinkRes.AddFileName(maybequoted(s));
  126. end;
  127. LinkRes.Add(')');
  128. with LinkRes do
  129. begin
  130. Add('');
  131. Add('SECTIONS');
  132. Add('{');
  133. Add(' . = 0x'+hexstr(FOrigin,4)+';');
  134. Add(' .text : { *(.text .text.* ) }');
  135. Add(' .data : { *(.data .data.* .rodata .rodata.* .bss .bss.* .fpc.* .stack .stack.* ) }');
  136. Add('}');
  137. end;
  138. { Write and Close response }
  139. linkres.writetodisk;
  140. linkres.free;
  141. result:=true;
  142. end;
  143. procedure TLinkerZXSpectrum.SetDefaultInfo_Sdld;
  144. const
  145. ExeName='sdldz80';
  146. begin
  147. FOrigin:={32768}23800;
  148. with Info do
  149. begin
  150. ExeCmd[1]:=ExeName+' -n $OPT -i $MAP $EXE -f $RES'
  151. end;
  152. end;
  153. procedure TLinkerZXSpectrum.SetDefaultInfo_Vlink;
  154. const
  155. ExeName='vlink';
  156. begin
  157. FOrigin:={32768}23800;
  158. with Info do
  159. begin
  160. ExeCmd[1]:=ExeName+' -bihex $GCSECTIONS -e $STARTSYMBOL $STRIP $OPT -o $EXE -T $RES'
  161. end;
  162. end;
  163. procedure TLinkerZXSpectrum.SetDefaultInfo;
  164. begin
  165. if not (cs_link_vlink in current_settings.globalswitches) then
  166. SetDefaultInfo_Sdld
  167. else
  168. SetDefaultInfo_Vlink;
  169. end;
  170. function TLinkerZXSpectrum.MakeExecutable_Sdld: boolean;
  171. var
  172. binstr,
  173. cmdstr,
  174. mapstr: TCmdStr;
  175. success : boolean;
  176. StaticStr,
  177. //GCSectionsStr,
  178. DynLinkStr,
  179. StripStr,
  180. FixedExeFileName: string;
  181. begin
  182. { for future use }
  183. StaticStr:='';
  184. StripStr:='';
  185. mapstr:='';
  186. DynLinkStr:='';
  187. FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));
  188. if (cs_link_map in current_settings.globalswitches) then
  189. mapstr:='-mw';
  190. { Write used files and libraries }
  191. WriteResponseFile_Sdld();
  192. { Call linker }
  193. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  194. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  195. Replace(cmdstr,'$EXE',FixedExeFileName);
  196. Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
  197. Replace(cmdstr,'$STATIC',StaticStr);
  198. Replace(cmdstr,'$STRIP',StripStr);
  199. Replace(cmdstr,'$MAP',mapstr);
  200. //Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  201. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  202. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  203. { Remove ReponseFile }
  204. if success and not(cs_link_nolink in current_settings.globalswitches) then
  205. DeleteFile(outputexedir+Info.ResName);
  206. { Post process }
  207. if success and not(cs_link_nolink in current_settings.globalswitches) then
  208. success:=PostProcessExecutable(FixedExeFileName,false);
  209. result:=success; { otherwise a recursive call to link method }
  210. end;
  211. function TLinkerZXSpectrum.MakeExecutable_Vlink: boolean;
  212. var
  213. binstr,
  214. cmdstr: TCmdStr;
  215. success: boolean;
  216. GCSectionsStr,
  217. StripStr,
  218. StartSymbolStr,
  219. FixedExeFilename: string;
  220. begin
  221. GCSectionsStr:='-gc-all -mtype';
  222. StripStr:='';
  223. StartSymbolStr:='start';
  224. FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));
  225. { Write used files and libraries }
  226. WriteResponseFile_Vlink();
  227. { Call linker }
  228. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  229. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  230. Replace(cmdstr,'$EXE',FixedExeFileName);
  231. Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
  232. Replace(cmdstr,'$STRIP',StripStr);
  233. Replace(cmdstr,'$STARTSYMBOL',StartSymbolStr);
  234. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  235. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  236. { Remove ReponseFile }
  237. if success and not(cs_link_nolink in current_settings.globalswitches) then
  238. DeleteFile(outputexedir+Info.ResName);
  239. { Post process }
  240. if success and not(cs_link_nolink in current_settings.globalswitches) then
  241. success:=PostProcessExecutable(FixedExeFileName,false);
  242. result:=success;
  243. end;
  244. function TLinkerZXSpectrum.MakeExecutable: boolean;
  245. begin
  246. if not (cs_link_vlink in current_settings.globalswitches) then
  247. result:=MakeExecutable_Sdld
  248. else
  249. result:=MakeExecutable_Vlink;
  250. end;
  251. procedure TLinkerZXSpectrum.InitSysInitUnitName;
  252. begin
  253. sysinitunit:='si_prc';
  254. end;
  255. function TLinkerZXSpectrum.postprocessexecutable(const fn: string; isdll: boolean): boolean;
  256. begin
  257. result:=DoExec(FindUtil(utilsprefix+'ihx2tzx'),' '+fn,true,false);
  258. end;
  259. {*****************************************************************************
  260. TInternalLinkerZXSpectrum
  261. *****************************************************************************}
  262. procedure TInternalLinkerZXSpectrum.DefaultLinkScript;
  263. begin
  264. end;
  265. constructor TInternalLinkerZXSpectrum.create;
  266. begin
  267. inherited create;
  268. CArObjectReader:=TArObjectReader;
  269. CExeOutput:=TIntelHexExeOutput;
  270. CObjInput:=TRelObjInput;
  271. end;
  272. procedure TInternalLinkerZXSpectrum.InitSysInitUnitName;
  273. begin
  274. sysinitunit:='si_prc';
  275. end;
  276. {*****************************************************************************
  277. Initialize
  278. *****************************************************************************}
  279. initialization
  280. {$ifdef z80}
  281. RegisterLinker(ld_int_zxspectrum,TInternalLinkerZXSpectrum);
  282. RegisterLinker(ld_zxspectrum,TLinkerZXSpectrum);
  283. RegisterTarget(system_z80_zxspectrum_info);
  284. {$endif z80}
  285. end.