;
;               Language Independent Runtime Library
;
;       Copyright 1983-2000
;                   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.
;

	.file "ind_call.arm"

#include "arm_dt.arm"
	dtrace_stamp ind_call.arm
#if defined(EMBEDDED)

#if defined(MINIMAL_STARTUP) && !defined(NO_FAR_SYSCALL)
#define NO_FAR_SYSCALL
#endif
#if (defined(__ghs_pic) || defined(__ghs_ropi)) && defined(__THUMB)
#define PICADDR(addr, base) addr-base-4
#elif defined(__ghs_pic) || defined(__ghs_ropi)
#define PICADDR(addr, base) addr-base-8
#else
#define PICADDR(addr, base) addr
#endif

	.align	4
	.text
#ifdef __THUMB
#if defined(__THUMB2_AWARE) && defined(__GHS_NO_DATA_IN_TEXT__)
	.thumb2
#else
	.thumb
#endif
#endif
#ifdef __ghs_asm
; Define an argcheck __callee symbol for the function __ghs_syscall.
; int __ghs_syscall(int, ...)
__callee.__ghs_syscall.i.ie::               \
	.size __callee.__ghs_syscall.i.ie,0
#endif
	.globl	__ghs_syscall
__ghs_syscall:
	stack_entry
	block_entry
#ifdef __THUMB
	push	{r7,lr}

#if defined(NO_FAR_SYSCALL)
	mov	r7, 0				; Clear all condition codes
	bl	__dotsyscall			; Call into this area
#else
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movw	r7, %lo(PICADDR(__dotsyscall, piclab))
	movt	r7, %hi(PICADDR(__dotsyscall, piclab))
#else
	ldr	r7, dotsyscalladdr
#endif
#if defined(__ghs_pic) || defined(__ghs_ropi)
piclab:
	add	r7,pc
#endif
	mov	ip, r7
#if 	defined (__ARM_DSP) || defined(__THUMB2_AWARE)
	mov	r7, 0				; Clear all condition codes
	blx	ip
#else
	mov	r7, pc
	add	r7, r7, 7
	mov	lr, r7
	mov	r7, 0				; Clear all condition codes
..ghs.annotate.call_0:
	bx 	ip
#endif
#endif
	block_entry

; If error, carry flag is set.  If this happens, do some error code
	bcc	noerror				
	block_entry
	bl	__gh_set_errno
	block_entry
	mvn	r0,r7				; r0 := -1
noerror:
	block_entry
	pop	{r7}
	pop	{r3}
..ghs.annotate.return_0:
	bx	r3				; Return to caller
#else
	block_entry
	mov	r12,sp
	stmfd	[sp]!,{fp-r12,lr-pc}
	sub	fp,r12,4
	mov	ip, 0
	adds	ip, ip, ip			; Clear all condition codes

#if defined(NO_FAR_SYSCALL)
	bl	__dotsyscall			; Call into this area
#else
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movw	ip, %lo(PICADDR(__dotsyscall, piclab))
	movt	ip, %hi(PICADDR(__dotsyscall, piclab))
#else
	ldr	ip, dotsyscalladdr
#endif
#if defined(__ghs_pic) || defined(__ghs_ropi)
piclab:
	add	ip, ip, pc
#endif
#if	defined (__ARM_DSP)
	blx	ip
#else
	mov	lr, pc
#if defined (__THUMB_AWARE)
	bx	ip
#else
	mov	pc, ip
#endif
#endif
#endif
	block_entry

; If error, carry flag is set.  If this happens, do some error code
	bcc	noerror
	block_entry
	bl	__gh_set_errno
	block_entry
	mvn	r0, 0				; r0 := -1
noerror:
	block_entry
	stack_exit
	ldmea	[fp],{fp,ip,lr}			; Return to caller
	mov	sp, ip
#if defined (__THUMB_AWARE)
	bx	lr
#else
	mov	pc, lr
#endif
#endif
	.type   __ghs_syscall,$function
	.size   __ghs_syscall,.-__ghs_syscall

#if !defined(__GHS_NO_DATA_IN_TEXT__)
#if !defined(NO_FAR_SYSCALL)
	.align 	4
dotsyscalladdr:
	.data.w PICADDR(__dotsyscall, piclab)
	.type	dotsyscalladdr,$object
	.size	dotsyscalladdr,4
#endif
#endif

#ifdef __ghs_asm
#ifdef __THUMB
	.frameinfo __ghs_syscall,4,-4,0x4080
#else
	.frameinfo __ghs_syscall,12,-12,0xd800
#endif
	.scall  __ghs_syscall, __gh_set_errno
	.scall  __ghs_syscall, __dotsyscall
