• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2024 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#include "arch/arm/shorty.S"
18#include "shorty_values.h"
19
20#define SHORTY_PTR_REG DEFAULT_SHORTY_PTR_REG
21#define SHORTY_REG DEFAULT_SHORTY_REG
22
23.macro PUSH_ARG arg_ptr, stack_ptr, tmp1, tmp2, next_label
24    cmp r2, #SHORTY_TAGGED
25    beq 2f
26
27    sub r2, r2, #SHORTY_FIRST_64
28    cmp r2, #(SHORTY_NUM_64BIT_TYPES - 1)
29    bls 1f
30    // it is a 32bit value
31    ldr \tmp1, [\arg_ptr]
32    str \tmp1, [\stack_ptr], #4
33    b \next_label
341:  // it is a 64bit value
35    ldm \arg_ptr, {\tmp1, \tmp2}
36    add \stack_ptr, \stack_ptr, #7 // round the address up to 8 byte boundary
37    bic \stack_ptr, \stack_ptr, #7
38    stm \stack_ptr!, {\tmp1, \tmp2}
39    b \next_label
40
412:  // the arg has type 'any'
42    add \stack_ptr, \stack_ptr, #7 // round the address up to 8 byte boundary
43    bic \stack_ptr, \stack_ptr, #7
44    // copy value
45    ldr \tmp2, [\arg_ptr], #4
46    str \tmp2, [\stack_ptr], #4
47    ldr \tmp2, [\arg_ptr], #4
48    str \tmp2, [\stack_ptr], #4
49    // copy tag
50    ldm \arg_ptr, {\tmp1, \tmp2}
51    stm \stack_ptr, {\tmp1, \tmp2}
52    b \next_label
53.endm
54
55.macro LOAD_ARGS begin_ptr, end_ptr
56    ldr r0, [\begin_ptr], #4
57    cmp \begin_ptr, \end_ptr
58    beq 1f
59    ldr r1, [\begin_ptr], #4
60    cmp \begin_ptr, \end_ptr
61    beq 1f
62    ldr r2, [\begin_ptr], #4
63    cmp \begin_ptr, \end_ptr
64    beq 1f
65    ldr r3, [\begin_ptr], #4
661:
67    bic sp, sp, #7 // round downd sp to 8byte boundary
68.endm
69
70// The procedure reserves stack space for the arguments
71// Input:
72// r0 - SHORTY_PTR_REG
73// r1 - SHORTY_REG
74// r2 - shorty value (no initialization needed)
75// r7 - method
76// The procedure musn't use other registers
77PrepareArgStack:
78    // check result type
79    NEXT_SHORTY r2
80    cmp r2, #SHORTY_TAGGED
81    subeq sp, sp, #4 // r0 contains a pointer to the space to which the result will be stored
82
83    sub sp, sp, #4 // space for Method
84
85    // parameter 'this' of instance methods is not encoded in the shorty
86    ldr r2, [r7, #METHOD_ACCESS_FLAGS_OFFSET]
87    tst r2, #ACCESS_STATIC
88    subeq sp, sp, #4 // it is an instance method
89
90.Lloop_shorty:
91    NEXT_SHORTY r2
92    cmp r2, #0
93    beq .Lexit
94
95    cmp r2, #SHORTY_TAGGED
96    beq 1f
97
98    sub r2, r2, #SHORTY_FIRST_64
99    cmp r2, #(SHORTY_NUM_64BIT_TYPES - 1)
100    // it is a 32bit value
101    subhi sp, sp, #4
102    // it is a 64bit value
103    // align arg slot
104    bicls sp, sp, #7
105    subls sp, sp, #8
106    b .Lloop_shorty
107
1081:  // argument has type 'any'
109    bic sp, sp, #7
110    sub sp, sp, #16
111    b .Lloop_shorty
112.Lexit:
113    bic sp, sp, #7 // round downd sp to 8byte boundary
114    mov pc, lr
115
116// void InterpreterToCompiledCodeBridge(const BytecodeInstruction* insn, const Frame *iframe, const Method *method, ManagedThread* thread)
117.global InterpreterToCompiledCodeBridge
118.type InterpreterToCompiledCodeBridge, %function
119InterpreterToCompiledCodeBridge:
120    CFI_STARTPROC
121    CFI_DEF_CFA(sp, 0)
122    push {r1, lr}
123    CFI_ADJUST_CFA_OFFSET(8)
124    CFI_REL_OFFSET(lr, 4)
125
126    sub sp, sp, #12
127    CFI_ADJUST_CFA_OFFSET(12)
128
129    stm sp, {THREAD_REG, fp}
130    CFI_REL_OFFSET(fp, 4)
131    CFI_REL_OFFSET(THREAD_REG, 0)
132    add fp, sp, #12
133    CFI_ADJUST_CFA_OFFSET(-12)
134    CFI_DEF_CFA_REGISTER(fp)
135
136    mov THREAD_REG, r3
137
138    // According to the current frame kind set the bridge type
139    ldrb r3, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET]
140    cmp r3, #0
141    moveq r3, #INTERPRETER_TO_COMPILED_CODE_BRIDGE
142    movne r3, #BYPASS_BRIDGE
143
144    str r3, [sp, #8]
145    push {r4, r5, r6, r7, r8, r9}
146    CFI_REL_OFFSET(r9,  -((3 + 1) * 4))
147    CFI_REL_OFFSET(r8,  -((3 + 2) * 4))
148    CFI_REL_OFFSET(r7,  -((3 + 3) * 4))
149    CFI_REL_OFFSET(r6,  -((3 + 4) * 4))
150    CFI_REL_OFFSET(r5,  -((3 + 5) * 4))
151    CFI_REL_OFFSET(r4,  -((3 + 6) * 4))
152    CFI_REL_OFFSET(r3,  -((3 + 7) * 4))
153    sub sp, sp, #4
154    // sp should be 8 byte aligned
155
156    // save regs to survive call of PrepareArgStack
157    // r4 - insn_ptr, r5 - iframe, r6 - method.shorty, r7 - method
158    mov r4, r0
159    mov r5, r1
160    ldr r6, [r2, #METHOD_SHORTY_OFFSET]
161    mov r7, r2
162    mov SHORTY_PTR_REG, r6
163    INIT_SHORTY_REG
164
165    bl PrepareArgStack
166
167    // setup regs as follow
168    // r0 - SHORTY_PTR_REG, r1 - SHORTY_REG, r2 - shorty value, r3 - insn, r4 - insn_ptr,
169    // r5 - iframe, r6, r7 and r9 - temps, r8 - pointer to stack, lr - method
170    mov SHORTY_PTR_REG, r6
171    INIT_SHORTY_REG
172    mov r8, sp
173    mov lr, r7
174
175    // handle the return type
176    NEXT_SHORTY r2
177    cmp r2, #SHORTY_TAGGED
178    // the return type is any
179    // the first arg is the pointer to the caller frame's acc
180    addeq r2, r5, #FRAME_ACC_OFFSET
181    streq r2, [r8], #4
182
183    str lr, [r8], #4 // push method to the stack
184
185    // parameter 'this' of instance methods is not encoded in the shorty
186    // in case of instance method hack SHORTY_REG by replacing the return type by REF
187    // in the another case just skip the return type
188    ldr r2, [lr, #METHOD_ACCESS_FLAGS_OFFSET]
189    tst r2, #ACCESS_STATIC
190    // it is an instance method
191    lsleq SHORTY_REG, SHORTY_REG, #4 // unshift shorty reg
192    orreq SHORTY_REG, SHORTY_REG, #SHORTY_REFERENCE
193
194    // setup r5 as follow
195    // r5 - iframe.vregs
196    add r5, r5, #FRAME_VREGS_OFFSET
197    ldrb r6, [r4], #1 // read opcode and advance insn_ptr
198
199    // The file contains code which checks opcode and jumps
200    // to the corresponding handler.
201    // At the end each handler jumps to .Linvoke_from_bridge label.
202    // The file is autogenerated from runtime/templates/bridge_dispatch.S.erb
203    // Handlers are distinguished by format and located in the corresponding files with name:
204    // handle_call_<format>.S
205    // If you get a compilation error that there is no such file it seems
206    // new call format was introduced and you have to implement the corresponding handler.
207#include "bridge_dispatch_arm.S"
208
209.Linvoke_from_bridge:
210    LOAD_ARGS sp, r8
211
212    ldr r4, [lr, #METHOD_SHORTY_OFFSET] // load Method.shorty_ into r4 to survive the call
213    ldr lr, [lr, #METHOD_COMPILED_ENTRY_POINT_OFFSET]
214    blx lr
215
216    // handle the result
217    // setup registers as follow
218    // r0, r1 - result, r2 - shorty[0] & 0xF, r3 - frame.acc, r4- temp
219    ldrb r2, [r4]
220    and r2, r2, #0xF
221
222    cmp r2, #SHORTY_VOID
223    cmpne r2, #SHORTY_TAGGED
224    beq .Lreturn
225    ldr r3, [fp]
226    add r3, r3, #FRAME_ACC_OFFSET
227    // store tag
228    cmp r2, #SHORTY_REFERENCE
229    moveq r4, #1
230    movne r4, #0
231    str r4, [r3, #FRAME_ACC_MIRROR_OFFSET]
232    streq r0, [r3]
233    beq .Lreturn
234    cmp r2, #SHORTY_FIRST_64
235    // u64, i64, f64
236    stmge r3, {r0, r1}
237    bge .Lreturn
238    cmp r2, #SHORTY_FIRST_32
239    bge .L32
240    cmp r2, #SHORTY_I16
241    beq .LI16
242    bpl .LU16
243    cmp r2, #SHORTY_I8
244    beq .LI8
245    uxtb r0, r0
246    b .L32
247.LI8:
248    sxtb r0, r0
249    b .L32
250.LI16:
251    sxth r0, r0
252    b .L32
253.LU16:
254    uxth r0, r0
255.L32:
256    str r0, [r3]
257.Lreturn:
258    // Signal handler of the sampling profiler use stack space below sp,
259    // so change it carefully only after registers restoration
260    sub sp, fp, #36
261    pop {r4, r5, r6, r7, r8, r9, THREAD_REG, fp}
262    CFI_RESTORE(r4)
263    CFI_RESTORE(r5)
264    CFI_RESTORE(r6)
265    CFI_RESTORE(r7)
266    CFI_RESTORE(r8)
267    CFI_RESTORE(r9)
268    CFI_RESTORE(THREAD_REG)
269    CFI_RESTORE(fp)
270    CFI_DEF_CFA(sp, 12)
271    ldr lr, [sp, #8]
272    CFI_RESTORE(lr)
273    add sp, sp, #12
274    CFI_ADJUST_CFA_OFFSET(-12)
275    bx lr
276    CFI_ENDPROC
277
278// uint64_t InvokeCompiledCodeWithArguments(const int64_t* args, const Frame *iframe, const Method *method, ManagedThread* thread)
279.global InvokeCompiledCodeWithArgArray
280.type InvokeCompiledCodeWithArgArray, %function
281InvokeCompiledCodeWithArgArray:
282    // r0 - args, r1 - iframe, r2 - method, r3 - thread
283    CFI_STARTPROC
284    CFI_DEF_CFA(sp, 0)
285
286    push {r1, lr}
287    CFI_ADJUST_CFA_OFFSET(8)
288    CFI_REL_OFFSET(lr, 4)
289
290    sub sp, sp, #12
291    CFI_ADJUST_CFA_OFFSET(12)
292
293    stm sp, {THREAD_REG, fp}
294    CFI_REL_OFFSET(fp, 4)
295    CFI_REL_OFFSET(THREAD_REG, 0)
296
297    add fp, sp, #12
298    CFI_DEF_CFA_REGISTER(fp)
299    CFI_ADJUST_CFA_OFFSET(-12)
300
301    mov THREAD_REG, r3
302
303    // According to the current frame kind set the bridge type
304    ldrb r1, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET]
305    cmp r1, #0
306    moveq r1, #INTERPRETER_TO_COMPILED_CODE_BRIDGE
307    movne r1, #BYPASS_BRIDGE
308    str r1, [sp, #8]
309    push {r4, r5, r6, r7, r8}
310    CFI_REL_OFFSET(r8, -(4 * 4))
311    CFI_REL_OFFSET(r7, -(5 * 4))
312    CFI_REL_OFFSET(r6, -(6 * 4))
313    CFI_REL_OFFSET(r5, -(7 * 4))
314    CFI_REL_OFFSET(r4, -(8 * 4))
315
316    // sp should be 8 bytes aligned
317
318    // setup regs as follow
319    // r4 - args, r6 - method.shorty, r7 - method
320    mov r4, r0
321    mov r7, r2
322    ldr r6, [r2, #METHOD_SHORTY_OFFSET]
323    mov SHORTY_PTR_REG, r6
324    INIT_SHORTY_REG
325
326    bl PrepareArgStack
327
328    // push arguments to the stack
329    // setup regs as follow
330    // r0 - SHORTY_PTR_REG, r1 - SHORTY_REG, r2 - shorty value, r3 - the pointer to the stack,
331    // r4 - args, r5 and r6 - temps, lr - method
332    mov SHORTY_PTR_REG, r6
333    INIT_SHORTY_REG
334    mov r3, sp
335    mov lr, r7
336
337    // handle the return type
338    NEXT_SHORTY r2
339
340    str lr, [r3], #4
341
342    // parameter 'this' of instance methods is not encoded in the shorty
343    // in case of instance method hack SHORTY_REG by replacing the return type by REF
344    // in the another case just skip the return type
345    ldr r2, [lr, #METHOD_ACCESS_FLAGS_OFFSET]
346    tst r2, #ACCESS_STATIC
347    // it is an instance method
348    lsleq SHORTY_REG, SHORTY_REG, #4 // unshift shorty reg
349    orreq SHORTY_REG, SHORTY_REG, #SHORTY_REFERENCE
350
351.Lloop_args_push:
352    NEXT_SHORTY r2
353    cmp r2, #0
354    beq .Lloopend_args_push
355
356    // handle the arg
357    mov r5, r4
358    add r4, r4, #8
359    PUSH_ARG r5, r3, r5, r6, .Lloop_args_push
360.Lloopend_args_push:
361    LOAD_ARGS sp, r3
362    // load shorty into r6 again
363    ldr r6, [lr, #METHOD_SHORTY_OFFSET]
364
365    ldr lr, [lr, #METHOD_COMPILED_ENTRY_POINT_OFFSET]
366    blx lr
367
368    // handle the result
369    // setup regs as follow
370    // r0,r1 - result, r2 - method.shorty[0] & 0xF
371    ldrb r2, [r6]
372    and r2, r2, #0xF
373    sub r3, r2, #SHORTY_FIRST_64
374    cmp r3, #(SHORTY_NUM_64BIT_TYPES - 1)
375    bls .Lreturn_ // the result type is a 64bit type
376    // the result type is a 32bit type
377    mov r1, #0 // set high 32 bits of 64bit value to 0
378    cmp r2, #SHORTY_FIRST_32
379    bge .Lreturn_
380    cmp r2, #SHORTY_I16
381    beq .LI16_
382    bpl .LU16_
383    cmp r2, #SHORTY_I8
384    beq .LI8_
385    uxtb r0, r0
386    b .Lreturn_
387.LI8_:
388    sxtb r0, r0
389    b .Lreturn_
390.LI16_:
391    sxth r0, r0
392    b .Lreturn_
393.LU16_:
394    uxth r0, r0
395
396.Lreturn_:
397    // Signal handler of the sampling profiler use stack space below sp,
398    // so change it carefully only after registers restoration
399    sub sp, fp, #32
400    pop {r4, r5, r6, r7, r8, THREAD_REG, fp}
401    CFI_RESTORE(fp)
402    CFI_RESTORE(THREAD_REG)
403    CFI_RESTORE(r8)
404    CFI_RESTORE(r7)
405    CFI_RESTORE(r6)
406    CFI_RESTORE(r5)
407    CFI_RESTORE(r4)
408    CFI_DEF_CFA(sp, 12)
409    ldr lr, [sp, #8]
410    CFI_RESTORE(lr)
411    add sp, sp, #12
412    CFI_ADJUST_CFA_OFFSET(-12)
413    bx lr
414    CFI_ENDPROC
415
416