summaryrefslogtreecommitdiff
path: root/rtl/amiga/m68k/si_prc.pp
blob: b37527cdf505f7a951b49900bc5e1c04d9330850 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
{
    This file is part of the Free Pascal run time library.
    Copyright (c) 2016 by the Free Pascal development team

    System Entry point for Amiga/68k, Pascal only programs

    See the file COPYING.FPC, included in this distribution,
    for details about the copyright.

    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.

 **********************************************************************}

unit si_prc;

interface

implementation

var
  AOS_ExecBase: Pointer; public name '_ExecBase';
  AOS_DosBase: Pointer; external name '_DOSBase';
  realExecBase: Pointer absolute $4;
  StkLen: LongInt; external name '__stklen';
  sysinit_jmpbuf: jmp_buf;
  ExitCode: LongInt;

{ the definitions in there need AOS_Execbase }
{$include execd.inc}
{$include execf.inc}
{$include timerd.inc}
{$include doslibd.inc}
{$include doslibf.inc}

{$if defined(AMIGA_V1_0_ONLY) or defined(AMIGA_V1_2_ONLY)}
{$define AMIGA_LEGACY}
{$include legacyexech.inc}
{$endif}

{$ifdef AMIGA_LEGACY}
var
  args: pointer; public name '__fpc_args';
  arglen: dword; public name '__fpc_arglen';
{$endif}

var
  sst: TStackSwapStruct;

const
{$if defined(AMIGA_V1_0_ONLY)}
  NEEDS_NEWER_OS = 'This program needs newer OS.'+LineEnding;
{$else}
{$if defined(AMIGA_V1_2_ONLY)}
  NEEDS_NEWER_OS = 'This program needs OS 1.2 or newer.'+LineEnding;
{$else}
{$if defined(AMIGA_V2_0_ONLY)}
  NEEDS_NEWER_OS = 'This program needs OS 2.04 or newer.'+LineEnding;
{$else}
  NEEDS_NEWER_OS = 'This program needs OS 3.0 or newer.'+LineEnding;
{$endif}
{$endif}
{$endif}

procedure PascalMain; external name 'PASCALMAIN';


{ this function must be the first in this unit which contains code }
function _FPC_proc_start: longint; cdecl; public name '_start';
var
  newStack: Pointer;
  task: PTask;
begin
{$IFDEF AMIGA_LEGACY}
  asm
    move.l d0, arglen
    move.l a0, args
  end;
{$ENDIF}
  AOS_ExecBase:=realExecBase;

  if PLibrary(AOS_ExecBase)^.lib_Version < AMIGA_OS_MINVERSION then
    begin
      AOS_DOSBase:=OpenLibrary('dos.library',0);
      if AOS_DOSBase <> nil then
        begin
          dosWrite(dosOutput,PChar(NEEDS_NEWER_OS),length(NEEDS_NEWER_OS));
          CloseLibrary(AOS_DOSBase);
        end;
      exit(20);
    end;

  newStack:=nil;
  task:=FindTask(nil);
  if (task^.tc_SPUpper-task^.tc_SPLower < StkLen) then
    begin
      newStack:=AllocVec(StkLen,MEMF_ANY);

      sst.stk_Lower:=newStack;
      sst.stk_Upper:=newStack+StkLen;
      sst.stk_Pointer:=newStack+StkLen;

      StackSwap(@sst);
    end;

  { Note: code between the two stackswaps only works because of the
    nature of the generated code. We're accessing globals which is
    safe, and the locals are either kept in reg, or accessed via
    the base pointer (A5), and because we don't use the stack for
    call arguments, only regs. If this CG behavior changes, this
    code might break. In that case an asm-written StackSwap+call
    wrapper code is the solution. (Basically the reimplementation
    of AROS' NewStackSwap or MorphOS' NewPPCStackSwap.) (KB) }

  if setjmp(sysinit_jmpbuf) = 0 then
    PascalMain;

  if newStack <> nil then
    begin
      StackSwap(@sst);
      FreeVec(newStack);
    end;

  _FPC_proc_start:=ExitCode;
end;

procedure _FPC_proc_halt(_ExitCode: longint); cdecl; public name '_haltproc';
begin
  ExitCode:=_ExitCode;
  longjmp(sysinit_jmpbuf,1);
end;


end.