#endif

	.align	4
	.text
#ifdef __THUMB
#if defined(__THUMB2_AWARE) && defined(__GHS_NO_DATA_IN_TEXT__)
	.thumb2
#else
	.thumb
#endif
#endif
#ifdef __ghs_asm
; Define an argcheck __callee symbol for the function __ghs_syscall64.
; int64_t __ghs_syscall64(int, ...)
__callee.__ghs_syscall64.l.ie::               \
	.size __callee.__ghs_syscall64.l.ie,0
#endif
	.globl	__ghs_syscall64
__ghs_syscall64:
	stack_entry
	block_entry
#ifdef __THUMB
	push	{r7,lr}

#if defined(NO_FAR_SYSCALL)
	mov	r7, 0				; Clear all condition codes
	bl	__dotsyscall			; Call into this area
#else
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movw	r7, %lo(PICADDR(__dotsyscall, piclab64))
	movt	r7, %hi(PICADDR(__dotsyscall, piclab64))
#else
	ldr	r7, dotsyscalladdr64
#endif
#if defined(__ghs_pic) || defined(__ghs_ropi)
piclab64:
	add	r7,pc
#endif
	mov	ip, r7
#if 	defined (__ARM_DSP) || defined(__THUMB2_AWARE)
	mov	r7, 0				; Clear all condition codes
	blx	ip
#else
	mov	r7, pc
	add	r7, r7, 7
	mov	lr, r7
	mov	r7, 0				; Clear all condition codes
..ghs.annotate.call_1:
	bx 	ip
#endif
#endif
	block_entry

; If error, carry flag is set.  If this happens, do some error code
	bcc	noerror64
	block_entry
	bl	__gh_set_errno
	block_entry
	mvn	r0,r7				; r0 := -1
	mvn	r1,r7				; r1 := -1
noerror64:
	block_entry
#if defined(__BigEndian)
	; For compatibility with older libraries syscall return values are
	; always little-endian.  Swap r0 and r1 for big-endian.
	mov	r7,r0
	mov	r0,r1
	mov	r1,r7
#endif
	pop	{r7}
	pop	{r3}
..ghs.annotate.return_1:
	bx	r3				; Return to caller
#else
	mov	r12,sp
	stmfd	[sp]!,{fp-r12,lr-pc}
	sub	fp,r12,4
	mov	ip, 0
	adds	ip, ip, ip			; Clear all condition codes

#if defined(NO_FAR_SYSCALL)
	bl	__dotsyscall			; Call into this area
#else
#if defined(__GHS_NO_DATA_IN_TEXT__)
	movw	ip, %lo(PICADDR(__dotsyscall, piclab64))
	movt	ip, %hi(PICADDR(__dotsyscall, piclab64))
#else
	ldr	ip, dotsyscalladdr64
#endif
#if defined(__ghs_pic) || defined(__ghs_ropi)
piclab64:
	add	ip, ip, pc
#endif
#if	defined (__ARM_DSP)
	blx	ip
#else
	mov	lr, pc
#if defined (__THUMB_AWARE)
	bx	ip
#else
	mov	pc, ip
#endif
#endif
#endif
	block_entry

; If error, carry flag is set.  If this happens, do some error code
	bcc	noerror64
	block_entry
	bl	__gh_set_errno
	block_entry
	mvn	r0, 0				; r0 := -1
	mvn	r1, 0
noerror64:
	block_entry
#if defined(__BigEndian)
	; For compatibility with older libraries syscall return values are
	; always little-endian.  Swap r0 and r1 for big-endian.
	mov	ip, r0
	mov	r0, r1
	mov	r1, ip
#endif
	ldmea	[fp],{fp,ip,lr}			; Return to caller
	mov	sp, ip
	stack_exit
#if defined (__THUMB_AWARE)
	bx	lr
#else
	mov	pc, lr
#endif
#endif
	.type   __ghs_syscall64,$function
	.size   __ghs_syscall64,.-__ghs_syscall64

#if !defined(__GHS_NO_DATA_IN_TEXT__)
#if !defined(NO_FAR_SYSCALL)
	.align 	4
dotsyscalladdr64:
	.data.w	PICADDR(__dotsyscall, piclab64)
	.type	dotsyscalladdr64,$object
	.size	dotsyscalladdr64,4
#endif
#endif

#ifdef __ghs_asm
#ifdef __THUMB
	.frameinfo __ghs_syscall64,4,-4,0x4080
#else
	.frameinfo __ghs_syscall64,12,-12,0xd800
#endif
	.scall  __ghs_syscall64, __gh_set_errno
	.scall  __ghs_syscall64, __dotsyscall
#endif

#endif
