2
0

si_prc.pp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2020 by Karoly Balogh
  4. System Entry point for the Sinclair QL
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit si_prc;
  12. interface
  13. implementation
  14. {$i qdosh.inc}
  15. {$i qdosfuncs.inc}
  16. var
  17. binstart: byte; external name '_stext';
  18. binend: byte; external name '_etext';
  19. bssstart: byte; external name '_sbss';
  20. bssend: byte; external name '_ebss';
  21. stackpointer_on_entry: pointer; public name '__stackpointer_on_entry';
  22. procedure PascalMain; external name 'PASCALMAIN';
  23. procedure PascalStart(a7_on_entry: pointer); noreturn; forward;
  24. { this function must be the first in this unit which contains code }
  25. procedure _FPC_proc_start; cdecl; assembler; nostackframe; noreturn; public name '_start';
  26. asm
  27. bra @start
  28. dc.l $0
  29. dc.w $4afb
  30. dc.w 8
  31. dc.l $4650435f { Job name buffer. FPC_PROG by default, can be overridden }
  32. dc.l $50524f47 { the startup code will inject the main program name here }
  33. dc.l $00000000 { user codes is free to use the SetQLJobName() function }
  34. dc.l $00000000 { max. length: 48 characters }
  35. dc.l $00000000
  36. dc.l $00000000
  37. dc.l $00000000
  38. dc.l $00000000
  39. dc.l $00000000
  40. dc.l $00000000
  41. dc.l $00000000
  42. dc.l $00000000
  43. @start:
  44. { relocation code }
  45. { get our actual position in RAM }
  46. lea.l binstart(pc),a0
  47. move.l a0,d0
  48. { get an offset to the end of the binary. this works both
  49. relocated and not. The decision if to relocate is done
  50. later then }
  51. lea.l binend,a1
  52. lea.l binstart,a0
  53. sub.l a0,a1
  54. add.l d0,a1
  55. move.l d0,a0
  56. { read the relocation marker, this is always two padding bytes
  57. ad the end of .text, so we're free to poke there }
  58. move.w -2(a1),d7
  59. beq @noreloc
  60. { zero out the relocation marker, so if our code is called again
  61. without reload, it won't relocate itself twice }
  62. move.w #0,-2(a1)
  63. { first item in the relocation table is the number of relocs }
  64. move.l (a1)+,d7
  65. beq @noreloc
  66. {$DEFINE PACKEDRELOCS}
  67. {$IFNDEF PACKEDRELOCS}
  68. @relocloop:
  69. { we read the offsets and relocate them }
  70. move.l (a1)+,d1
  71. add.l d0,(a0,d1)
  72. subq.l #1,d7
  73. bne @relocloop
  74. {$ELSE PACKEDRELOCS}
  75. moveq #0,d2
  76. @relocloop:
  77. { we read the offsets and relocate them }
  78. moveq #0,d1
  79. move.b (a1)+,d1
  80. bne @addoffs
  81. { if byte = 0, we have a long offset following }
  82. move.b (a1)+,d1
  83. lsl.w #8,d1
  84. move.b (a1)+,d1
  85. swap d1
  86. move.b (a1)+,d1
  87. lsl.w #8,d1
  88. move.b (a1)+,d1
  89. subq.l #4,d7
  90. @addoffs:
  91. add.l d1,d2
  92. add.l d0,(a0,d2)
  93. subq.l #1,d7
  94. bgt @relocloop
  95. {$ENDIF PACKEDRELOCS}
  96. @noreloc:
  97. move.l a7,a0
  98. bra PascalStart
  99. end;
  100. procedure _FPC_proc_halt(_ExitCode: longint); noreturn; public name '_haltproc';
  101. begin
  102. mt_frjob(-1, _ExitCode);
  103. end;
  104. procedure PascalStart(a7_on_entry: pointer); noreturn;
  105. begin
  106. { initialize .bss }
  107. FillChar(bssstart,PtrUInt(@bssend)-PtrUInt(@bssstart),#0);
  108. stackpointer_on_entry:=a7_on_entry;
  109. PascalMain;
  110. end;
  111. end.