1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
| /* -----------------------------------------------------------------------
| sysv.S - Copyright (c) 2004 Renesas Technology
|
| M32R Foreign Function Interface
|
| Permission is hereby granted, free of charge, to any person obtaining
| a copy of this software and associated documentation files (the
| ``Software''), to deal in the Software without restriction, including
| without limitation the rights to use, copy, modify, merge, publish,
| distribute, sublicense, and/or sell copies of the Software, and to
| permit persons to whom the Software is furnished to do so, subject to
| the following conditions:
|
| The above copyright notice and this permission notice shall be included
| in all copies or substantial portions of the Software.
|
| THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
| IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
| OTHER DEALINGS IN THE SOFTWARE.
| ----------------------------------------------------------------------- */
|
| #define LIBFFI_ASM
| #include <fficonfig.h>
| #include <ffi.h>
| #ifdef HAVE_MACHINE_ASM_H
| #include <machine/asm.h>
| #else
| /* XXX these lose for some platforms, I'm sure. */
| #define CNAME(x) x
| #define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
| #endif
|
| .text
|
| /* R0: ffi_prep_args */
| /* R1: &ecif */
| /* R2: cif->bytes */
| /* R3: fig->flags */
| /* sp+0: ecif.rvalue */
| /* sp+4: fn */
|
| /* This assumes we are using gas. */
| ENTRY(ffi_call_SYSV)
| /* Save registers. */
| push fp
| push lr
| push r3
| push r2
| push r1
| push r0
| mv fp, sp
|
| /* Make room for all of the new args. */
| sub sp, r2
|
| /* Place all of the ffi_prep_args in position. */
| mv lr, r0
| mv r0, sp
| /* R1 already set. */
|
| /* And call. */
| jl lr
|
| /* Move first 4 parameters in registers... */
| ld r0, @(0,sp)
| ld r1, @(4,sp)
| ld r2, @(8,sp)
| ld r3, @(12,sp)
|
| /* ...and adjust the stack. */
| ld lr, @(8,fp)
| cmpi lr, #16
| bc adjust_stack
| ldi lr, #16
| adjust_stack:
| add sp, lr
|
| /* Call the function. */
| ld lr, @(28,fp)
| jl lr
|
| /* Remove the space we pushed for the args. */
| mv sp, fp
|
| /* Load R2 with the pointer to storage for the return value. */
| ld r2, @(24,sp)
|
| /* Load R3 with the return type code. */
| ld r3, @(12,sp)
|
| /* If the return value pointer is NULL, assume no return value. */
| beqz r2, epilogue
|
| /* Return INT. */
| ldi r4, #FFI_TYPE_INT
| bne r3, r4, return_double
| st r0, @r2
| bra epilogue
|
| return_double:
| /* Return DOUBLE or LONGDOUBLE. */
| ldi r4, #FFI_TYPE_DOUBLE
| bne r3, r4, epilogue
| st r0, @r2
| st r1, @(4,r2)
|
| epilogue:
| pop r0
| pop r1
| pop r2
| pop r3
| pop lr
| pop fp
| jmp lr
|
| .ffi_call_SYSV_end:
| .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
|