prt0.as 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2016 by Marcus Sackrow
  4. Startup code for AROS/ARM RTL
  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. r0 = argc
  11. r1 = argv
  12. r2 = ExecBase
  13. */
  14. .text
  15. .globl _start
  16. .type _start,#function
  17. _start:
  18. # save registers
  19. push {r0-r12,r14}
  20. # save the back jump into OS
  21. ldr ip,=_Backjump
  22. str lr,[ip]
  23. /* ExecBase */
  24. ldr ip,=_ExecBase
  25. str r2, [ip] /* ExecBase seems to be in r2 ;-)*/
  26. /* Save initial stackpointer*/
  27. ldr ip,=__stkptr
  28. str sp,[ip]
  29. # jump back -> exit
  30. ldr ip,=_exit
  31. ldr lr,[ip]
  32. /* check for stack extent */
  33. /* FindTask(nil) */
  34. # execbase to r1
  35. ldr r1,=_ExecBase
  36. ldr r1,[r1]
  37. # nil to r0
  38. mov r0,#0
  39. # caluclate offset
  40. ldr r12,[r1, #-196]
  41. # do it
  42. blx r12
  43. /* get data from PTask splower r0, spupper r1 */
  44. mov r1, r0
  45. ldr r0, [r0, #60]
  46. ldr r1, [r1, #64]
  47. /* sub spUpper- spLower */
  48. sub r0,r1,r0
  49. /* compre with stacklen */
  50. ldr r1,=__stklen
  51. ldr r1,[r1]
  52. /* if OS stack bigger jump to nostack -> no stackswap needed */
  53. cmp r0, r1
  54. bge _nostack
  55. /* alloc a new stack and swap to it */
  56. _withstack:
  57. /* AllocVec(__stklen, MEMF_ANY) */
  58. # execbase to r2
  59. ldr r2,=_ExecBase
  60. ldr r2,[r2]
  61. # MEMF_ANY (0) to r1
  62. mov r1,#0
  63. # stacksize to r0
  64. ldr r0,=__stklen
  65. ldr r0,[r0]
  66. # do the call
  67. ldr r12,[r2, #-456]
  68. blx r12
  69. # save the Pointer to StackAreaPtr
  70. ldr ip,=StackAreaPtr
  71. str r0,[ip]
  72. # check if we got some Memory -> else byebye
  73. cmp r0, #0
  74. beq _exit
  75. /* Prepare StackSwapStruct */
  76. ldr ip,=StackSwapStruct
  77. str r0,[ip] /* stk_Lower */
  78. # get stacklen
  79. ldr r1,=__stklen
  80. ldr r1,[r1]
  81. # add StackLen to Lower Stack
  82. add r0,r1,r0
  83. # put upper stack swap
  84. str r0,[ip, #4] /* stk_Upper */
  85. # start pointer
  86. str r0,[ip, #8] /* stk_Pointer */
  87. /* NewStackSwap(StackSwapStruct, _runpascal, StackSwapArgs) */
  88. # 4. ExecBase
  89. ldr r3,=_ExecBase
  90. ldr r3,[r3]
  91. # 3. StackSwapArgs
  92. ldr r2,=StackSwapArgs
  93. # 2. funcptr
  94. ldr r1,=_runpascal
  95. # 1. StackSwapStruct
  96. ldr r0,=StackSwapStruct
  97. # do the call
  98. ldr r12,[r3, #-536]
  99. blx r12
  100. # after Stackswap we just to _afterstackswap to leave the program
  101. bl _afterstackswap
  102. /* NewStackswap will jump here */
  103. _runpascal:
  104. # save registers on the new stack
  105. push {r0-r12,lr}
  106. # save the stackswapped stackptr to
  107. ldr ip,=__stkptr1
  108. str sp,[ip]
  109. /* Main Program for both cases */
  110. _nostack:
  111. # call the Pascal Main
  112. bl PASCALMAIN
  113. # seems never reach this point
  114. /* haltproc is called by Pascal */
  115. .globl _haltproc
  116. .type _haltproc,#function
  117. _haltproc:
  118. # Check if StackAreaPtr not set -> no need to free, can directly exit
  119. ldr ip,=StackAreaPtr
  120. ldr r0,[ip]
  121. cmp r0, #0
  122. beq _exit
  123. # StackAreaPtr is assigned, so we did the Stack Swap and must
  124. # swap back and free the memory
  125. # get back the stackswaped stack and get back all registers and jump back
  126. # to stackswap -> leave the Stack
  127. ldr ip,=__stkptr1
  128. ldr sp,[ip]
  129. pop {r0-r12,lr}
  130. bx lr
  131. /* jumps here after Stackswap leaving -> with original stack again*/
  132. _afterstackswap:
  133. # get StackAreaPtr
  134. ldr ip,=StackAreaPtr
  135. ldr r0,[ip]
  136. # freeVec(StackAreaPtr)
  137. #execbase to r1
  138. ldr r1,=_ExecBase
  139. ldr r1,[r1]
  140. #calc FreeVec offset
  141. ldr r12,[r1, #-460]
  142. blx r12
  143. /* jumps here on error or if no stackswap was done */
  144. _exit:
  145. # get back the original OS Stack
  146. ldr ip,=__stkptr
  147. ldr sp,[ip]
  148. # restore registers
  149. pop {r0-r12,r14}
  150. # exitcode should be r0
  151. ldr ip,=operatingsystem_result
  152. ldr r0,[ip]
  153. # jump back to OS
  154. ldr ip,=_Backjump
  155. ldr lr,[ip]
  156. bx lr
  157. /* Define a symbol for the first piece of initialized data. */
  158. .data
  159. .globl __data_start
  160. __data_start:
  161. .long 0
  162. .weak data_start
  163. data_start = __data_start
  164. .bss
  165. .comm __stkptr,4
  166. .comm __stkptr1,4
  167. .comm _ExecBase,4
  168. .comm _Backjump,4
  169. .comm StackAreaPtr,4
  170. .comm StackSwapStruct, 12
  171. .comm StackSwapArgs, 32