• 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#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    sub sp, fp, #36
259    pop {r4, r5, r6, r7, r8, r9, THREAD_REG, fp}
260    CFI_RESTORE(r4)
261    CFI_RESTORE(r5)
262    CFI_RESTORE(r6)
263    CFI_RESTORE(r7)
264    CFI_RESTORE(r8)
265    CFI_RESTORE(r9)
266    CFI_RESTORE(THREAD_REG)
267    CFI_RESTORE(fp)
268    CFI_DEF_CFA(sp, 12)
269    add sp, sp, #12
270    CFI_ADJUST_CFA_OFFSET(-12)
271    ldr lr, [sp, #-4]
272    CFI_RESTORE(lr)
273    bx lr
274    CFI_ENDPROC
275
276// InvocationResult InvokeCompiledCodeWithArguments(const int64_t* args, const Frame *iframe, const Method *method, ManagedThread* thread)
277.global InvokeCompiledCodeWithArgArray
278.type InvokeCompiledCodeWithArgArray, %function
279InvokeCompiledCodeWithArgArray:
280    // Since Invocation result is 128bit structure the areguments are located here:
281    // r0 - pointer to memory where to store the result
282    // r1 - args, r2 - iframe, r3 - method, sp[0] - thread
283    CFI_STARTPROC
284    CFI_DEF_CFA(sp, 0)
285
286    push {r2, 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    ldr THREAD_REG, [fp, #8]
302
303    // According to the current frame kind set the bridge type
304    ldrb r2, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET]
305    cmp r2, #0
306    moveq r2, #INTERPRETER_TO_COMPILED_CODE_BRIDGE
307    movne r2, #BYPASS_BRIDGE
308    str r2, [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, r8 - pointer to memory where to store the result
320    mov r4, r1
321    mov r7, r3
322    ldr r6, [r3, #METHOD_SHORTY_OFFSET]
323    mov r8, r0
324    mov SHORTY_PTR_REG, r6
325    INIT_SHORTY_REG
326
327    bl PrepareArgStack
328
329    // push arguments to the stack
330    // setup regs as follow
331    // r0 - SHORTY_PTR_REG, r1 - SHORTY_REG, r2 - shorty value, r3 - the pointer to the stack,
332    // r4 - args, r5 and r6 - temps, lr - method
333    mov SHORTY_PTR_REG, r6
334    INIT_SHORTY_REG
335    mov r3, sp
336    mov lr, r7
337
338    // handle the return type
339    NEXT_SHORTY r2
340    cmp r2, #SHORTY_TAGGED
341    // the return type is any
342    // the first arg is the pointer to the result
343    streq r8, [r3], #4
344
345    str lr, [r3], #4
346
347    // parameter 'this' of instance methods is not encoded in the shorty
348    // in case of instance method hack SHORTY_REG by replacing the return type by REF
349    // in the another case just skip the return type
350    ldr r2, [lr, #METHOD_ACCESS_FLAGS_OFFSET]
351    tst r2, #ACCESS_STATIC
352    // it is an instance method
353    lsleq SHORTY_REG, SHORTY_REG, #4 // unshift shorty reg
354    orreq SHORTY_REG, SHORTY_REG, #SHORTY_REFERENCE
355
356.Lloop_args_push:
357    NEXT_SHORTY r2
358    cmp r2, #0
359    beq .Lloopend_args_push
360
361    // handle the arg
362    mov r5, r4
363    add r4, r4, #8
364    PUSH_ARG r5, r3, r5, r6, .Lloop_args_push
365.Lloopend_args_push:
366    LOAD_ARGS sp, r3
367    // load shorty into r6 again
368    ldr r6, [lr, #METHOD_SHORTY_OFFSET]
369
370    ldr lr, [lr, #METHOD_COMPILED_ENTRY_POINT_OFFSET]
371    blx lr
372
373    // handle the result
374    // setup regs as follow
375    // r0,r1 - result, r2 - method.shorty[0] & 0xF
376    ldrb r2, [r6]
377    and r2, r2, #0xF
378    cmp r2, #SHORTY_TAGGED
379    beq .Lreturn_
380    sub r3, r2, #SHORTY_FIRST_64
381    cmp r3, #(SHORTY_NUM_64BIT_TYPES - 1)
382    bls .Lstore_result // the result type is a 64bit type
383    // the result type is a 32bit type
384    mov r1, #0 // set high 32 bits of 64bit value to 0
385    cmp r2, #SHORTY_FIRST_32
386    bge .Lstore_result
387    cmp r2, #SHORTY_I16
388    beq .LI16_
389    bpl .LU16_
390    cmp r2, #SHORTY_I8
391    beq .LI8_
392    uxtb r0, r0
393    b .Lstore_result
394.LI8_:
395    sxtb r0, r0
396    b .Lstore_result
397.LI16_:
398    sxth r0, r0
399    b .Lstore_result
400.LU16_:
401    uxth r0, r0
402
403.Lstore_result:
404    // store the result r0,r1 into memory [r8]
405    stm r8!, {r0, r1}
406    // store tag
407    cmp r2, #SHORTY_REFERENCE
408    moveq r0, #1
409    movne r0, #0
410    mov r1, #0
411    stm r8, {r0, r1}
412
413.Lreturn_:
414    sub sp, fp, #32
415    pop {r4, r5, r6, r7, r8, THREAD_REG, fp}
416    CFI_RESTORE(fp)
417    CFI_RESTORE(THREAD_REG)
418    CFI_RESTORE(r8)
419    CFI_RESTORE(r7)
420    CFI_RESTORE(r6)
421    CFI_RESTORE(r5)
422    CFI_RESTORE(r4)
423    CFI_DEF_CFA(sp, 12)
424    add sp, sp, #12
425    CFI_ADJUST_CFA_OFFSET(-12)
426    ldr lr, [sp, #-4]
427    CFI_RESTORE(lr)
428    bx lr
429    CFI_ENDPROC
430
431