1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* -----------------------------------------------------------------------
2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   sysv.S - Copyright (c) 2004 Simon Posnjak
3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    Copyright (c) 2005 Axis Communications AB
4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   CRIS Foreign Function Interface
6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Permission is hereby granted, free of charge, to any person obtaining
8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   a copy of this software and associated documentation files (the
9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ``Software''), to deal in the Software without restriction, including
10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   without limitation the rights to use, copy, modify, merge, publish,
11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   distribute, sublicense, and/or sell copies of the Software, and to
12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   permit persons to whom the Software is furnished to do so, subject to
13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   the following conditions:
14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   The above copyright notice and this permission notice shall be included
16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   in all copies or substantial portions of the Software.
17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   OTHER DEALINGS IN THE SOFTWARE.
25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ----------------------------------------------------------------------- */
26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define LIBFFI_ASM
28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h>
29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define CONCAT(x,y) x ## y
30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define XCONCAT(x,y) CONCAT (x, y)
31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.text
34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; OK, when we get called we should have this (according to
36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;;
38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; R10:	 ffi_prep_args (func. pointer)
39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; R11:  &ecif
40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; R12:  cif->bytes
41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; R13:  fig->flags
42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; sp+0: ecif.rvalue
43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; sp+4: fn (function pointer to the function that we need to call)
44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.globl  L(ffi_call_SYSV)
46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.type   L(ffi_call_SYSV),@function
47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.hidden	L(ffi_call_SYSV)
48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueL(ffi_call_SYSV):
50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Save the regs to the stack.
51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	push $srp
52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Used for stack pointer saving.
53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	push $r6
54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Used for function address pointer.
55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	push $r7
56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Used for stack pointer saving.
57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	push $r8
58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; We save fig->flags to stack we will need them after we
59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; call The Function.
60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	push $r13
61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Saving current stack pointer.
63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $sp,$r8
64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $sp,$r6
65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Move address of ffi_prep_args to r13.
67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r10,$r13
68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Make room on the stack for the args of fn.
70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	sub.d  $r12,$sp
71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; 	r10 <-- stack pointer
74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; 	r11 <-- &ecif (already there)
75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $sp,$r10
76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Call the function.
78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	jsr $r13
79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Save the size of the structures which are passed on stack.
81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r10,$r7
82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Move first four args in to r10..r13.
84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+0],$r10
85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+4],$r11
86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+8],$r12
87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+12],$r13
88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Adjust the stack and check if any parameters are given on stack.
90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	addq 16,$sp
91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	sub.d $r7,$r6
92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmp.d $sp,$r6
93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	bpl go_on
95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	nop
96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquego_on_no_params_on_stack:
98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r6,$sp
99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquego_on:
101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Discover if we need to put rval address in to r9.
102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$r8+0],$r7
103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_STRUCT,$r7
104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	bne call_now
105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	nop
106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Move rval address to $r9.
108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$r8+20],$r9
109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecall_now:
111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Move address of The Function in to r7.
112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$r8+24],$r7
113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Call The Function.
115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	jsr $r7
116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Reset stack.
118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r8,$sp
119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Load rval type (fig->flags) in to r13.
121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	pop $r13
122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Detect rval type.
124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_VOID,$r13
125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	beq epilogue
126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_STRUCT,$r13
128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	beq epilogue
129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_DOUBLE,$r13
131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	beq return_double_or_longlong
132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_UINT64,$r13
134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	beq return_double_or_longlong
135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	cmpq FFI_TYPE_SINT64,$r13
137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	beq return_double_or_longlong
138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	nop
139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Just return the 32 bit value.
141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	ba return
142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	nop
143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquereturn_double_or_longlong:
145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Load half of the rval to r10 and the other half to r11.
146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+16],$r13
147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r10,[$r13]
148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	addq 4,$r13
149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r11,[$r13]
150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	ba epilogue
151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	nop
152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquereturn:
154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	;; Load the rval to r10.
155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp+16],$r13
156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r10,[$r13]
157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueepilogue:
159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	pop $r8
160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	pop $r7
161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	pop $r6
162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	Jump [$sp+]
163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.size   ffi_call_SYSV,.-ffi_call_SYSV
165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Save R10..R13 into an array, somewhat like varargs.  Copy the next
167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   argument too, to simplify handling of any straddling parameter.
168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Save R9 and SP after those.  Jump to function handling the rest.
169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Since this is a template, copied and the main function filled in by
170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   the user.  */
171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.globl	L(ffi_cris_trampoline_template)
173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.type	L(ffi_cris_trampoline_template),@function
174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.hidden	L(ffi_cris_trampoline_template)
175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueL(ffi_cris_trampoline_template):
177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique0:
178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	/* The value we get for "PC" is right after the prefix instruction,
179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   two bytes from the beginning, i.e. 0b+2. */
180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r10,[$pc+2f-(0b+2)]
181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $pc,$r10
182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique1:
183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	addq 2f-1b+4,$r10
184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r11,[$r10+]
185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r12,[$r10+]
186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r13,[$r10+]
187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d [$sp],$r11
188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r11,[$r10+]
189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $r9,[$r10+]
190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d $sp,[$r10+]
191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	move.d 0,$r11
193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique3:
194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        jump 0
195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique2:
196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.size	ffi_cris_trampoline_template,.-0b
197457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
198457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* This macro create a constant usable as "extern const int \name" in
199457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   C from within libffi, when \name has no prefix decoration.  */
200457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
201457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.macro const name,value
202457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.globl	\name
203457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.type	\name,@object
204457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.hidden	\name
205457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique\name:
206457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.dword  \value
207457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.size	\name,4
208457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	.endm
209457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
210457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Constants for offsets within the trampoline.  We could do this with
211457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   just symbols, avoiding memory contents and memory accesses, but the
212457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   C usage code would look a bit stranger.  */
213457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
214457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	const L(ffi_cris_trampoline_fn_offset),2b-4-0b
215457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	const L(ffi_cris_trampoline_closure_offset),3b-4-0b
216