summaryrefslogtreecommitdiff
path: root/avx512-0037785/compiler/systems/t_sinclairql.pas
diff options
context:
space:
mode:
Diffstat (limited to 'avx512-0037785/compiler/systems/t_sinclairql.pas')
-rw-r--r--avx512-0037785/compiler/systems/t_sinclairql.pas402
1 files changed, 402 insertions, 0 deletions
diff --git a/avx512-0037785/compiler/systems/t_sinclairql.pas b/avx512-0037785/compiler/systems/t_sinclairql.pas
new file mode 100644
index 0000000000..42da38a77b
--- /dev/null
+++ b/avx512-0037785/compiler/systems/t_sinclairql.pas
@@ -0,0 +1,402 @@
+{
+ Copyright (c) 2020 by Free Pascal Development Team
+
+ This unit implements support import, export, link routines
+ for the m68k Sinclair QL target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_sinclairql;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ rescmn, comprsrc, link;
+
+type
+ PLinkerSinclairQL = ^TLinkerSinclairQL;
+ TLinkerSinclairQL = class(texternallinker)
+ private
+ Origin: DWord;
+ UseVLink: boolean;
+ function WriteResponseFile(isdll: boolean): boolean;
+ procedure SetSinclairQLInfo;
+ function MakeSinclairQLExe: boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ procedure InitSysInitUnitName; override;
+ function MakeExecutable: boolean; override;
+ end;
+
+
+implementation
+
+ uses
+ sysutils,cutils,cfileutl,cclasses,aasmbase,
+ globtype,globals,systems,verbose,cscript,fmodule,i_sinclairql;
+
+ type
+ TQLHeader = packed record
+ hdr_id: array[0..17] of char;
+ hdr_reserved: byte;
+ hdr_length: byte;
+ hdr_access: byte;
+ hdr_type: byte;
+ hdr_data: dword;
+ hdr_extra: dword;
+ end;
+
+ TXTccData = packed record
+ xtcc_id: array[0..3] of char;
+ xtcc_data: dword;
+ end;
+
+ const
+ DefaultQLHeader: TQLHeader = (
+ hdr_id: ']!QDOS File Header';
+ hdr_reserved: 0;
+ hdr_length: $f;
+ hdr_access: 0;
+ hdr_type: 1;
+ hdr_data: 0;
+ hdr_extra: 0;
+ );
+
+ DefaultXTccData: TXTCCData = (
+ xtcc_id: 'XTcc';
+ xtcc_data: 0;
+ );
+
+ const
+ DefaultOrigin = $0;
+ ProgramHeaderName = 'main';
+
+
+constructor TLinkerSinclairQL.Create;
+begin
+ UseVLink:=(cs_link_vlink in current_settings.globalswitches);
+
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerSinclairQL.SetSinclairQLInfo;
+begin
+ if ImageBaseSetExplicity then
+ Origin:=ImageBase
+ else
+ Origin:=DefaultOrigin;
+
+ with Info do
+ begin
+ if not UseVLink then
+ begin
+ ExeCmd[1]:='ld $DYNLINK $OPT -d -n -o $EXE $RES';
+ end
+ else
+ begin
+ ExeCmd[1]:='vlink -b rawseg -q $FLAGS $GCSECTIONS $OPT $STRIP $MAP -o $EXE -T $RES';
+ end;
+ end;
+end;
+
+
+procedure TLinkerSinclairQL.SetDefaultInfo;
+begin
+ if target_info.system = system_m68k_sinclairql then
+ SetSinclairQLInfo;
+end;
+
+
+procedure TLinkerSinclairQL.InitSysInitUnitName;
+begin
+ sysinitunit:='si_prc';
+end;
+
+
+function TLinkerSinclairQL.WriteResponseFile(isdll: boolean): boolean;
+var
+ linkres : TLinkRes;
+ HPath : TCmdStrListItem;
+ s : string;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR("'+s+'")');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ if not (target_info.system in systems_internal_sysinit) then
+ begin
+ s:=FindObjectFile('prt0','',false);
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if UseVLink then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if not UseVLink then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ end;
+
+ LinkRes.Add(')');
+
+ with LinkRes do
+ begin
+ Add('');
+ Add('PHDRS {');
+ Add(' '+ProgramHeaderName+' PT_LOAD;');
+ Add('}');
+ Add('SECTIONS');
+ Add('{');
+ Add(' . = 0x'+hexstr(Origin,8)+';');
+ Add(' .text : {');
+ Add(' _stext = .;');
+ Add(' *(.text .text.* )');
+ Add(' *(.data .data.* .rodata .rodata.* .fpc.* )');
+ Add(' *(.stack .stack.*)');
+ { force the end of section to be word aligned }
+ Add(' . = ALIGN(2); SHORT(0x514C);');
+ Add(' _etext = .;');
+ Add(' } :'+ProgramHeaderName);
+ Add(' .bss (NOLOAD): {');
+ Add(' _sbss = .;');
+ Add(' *(.bss .bss.*)');
+ Add(' _ebss = .;');
+ Add(' } :'+ProgramHeaderName);
+ Add('}');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerSinclairQL.MakeSinclairQLExe: boolean;
+var
+ BinStr,
+ CmdStr : TCmdStr;
+ StripStr: string[40];
+ DynLinkStr : string;
+ GCSectionsStr : string;
+ FlagsStr : string;
+ MapStr : string;
+ ExeName: string;
+ fd,fs: file;
+ fhdr: text;
+ buf: pointer;
+ bufread,bufsize: longint;
+ HdrName: string;
+ HeaderLine: string;
+ HeaderSize: longint;
+ code: word;
+ QLHeader: TQLHeader;
+ XTccData: TXTccData;
+ BinSize: longint;
+ DataSpace: DWord;
+begin
+ StripStr:='';
+ GCSectionsStr:='';
+ DynLinkStr:='';
+ FlagsStr:='';
+ MapStr:='';
+
+ if (cs_link_map in current_settings.globalswitches) then
+ MapStr:='-M'+maybequoted(ScriptFixFilename(current_module.mapfilename));
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ if rlinkpath<>'' then
+ DynLinkStr:='--rpath-link '+rlinkpath;
+ if UseVLink then
+ begin
+ if create_smartlink_sections then
+ GCSectionsStr:='-gc-all';
+ end;
+
+ ExeName:=current_module.exefilename;
+ HdrName:=ExeName+'.hdr';
+
+ { Call linker }
+ SplitBinCmd(Info.ExeCmd[1],BinStr,CmdStr);
+ binstr:=FindUtil(utilsprefix+BinStr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(ExeName)));
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ Replace(cmdstr,'$MAP',MapStr);
+ Replace(cmdstr,'$FLAGS',FlagsStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ MakeSinclairQLExe:=DoExec(BinStr,CmdStr,true,false);
+
+ { Kludge:
+ With the above linker script, vlink will produce two files. The main binary
+ and the relocation info. Here we copy the two together. (KB) }
+ if MakeSinclairQLExe then
+ begin
+ QLHeader:=DefaultQLHeader;
+ XTccData:=DefaultXTccData;
+
+ BinSize:=0;
+ bufsize:=16384;
+{$push}
+{$i-}
+ { Rename vlink's output file into the header file it is, then parse the
+ expected length from it. Later we use either this size or the final binary
+ size in the BASIC loader, depending on which one is bigger. (KB) }
+ RenameFile(ExeName,HdrName);
+ assign(fhdr,HdrName);
+ reset(fhdr);
+ readln(fhdr,HeaderLine);
+ Val(Copy(HeaderLine,RPos('0x',HeaderLine),Length(HeaderLine)),HeaderSize,code);
+ close(fhdr);
+
+ buf:=GetMem(bufsize);
+ assign(fd,ExeName);
+ rewrite(fd,1);
+
+ assign(fs,ExeName+'.'+ProgramHeaderName);
+ reset(fs,1);
+ BinSize := FileSize(fs);
+
+ { We assume .bss size is total size indicated by linker minus emmited binary.
+ DataSpace size is .bss + stack space }
+ DataSpace := NToBE(DWord(HeaderSize - BinSize + StackSize));
+
+ { Option: prepend QEmuLator and QPC2 v5 compatible header to EXE }
+ if sinclairql_metadata_format='QHDR' then
+ begin
+ QLHeader.hdr_data:=DataSpace;
+ blockwrite(fd, QLHeader, sizeof(QLHeader));
+ end;
+
+ repeat
+ blockread(fs,buf^,bufsize,bufread);
+ blockwrite(fd,buf^,bufread);
+ until eof(fs);
+ close(fs);
+ // erase(fs);
+
+ assign(fs,ExeName+'.'+ProgramHeaderName+'.rel'+ProgramHeaderName);
+ reset(fs,1);
+ repeat
+ blockread(fs,buf^,bufsize,bufread);
+ blockwrite(fd,buf^,bufread);
+ until eof(fs);
+ close(fs);
+ // erase(fs);
+
+ { Option: append cross compilation data space marker, this can be picked up by
+ a special version of InfoZIP (compiled with -DQLZIP and option -Q) or by any
+ of the XTcc unpack utilities }
+ if sinclairql_metadata_format='XTCC' then
+ begin
+ XTccData.xtcc_data:=DataSpace;
+ blockwrite(fd, XTccData, sizeof(XTccData));
+ end;
+
+ close(fd);
+{$pop}
+ FreeMem(buf);
+
+ MakeSinclairQLExe:=(code = 0) and not (BinSize = 0) and (IOResult = 0);
+ end;
+end;
+
+
+function TLinkerSinclairQL.MakeExecutable:boolean;
+var
+ success : boolean;
+ bootfile : TScript;
+ ExeName: String;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename);
+
+ { Write used files and libraries }
+ WriteResponseFile(false);
+
+ success:=MakeSinclairQLExe;
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterLinker(ld_sinclairql,TLinkerSinclairQL);
+ RegisterTarget(system_m68k_sinclairql_info);
+end.