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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/*
* The float abi macros used bellow are from risc-v c api:
* https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md
*
*/
#if defined(__riscv_float_abi_soft)
#define RV_FPREG_SIZE 0
#elif defined(__riscv_float_abi_single)
#define RV_OP_LOADFPREG flw
#define RV_OP_STROEFPREG fsw
#define RV_FPREG_SIZE 4
#elif defined(__riscv_float_abi_double)
#define RV_OP_LOADFPREG fld
#define RV_OP_STROEFPREG fsd
#define RV_FPREG_SIZE 8
#endif
#if __riscv_xlen == 32
#define RV_OP_LOADREG lw
#define RV_OP_STOREREG sw
#define RV_REG_SIZE 4
#define RV_REG_SHIFT 2
#define RV_FP_OFFSET (8 * RV_REG_SIZE)
#define RV_INT_OFFSET 0
#else
#define RV_OP_LOADREG ld
#define RV_OP_STOREREG sd
#define RV_REG_SIZE 8
#define RV_REG_SHIFT 3
#define RV_FP_OFFSET 0
#define RV_INT_OFFSET (8 * RV_FPREG_SIZE)
#endif
.text
.align 2
#ifndef BH_PLATFORM_DARWIN
.globl invokeNative
.type invokeNative, function
invokeNative:
#else
.globl _invokeNative
_invokeNative:
#endif /* end of BH_PLATFORM_DARWIN */
/*
* Arguments passed in:
*
* a0 function ptr
* a1 argv
* a2 nstacks
*/
/*
* sp (stack pointer)
* |- sd/sw to store 64/32-bit values from register to memory
* |- ld/lw to load from stack to register
* fp/s0 (frame pointer)
* a0-a7 (8 integer arguments)
* |- sd/sw to store
* |- ld/lw to load
* fa0-a7 (8 float arguments)
* |- fsd/fsw to store
* |- fld/fsw to load
* t0-t6 (temporaries regisgers)
* |- caller saved
*/
/* reserve space on stack to save return address and frame pointer */
addi sp, sp, - 2 * RV_REG_SIZE
RV_OP_STOREREG fp, 0 * RV_REG_SIZE(sp) /* save frame pointer */
RV_OP_STOREREG ra, 1 * RV_REG_SIZE(sp) /* save return address */
mv fp, sp /* set frame pointer to bottom of fixed frame */
/* save function ptr, argv & nstacks */
mv t0, a0 /* t0 = function ptr */
mv t1, a1 /* t1 = argv array address */
mv t2, a2 /* t2 = nstack */
#ifndef __riscv_float_abi_soft
/* fill in fa0-7 float-registers*/
RV_OP_LOADFPREG fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */
RV_OP_LOADFPREG fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */
RV_OP_LOADFPREG fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */
RV_OP_LOADFPREG fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */
RV_OP_LOADFPREG fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */
RV_OP_LOADFPREG fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */
RV_OP_LOADFPREG fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */
RV_OP_LOADFPREG fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */
#endif
/* fill in a0-7 integer-registers*/
RV_OP_LOADREG a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1) /* a0 */
RV_OP_LOADREG a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1) /* a1 */
RV_OP_LOADREG a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1) /* a2 */
RV_OP_LOADREG a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1) /* a3 */
RV_OP_LOADREG a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1) /* a4 */
RV_OP_LOADREG a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1) /* a5 */
RV_OP_LOADREG a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1) /* a6 */
RV_OP_LOADREG a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1) /* a7 */
/* t1 points to stack args */
/* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */
addi t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8
/* directly call the function if no args in stack,
x0 always holds 0 */
beq t2, x0, call_func
/* reserve enough stack space for function arguments */
sll t3, t2, RV_REG_SHIFT /* shift left 3 bits. t3 = n_stacks * 8 */
sub sp, sp, t3
/* make 16-byte aligned */
li t3, 15
not t3, t3
and sp, sp, t3
/* save sp in t4 register */
mv t4, sp
/* copy left arguments from caller stack to own frame stack */
loop_stack_args:
beq t2, x0, call_func
RV_OP_LOADREG t5, 0(t1) /* load stack argument, t5 = argv[i] */
RV_OP_STOREREG t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
addi t1, t1, RV_REG_SIZE /* move to next stack argument */
addi t4, t4, RV_REG_SIZE /* move to next stack pointer */
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
j loop_stack_args
call_func:
jalr t0
/* restore registers pushed in stack or saved in another register */
return:
mv sp, fp /* restore sp saved in fp before function call */
RV_OP_LOADREG fp, 0 * RV_REG_SIZE(sp) /* load previous frame poniter to fp register */
RV_OP_LOADREG ra, 1 * RV_REG_SIZE(sp) /* load previous return address to ra register */
addi sp, sp, 2 * RV_REG_SIZE /* pop frame, restore sp */
jr ra
|