fpc/rtl/aros/arm/prt0.as
2016-11-15 19:33:46 +00:00

200 lines
4.1 KiB
ActionScript

/*
This file is part of the Free Pascal run time library.
Copyright (c) 2016 by Marcus Sackrow
Startup code for AROS/ARM RTL
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.
r0 = argc
r1 = argv
r2 = ExecBase
*/
.text
.globl _start
.type _start,#function
_start:
# save registers
push {r0-r12,r14}
# save the back jump into OS
ldr ip,=_Backjump
str lr,[ip]
/* ExecBase */
ldr ip,=_ExecBase
str r2, [ip] /* ExecBase seems to be in r2 ;-)*/
/* Save initial stackpointer*/
ldr ip,=__stkptr
str sp,[ip]
# jump back -> exit
ldr ip,=_exit
ldr lr,[ip]
/* check for stack extent */
/* FindTask(nil) */
# execbase to r1
ldr r1,=_ExecBase
ldr r1,[r1]
# nil to r0
mov r0,#0
# caluclate offset
ldr r12,[r1, #-196]
# do it
blx r12
/* get data from PTask splower r0, spupper r1 */
mov r1, r0
ldr r0, [r0, #60]
ldr r1, [r1, #64]
/* sub spUpper- spLower */
sub r0,r1,r0
/* compre with stacklen */
ldr r1,=__stklen
ldr r1,[r1]
/* if OS stack bigger jump to nostack -> no stackswap needed */
cmp r0, r1
bge _nostack
/* alloc a new stack and swap to it */
_withstack:
/* AllocVec(__stklen, MEMF_ANY) */
# execbase to r2
ldr r2,=_ExecBase
ldr r2,[r2]
# MEMF_ANY (0) to r1
mov r1,#0
# stacksize to r0
ldr r0,=__stklen
ldr r0,[r0]
# do the call
ldr r12,[r2, #-456]
blx r12
# save the Pointer to StackAreaPtr
ldr ip,=StackAreaPtr
str r0,[ip]
# check if we got some Memory -> else byebye
cmp r0, #0
beq _exit
/* Prepare StackSwapStruct */
ldr ip,=StackSwapStruct
str r0,[ip] /* stk_Lower */
# get stacklen
ldr r1,=__stklen
ldr r1,[r1]
# add StackLen to Lower Stack
add r0,r1,r0
# put upper stack swap
str r0,[ip, #4] /* stk_Upper */
# start pointer
str r0,[ip, #8] /* stk_Pointer */
/* NewStackSwap(StackSwapStruct, _runpascal, StackSwapArgs) */
# 4. ExecBase
ldr r3,=_ExecBase
ldr r3,[r3]
# 3. StackSwapArgs
ldr r2,=StackSwapArgs
# 2. funcptr
ldr r1,=_runpascal
# 1. StackSwapStruct
ldr r0,=StackSwapStruct
# do the call
ldr r12,[r3, #-536]
blx r12
# after Stackswap we just to _afterstackswap to leave the program
bl _afterstackswap
/* NewStackswap will jump here */
_runpascal:
# save registers on the new stack
push {r0-r12,lr}
# save the stackswapped stackptr to
ldr ip,=__stkptr1
str sp,[ip]
/* Main Program for both cases */
_nostack:
# call the Pascal Main
bl PASCALMAIN
# seems never reach this point
/* haltproc is called by Pascal */
.globl _haltproc
.type _haltproc,#function
_haltproc:
# Check if StackAreaPtr not set -> no need to free, can directly exit
ldr ip,=StackAreaPtr
ldr r0,[ip]
cmp r0, #0
beq _exit
# StackAreaPtr is assigned, so we did the Stack Swap and must
# swap back and free the memory
# get back the stackswaped stack and get back all registers and jump back
# to stackswap -> leave the Stack
ldr ip,=__stkptr1
ldr sp,[ip]
pop {r0-r12,lr}
bx lr
/* jumps here after Stackswap leaving -> with original stack again*/
_afterstackswap:
# get StackAreaPtr
ldr ip,=StackAreaPtr
ldr r0,[ip]
# freeVec(StackAreaPtr)
#execbase to r1
ldr r1,=_ExecBase
ldr r1,[r1]
#calc FreeVec offset
ldr r12,[r1, #-460]
blx r12
/* jumps here on error or if no stackswap was done */
_exit:
# get back the original OS Stack
ldr ip,=__stkptr
ldr sp,[ip]
# restore registers
pop {r0-r12,r14}
# exitcode should be r0
ldr ip,=operatingsystem_result
ldr r0,[ip]
# jump back to OS
ldr ip,=_Backjump
ldr lr,[ip]
bx lr
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start
.bss
.comm __stkptr,4
.comm __stkptr1,4
.comm _ExecBase,4
.comm _Backjump,4
.comm StackAreaPtr,4
.comm StackSwapStruct, 12
.comm StackSwapArgs, 32