/*
*
*                Language Independent Library
*
*       Copyright 1983-2013 Green Hills Software,Inc.
*
*  This program is the property of Green Hills Software, Inc,
*  its contents are proprietary information and no part of it
*  is to be disclosed to anyone except employees of Green Hills
*  Software, Inc., or as agreed in writing signed by the President
*  of Green Hills Software, Inc.
*
*/
#ifdef __GHS_DTRACE_INSTRUMENTATION
	.dtinst
#elif defined(__GHS_REPLAY_INSTRUMENTATION)
	.rplinst
#endif

#include "indsyscl.h"
#if defined(EMBEDDED)
	.text
#if !defined(MINIMAL_STARTUP)
	.weak __ghsbegin_picbase
	.weak __ghsbegin_robase
	.weak __ghsbegin_pidbase
	.weak __ghs_rambootcodestart
	.weak __ghs_rambootcodeend
	.weak __ghs_rombootcodestart
	.weak __ghs_rombootcodeend
#if defined(__GHS_DTRACE_INSTRUMENTATION)
	.weak   __ghsbegin_tracebuf
#endif
#endif
        .weak __ghs_board_memory_init
#ifndef __GHS_DTRACE_INSTRUMENTATION
	.weak __ghs_initial_dotsyscall
#endif
_start::
	.need	exit
#ifndef __GHS_DTRACE_INSTRUMENTATION
	.need	__dotsyscall
#endif
; Save argc, argv, encp (if not under Multi, these are meaningless)
	mov	x19, x0
	mov	x20, x1
	mov	x21, x2
; initialize SDRAM a chance to initialize if we're running from flash
; NOTE: elxr will jump to the next instruction if no __ghs_board_memory_init
	bl	__ghs_board_memory_init
; Here is where we check to see if Green Hills Multi is running on top of us.
	mov	x0, SYSCALL_HELLO		; Set call type
	mov	x1, 1				; Another argument
#ifndef __GHS_DTRACE_INSTRUMENTATION
	bl	__ghs_initial_dotsyscall	; Make system call
#else
	mov	x0, 0				; Act like we found Multi
#endif

; We want to find the picbias, which is given by: 
;     picbias = actualaddress - linktime address
; 4 is added to the linktime address, to account for the extra 4 added to the
; PC when read, due to the less-than-transparent pipelining model of the ARM.

#if !defined(MINIMAL_STARTUP)
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movz	r5, :highest16:myaddr, LSL 48
	movk	r5, :higher16:myaddr, LSL 32
	movk	r5, :hi16:myaddr, LSL 16
	movk	r5, :lo16:myaddr, LSL 0
#else
	ldr	r5, pool_myaddr
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
.Lpicbase:
myaddr:
	adr     r2, myaddr
	sub	r5, r2, r5			; Now r5 contains picbase
#if defined(__GHS_NO_DATA_IN_TEXT__)
	mov	r9, r2				; used below
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
#endif /* !defined(MINIMAL_STARTUP) */

        cbnz	x0, setupregs			; Did we find Multi?

; We are under Multi.  Move the argc, argv, envp stuff into r1, r2, r3 for the
; next procedure call.  They were placed in r6, r7, r8 above...
	mov	x1, x19
	mov	x2, x20
	mov	x3, x21
	b	regsokay

setupregs:
; Let's put some reasonable value in the regs
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movz	x1, :highest16:__ghsend_stack, LSL 48
	movk	x1, :higher16:__ghsend_stack, LSL 32
	movk	x1, :hi16:__ghsend_stack, LSL 16
	movk	x1, :lo16:__ghsend_stack, LSL 0
#else
 	ldr	x1, pool_stack
#endif
	mov 	x3, 0				; Clear envp reg
	mov	sp, x1
	mov	x2, 0				; Clear argv reg
	mov	x1, 0				; Clear argc reg

regsokay:
#if !defined(MINIMAL_STARTUP)
#if defined(__GHS_NO_DATA_IN_TEXT__)
; With -layout=romcopy, the linker calculated the difference of regtab/baseptrs
; which are in ROM and .Lpicbase which is in RAM, so we need to adjust the
; difference at run time in this case. */
; Note that PIC is not handled here, as -no_data_in_text is not supported
; on PIC
   	mov 	r4, 0		; default
	movz	r0, :highest16:__ghs_rombootcodestart, LSL 48
	movk	r0, :higher16:__ghs_rombootcodestart, LSL 32
	movk	r0, :hi16:__ghs_rombootcodestart, LSL 16
	movk	r0, :lo16:__ghs_rombootcodestart, LSL 0
	cmp	r9, r0
	b.lt	.Lskipfix
	movz	r0, :highest16:__ghs_rombootcodeend, LSL 48
	movk	r0, :higher16:__ghs_rombootcodeend, LSL 32
	movk	r0, :hi16:__ghs_rombootcodeend, LSL 16
	movk	r0, :lo16:__ghs_rombootcodeend, LSL 0
	cmp	r9, r0
	b.gt	.Lskipfix
	mov	r4, r5		; correction factor
.Lskipfix:
	movz	r0, :highest16:baseptrs, LSL 48
	movk	r0, :higher16:baseptrs, LSL 32
	movk	r0, :hi16:baseptrs, LSL 16
	movk	r0, :lo16:baseptrs, LSL 0
	sub	r0, r0, r4
	add	r0, r0, r5			; Add in picbase
