Skip to content

Commit 8335ffa

Browse files
committed
Merge invokeNative for riscv32/64 into unified implementation
Signed-off-by: Huang Qi <[email protected]>
1 parent e2638f1 commit 8335ffa

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
*/
5+
6+
/*
7+
* The float abi macros used bellow are from risc-v c api:
8+
* https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md
9+
*
10+
*/
11+
12+
#if defined(__riscv_float_abi_soft)
13+
#define RV_FPREG_SIZE 0
14+
#elif defined(__riscv_float_abi_single)
15+
#define RV_OP_LOADFPREG flw
16+
#define RV_OP_STROEFPREG fsw
17+
#define RV_FPREG_SIZE 4
18+
#elif defined(__riscv_float_abi_double)
19+
#define RV_OP_LOADFPREG fld
20+
#define RV_OP_STROEFPREG fsd
21+
#define RV_FPREG_SIZE 8
22+
#endif
23+
24+
#if __riscv_xlen == 32
25+
#define RV_OP_LOADREG lw
26+
#define RV_OP_STOREREG sw
27+
#define RV_REG_SIZE 4
28+
#define RV_REG_SHIFT 2
29+
#define RV_FP_OFFSET (8 * RV_FPREG_SIZE)
30+
#define RV_INT_OFFSET 0
31+
#else
32+
#define RV_OP_LOADREG ld
33+
#define RV_OP_STOREREG sd
34+
#define RV_REG_SIZE 8
35+
#define RV_REG_SHIFT 3
36+
#define RV_FP_OFFSET 0
37+
#define RV_INT_OFFSET (8 * RV_FPREG_SIZE)
38+
#endif
39+
40+
.text
41+
.align 2
42+
#ifndef BH_PLATFORM_DARWIN
43+
.globl invokeNative
44+
.type invokeNative, function
45+
invokeNative:
46+
#else
47+
.globl _invokeNative
48+
_invokeNative:
49+
#endif /* end of BH_PLATFORM_DARWIN */
50+
51+
/*
52+
* Arguments passed in:
53+
*
54+
* a0 function ptr
55+
* a1 argv
56+
* a2 nstacks
57+
*/
58+
59+
/*
60+
* sp (stack pointer)
61+
* |- sd/sw to store 64/32-bit values from register to memory
62+
* |- ld/lw to load from stack to register
63+
* fp/s0 (frame pointer)
64+
* a0-a7 (8 integer arguments)
65+
* |- sd/sw to store
66+
* |- ld/lw to load
67+
* fa0-a7 (8 float arguments)
68+
* |- fsd/fsw to store
69+
* |- fld/fsw to load
70+
* t0-t6 (temporaries regisgers)
71+
* |- caller saved
72+
*/
73+
74+
/* reserve space on stack to save return address and frame pointer */
75+
addi sp, sp, - 2 * RV_REG_SIZE
76+
RV_OP_STOREREG fp, 0 * RV_REG_SIZE(sp) /* save frame pointer */
77+
RV_OP_STOREREG ra, 1 * RV_REG_SIZE(sp) /* save return address */
78+
79+
mv fp, sp /* set frame pointer to bottom of fixed frame */
80+
81+
/* save function ptr, argv & nstacks */
82+
mv t0, a0 /* t0 = function ptr */
83+
mv t1, a1 /* t1 = argv array address */
84+
mv t2, a2 /* t2 = nstack */
85+
86+
#ifndef __riscv_float_abi_soft
87+
/* fill in fa0-7 float-registers*/
88+
RV_OP_LOADFPREG fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */
89+
RV_OP_LOADFPREG fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */
90+
RV_OP_LOADFPREG fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */
91+
RV_OP_LOADFPREG fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */
92+
RV_OP_LOADFPREG fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */
93+
RV_OP_LOADFPREG fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */
94+
RV_OP_LOADFPREG fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */
95+
RV_OP_LOADFPREG fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */
96+
#endif
97+
98+
/* fill in a0-7 integer-registers*/
99+
RV_OP_LOADREG a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1) /* a0 */
100+
RV_OP_LOADREG a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1) /* a1 */
101+
RV_OP_LOADREG a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1) /* a2 */
102+
RV_OP_LOADREG a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1) /* a3 */
103+
RV_OP_LOADREG a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1) /* a4 */
104+
RV_OP_LOADREG a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1) /* a5 */
105+
RV_OP_LOADREG a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1) /* a6 */
106+
RV_OP_LOADREG a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1) /* a7 */
107+
108+
/* t1 points to stack args */
109+
110+
/* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */
111+
addi t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8
112+
113+
/* directly call the function if no args in stack,
114+
x0 always holds 0 */
115+
beq t2, x0, call_func
116+
117+
/* reserve enough stack space for function arguments */
118+
sll t3, t2, RV_REG_SHIFT /* shift left 3 bits. t3 = n_stacks * 8 */
119+
sub sp, sp, t3
120+
121+
/* make 16-byte aligned */
122+
li t3, 15
123+
not t3, t3
124+
and sp, sp, t3
125+
126+
/* save sp in t4 register */
127+
mv t4, sp
128+
129+
/* copy left arguments from caller stack to own frame stack */
130+
loop_stack_args:
131+
beq t2, x0, call_func
132+
RV_OP_LOADREG t5, 0(t1) /* load stack argument, t5 = argv[i] */
133+
RV_OP_STOREREG t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
134+
addi t1, t1, RV_REG_SIZE /* move to next stack argument */
135+
addi t4, t4, RV_REG_SIZE /* move to next stack pointer */
136+
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
137+
j loop_stack_args
138+
139+
call_func:
140+
jalr t0
141+
142+
/* restore registers pushed in stack or saved in another register */
143+
return:
144+
mv sp, fp /* restore sp saved in fp before function call */
145+
RV_OP_LOADREG fp, 0 * RV_REG_SIZE(sp) /* load previous frame poniter to fp register */
146+
RV_OP_LOADREG ra, 1 * RV_REG_SIZE(sp) /* load previous return address to ra register */
147+
addi sp, sp, 2 * RV_REG_SIZE /* pop frame, restore sp */
148+
jr ra

0 commit comments

Comments
 (0)