• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "arch/asm_support.h"
17
18.macro SAVE_CALLEE_GP_REGS base_reg, tmp_reg, offset
19    add \tmp_reg, \base_reg, #(\offset - CALLEE_REG0_OFFSET)
20    stm \tmp_reg, {r4-r10}
21    CFI_REL_OFFSET(r10, (\offset - CALLEE_REG0_OFFSET + 4*6))
22    CFI_REL_OFFSET(r9,  (\offset - CALLEE_REG0_OFFSET + 4*5))
23    CFI_REL_OFFSET(r8,  (\offset - CALLEE_REG0_OFFSET + 4*4))
24    CFI_REL_OFFSET(r7,  (\offset - CALLEE_REG0_OFFSET + 4*3))
25    CFI_REL_OFFSET(r6,  (\offset - CALLEE_REG0_OFFSET + 4*2))
26    CFI_REL_OFFSET(r5,  (\offset - CALLEE_REG0_OFFSET + 4*1))
27    CFI_REL_OFFSET(r4,  (\offset - CALLEE_REG0_OFFSET + 4*0))
28.endm
29
30.macro RESTORE_CALLEE_GP_REGS base_reg, tmp_reg, offset
31    add \tmp_reg, \base_reg, #(\offset - CALLEE_REG0_OFFSET)
32    ldm \tmp_reg, {r4-r10}
33    CFI_RESTORE(r10)
34    CFI_RESTORE(r9)
35    CFI_RESTORE(r8)
36    CFI_RESTORE(r7)
37    CFI_RESTORE(r6)
38    CFI_RESTORE(r5)
39    CFI_RESTORE(r4)
40.endm
41
42.macro SAVE_CALLEE_FP_REGS base_reg, tmp_reg, offset
43    add \tmp_reg, \base_reg, #(\offset - CALLEE_VREG0_OFFSET)
44    vstm \tmp_reg, {d8-d15}
45    CFI_REL_OFFSET(d15, (\offset - CALLEE_VREG0_OFFSET + 4*14))
46    CFI_REL_OFFSET(d14, (\offset - CALLEE_VREG0_OFFSET + 4*12))
47    CFI_REL_OFFSET(d13, (\offset - CALLEE_VREG0_OFFSET + 4*10))
48    CFI_REL_OFFSET(d12, (\offset - CALLEE_VREG0_OFFSET + 4*8))
49    CFI_REL_OFFSET(d11, (\offset - CALLEE_VREG0_OFFSET + 4*6))
50    CFI_REL_OFFSET(d10, (\offset - CALLEE_VREG0_OFFSET + 4*4))
51    CFI_REL_OFFSET(d9,  (\offset - CALLEE_VREG0_OFFSET + 4*2))
52    CFI_REL_OFFSET(d8,  (\offset - CALLEE_VREG0_OFFSET + 4*0))
53.endm
54
55.macro RESTORE_CALLEE_FP_REGS base_reg, tmp_reg, offset
56    add \tmp_reg, \base_reg, #(\offset - CALLEE_VREG0_OFFSET)
57    vldm \tmp_reg, {d8-d15}
58    CFI_RESTORE(d15)
59    CFI_RESTORE(d14)
60    CFI_RESTORE(d13)
61    CFI_RESTORE(d12)
62    CFI_RESTORE(d11)
63    CFI_RESTORE(d10)
64    CFI_RESTORE(d9)
65    CFI_RESTORE(d8)
66.endm
67
68.macro SAVE_CALLER_GP_REGS fp_reg, tmp_reg, paramsnum
69    add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET+4*4
70.ifeq \paramsnum
71    stmdb \tmp_reg, {r0-r3}
72.endif
73.ifeq \paramsnum-1
74    stmdb \tmp_reg, {r1-r3}
75.endif
76.ifeq \paramsnum-2
77    stmdb \tmp_reg, {r2-r3}
78.endif
79.ifeq \paramsnum-3
80    str r3, [\tmp_reg, #-4]
81.endif
82.endm
83
84.macro RESTORE_CALLER_GP_REGS fp_reg, tmp_reg, is_void
85    add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET+4*4
86.if \is_void == 1
87    ldmdb \tmp_reg, {r0-r3}
88.else
89    ldmdb \tmp_reg, {r1-r3}
90.endif
91.endm
92
93.macro SAVE_CALLER_FP_REGS fp_reg, tmp_reg
94    add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET
95    vstm \tmp_reg, {d0-d7}
96.endm
97
98.macro RESTORE_CALLER_FP_REGS fp_reg, tmp_reg
99    add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET
100    vldm \tmp_reg, {d0-d7}
101.endm
102
103.macro CHECK_NATIVE_EXCEPTION is_void
104    ldr lr, [THREAD_REG, #MANAGED_THREAD_EXCEPTION_OFFSET]
105    cmp lr, #0
106
107    beq 3f
108    CFI_REMEMBER_STATE
109
110.if \is_void == 0
111    add lr, fp, #-CALLER_REG0_OFFSET
112    ldr r0, [lr]
113.endif
114
115    ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)]
116    CFI_RESTORE(lr)
117
118    add sp, sp, #BRIDGE_FRAME_SIZE
119    CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE)
120
121    b ThrowNativeExceptionBridge
122    CFI_RESTORE_STATE
123
1243:
125    ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)]
126    CFI_RESTORE(lr)
127
128    add sp, sp, #BRIDGE_FRAME_SIZE
129    CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE)
130.endm
131
132.macro BRIDGE_SELECTOR name, notcompiled_entry, compiled_entry
133.global \name
134.type \name, %function
135\name:
136    ldrb r12, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET]
137    tst r12, r12
138    bne \compiled_entry
139    b \notcompiled_entry
140.endm
141
142
143.macro RUNTIME_CALL_CHECKER name, entry
144.global \name
145.type \name, %function
146\name:
147      CFI_STARTPROC
148      CFI_DEF_CFA(sp, 0)
149
150      ldr r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET]
151
152      sub sp, sp, #8
153      CFI_ADJUST_CFA_OFFSET(8)
154
155      stm sp, {r12, lr}
156      CFI_REL_OFFSET(lr, -4)
157
158      mov r12, #0
159      str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET]
160
161      bl \entry
162
163      ldm sp, {r12, lr}
164      CFI_RESTORE(lr)
165
166      add sp, sp, #8
167      CFI_ADJUST_CFA_OFFSET(-8)
168
169      str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET]
170
171      bx lr
172      CFI_ENDPROC
173.endm
174
175.macro CALL_RUNTIME mode, entry, paramsnum, is_void
176      sub sp, sp, #BRIDGE_FRAME_SIZE
177      CFI_ADJUST_CFA_OFFSET(BRIDGE_FRAME_SIZE)
178
179      // Setup BoundaryFrame
180      str lr, [sp, #(BRIDGE_FRAME_SIZE - 1 * 4)]     // Bridge frame, slot 1 = npc = LR (the StackMap stays just after the bridge call)
181      CFI_REL_OFFSET(lr, (BRIDGE_FRAME_SIZE - 1 * 4))
182      str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] // ManagedThread.npc update
183      mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE
184      str lr, [sp, #(BRIDGE_FRAME_SIZE - 2 * 4)]     // Bridge frame, slot 2 = COMPILED_CODE_TO_INTERPRETER_BRIDGE flag
185      str fp, [sp, #(BRIDGE_FRAME_SIZE - 3 * 4)]    // Bridge frame, slot 3 = parent frame pointer
186      CFI_REL_OFFSET(fp, (BRIDGE_FRAME_SIZE - 3 * 4))
187      add lr, sp, #(BRIDGE_FRAME_SIZE - 3 * 4)
188      str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET]    // ManagedThread._frame = this boundary frame
189
190      SAVE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE
191#ifndef PANDA_TARGET_ARM32_ABI_SOFT
192      // StackWalker requires callee-saved FP registers to be saved unconditionally in the runtime bridge
193      SAVE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE
194#endif
195
196.if \mode != RUNTIME_MODE_SLOW_PATH
197      SAVE_CALLER_GP_REGS fp, lr, \paramsnum
198.endif
199
200#ifndef PANDA_TARGET_ARM32_ABI_SOFT
201      ldr r4, [fp, #(-CFRAME_FLAGS_SLOT * 4)]
202      tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK
203      beq 1f
204
205      SAVE_CALLER_FP_REGS fp, lr
2061:
207#endif
208
209      bl \entry
210
211      // State restore
212      str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET]
213
214#ifndef PANDA_TARGET_ARM32_ABI_SOFT
215      tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK
216      beq 2f
217
218      RESTORE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE
219      RESTORE_CALLER_FP_REGS fp, lr
2202:
221#endif
222
223      RESTORE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE
224      RESTORE_CALLER_GP_REGS fp, lr, \is_void
225
226      CHECK_NATIVE_EXCEPTION \is_void
227.endm
228
229.macro ENTRYPOINT name, entry, paramsnum, is_void
230.global \name
231.type \name, %function
232\name:
233      CFI_STARTPROC
234      CFI_DEF_CFA(sp, 0)
235
236      CALL_RUNTIME RUNTIME_MODE_DEFAULT, \entry, \paramsnum, \is_void
237      bx lr
238      CFI_ENDPROC
239.endm
240
241.macro ENTRYPOINT_SLOW_PATH name, entry, paramsnum, is_void
242.global \name
243.type \name, %function
244\name:
245    CFI_STARTPROC
246    CFI_DEF_CFA(sp, 0)
247
248    CALL_RUNTIME RUNTIME_MODE_SLOW_PATH, \entry, \paramsnum, \is_void
249    bx lr
250    CFI_ENDPROC
251.endm
252
253.macro MethodEntrypointStub name, entry, notcompiled
254.global \name
255.type \name, %function
256\name:
257    CFI_STARTPROC
258    CFI_DEF_CFA(sp, 0)
259
260    // If the caller is not a compiled method, we need to call \entry
261    // and return back after its execution
262    ldrb r1, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET]
263    tst r1, r1
264    beq .L\notcompiled
265    CFI_REMEMBER_STATE
266
267    str lr, [sp, #-4]
268    CFI_REL_OFFSET(lr, -4)
269    str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET]
270    mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE
271    str lr, [sp, #-8]
272    str fp, [sp, #-12]
273    CFI_REL_OFFSET(fp, -12)
274    sub lr, sp, #12
275    str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET]
276    sub sp, sp, #16
277    CFI_ADJUST_CFA_OFFSET(16)
278
279    push {r4 - r10}
280    CFI_ADJUST_CFA_OFFSET(28)
281    CFI_REL_OFFSET(r10, (6 * 4))
282    CFI_REL_OFFSET(r9,  (5 * 4))
283    CFI_REL_OFFSET(r8,  (4 * 4))
284    CFI_REL_OFFSET(r7,  (3 * 4))
285    CFI_REL_OFFSET(r6,  (2 * 4))
286    CFI_REL_OFFSET(r5,  (1 * 4))
287    CFI_REL_OFFSET(r4,  (0 * 4))
288
289#ifndef PANDA_TARGET_ARM32_ABI_SOFT
290    vpush {d8 - d15}
291    CFI_ADJUST_CFA_OFFSET(64)
292    CFI_REL_OFFSET(d15, (14 * 4))
293    CFI_REL_OFFSET(d14, (12 * 4))
294    CFI_REL_OFFSET(d13, (10 * 4))
295    CFI_REL_OFFSET(d12, (8 * 4))
296    CFI_REL_OFFSET(d11, (6 * 4))
297    CFI_REL_OFFSET(d10, (4 * 4))
298    CFI_REL_OFFSET(d9,  (2 * 4))
299    CFI_REL_OFFSET(d8,  (0 * 4))
300#endif
301
302    // align to 8
303    sub sp, sp, #4
304
305    bl \entry
306    // we're not going to return back here
307
308.L\notcompiled:
309    CFI_RESTORE_STATE
310    CFI_DEF_CFA(sp, 0)
311    str lr, [sp, #-4]
312    CFI_REL_OFFSET(lr, -(1 * 4))
313    sub sp, sp, #8
314    CFI_ADJUST_CFA_OFFSET(2 * 4)
315    bl \entry
316    add sp, sp, #8
317    CFI_ADJUST_CFA_OFFSET(-(2 * 4))
318    ldr lr, [sp, #-4]
319    CFI_RESTORE(lr)
320    bx lr
321    CFI_ENDPROC
322.endm
323
324#include "entrypoints_gen.S"
325#include "entrypoints_bridge_asm_macro.inl"
326
327MethodEntrypointStub AbstractMethodStub AbstractMethodErrorEntrypoint ame_not_compiled
328
329MethodEntrypointStub DefaultConflictMethodStub IncompatibleClassChangeErrorForMethodConflictEntrypoint icce_not_compiled
330