#else
        adr	r0, baseptrs
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
	; Initialize globalregs
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movz	r9, :highest16:regtab, LSL 48
	movk	r9, :higher16:regtab, LSL 32
	movk	r9, :hi16:regtab, LSL 16
	movk	r9, :lo16:regtab, LSL 0
	sub	r9, r9, r4
	add	r9, r9, r5			; Add in picbase
#else
 	adr	r9, regtab
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
	ldr	r18, [r9, #0x00]
	ldr	r19, [r9, #0x08]
	ldr	r20, [r9, #0x10]
	ldr	r21, [r9, #0x18]
	ldr	r22, [r9, #0x20]
	ldr	r23, [r9, #0x28]
	ldr	r24, [r9, #0x30]
	ldr	r25, [r9, #0x38]
#endif
#if defined(__GHS_DTRACE)
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movz	x19, :highest16:__ghsbegin_tracebuf, LSL 48
	movk	x19, :higher16:__ghsbegin_tracebuf, LSL 32
	movk	x19, :hi16:__ghsbegin_tracebuf, LSL 16
	movk	x19, :lo16:__ghsbegin_tracebuf, LSL 0
#else
	ldr	x19, pool_tracebuf
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
#endif /* defined(__GHS_DTRACE) */
	mov	fp, 0
; Now let's make a call into
; __ghs_ind_crt0 which will do some more stuff before finally calling main()
	bl	__ghs_ind_crt0			; Go to C land
loop_forever:
	b	loop_forever
	.endf	_start
#ifdef __ghs_asm	
	.maxstack _start, 0
	.fsize _start, 0
	.scall _start, __ghs_ind_crt0
	.scall _start, __ghs_board_memory_init
#ifndef __GHS_DTRACE_INSTRUMENTATION
	.scall _start, __ghs_initial_dotsyscall
#endif
#endif
__ghs_enterblock_func::
	ret
	.endf __ghs_enterblock_func
#if defined(__ghs_asm)
	.maxstack __ghs_enterblock_func,0
	.scall __ghs_enterblock_func,__leaf__
#endif

#if defined(__GHS_NO_DATA_IN_TEXT__)
/* put the following literals / addresses in .rodata instead of .tet*/
	.section ".rodata", "a"
 	.align 8
#else
	.align 8
#if defined(__GHS_DTRACE)
pool_tracebuf:
	.dword	__ghsbegin_tracebuf
#endif /* defined(__GHS_DTRACE) */
pool_stack:
	.dword	__ghsend_stack
	.endo 	pool_stack
#if !defined(MINIMAL_STARTUP)
pool_myaddr:
	.dword	myaddr
	.endo 	pool_myaddr
#endif /* !defined(MINIMAL_STARTUP) */
#endif /* defined(__GHS_NO_DATA_IN_TEXT__) */
#if !defined(MINIMAL_STARTUP)
baseptrs:
	.dword 1	/* baseptrs version number */
	.dword	__ghsbegin_picbase
	.dword	__ghsbegin_robase
	.dword	__ghsbegin_pidbase
	.dword	__ghs_rambootcodestart
	.dword	__ghs_rambootcodeend
	.dword	__ghs_rombootcodestart
	.dword	__ghs_rombootcodeend
	.endo baseptrs

	.align 8
regtab:
	.weak	__ghs_init_r18, __ghs_init_r19
	.dword	__ghs_init_r18, __ghs_init_r19
	.weak	__ghs_init_r20, __ghs_init_r21
	.dword	__ghs_init_r20, __ghs_init_r21
	.weak	__ghs_init_r22, __ghs_init_r23
	.dword	__ghs_init_r22, __ghs_init_r23
	.weak	__ghs_init_r24, __ghs_init_r25
	.dword	__ghs_init_r24, __ghs_init_r25
	.endo	regtab
#endif

	.section ".secinfo", "a"
/* Secinfo: Contains information on what sections should be cleared, copied,
	    etc.  Normally, the linker just fills this stuff in whenever the
	    section is empty.  So, this is left commented out, but you can
	    customize it if your application requires it.
        .globl __ghsbinfo_clear
        .globl __ghseinfo_clear
__ghsbinfo_clear:
	[these are arguments to the C function memset]
	.data.w __ghsbegin_bss, 0, __ghssize_bss 
	.data.w __ghsbegin_sbss,0,  __ghssize_sbss
__ghseinfo_clear:

        .globl __ghsbinfo_copy
        .globl __ghseinfo_copy
__ghsbinfo_copy:
	[these are arguments to the C function memcpy]
	.data.w	__ghsbegin_data, __ghsbegin_romdata, __ghssize_data
__ghseinfo_copy:

        .globl __ghsbinfo_gcount
        .globl __ghseinfo_gcount
__ghsbinfo_gcount:
	.data.w __ghsbegin_text, __ghssize_text
__ghseinfo_gcount:
*/

#endif

#ifdef __GHS_DTRACE_INSTRUMENTATION
	.nodtinst
#elif defined(__GHS_REPLAY_INSTRUMENTATION)
	.norplinst
#endif

