• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "asm_support_riscv64.S"
18#include "interpreter/cfi_asm_support.h"
19
20
21// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding.
22//  Argument 0: a0: The context pointer for ExecuteSwitchImpl.
23//  Argument 1: a1: Pointer to the templated ExecuteSwitchImpl to call.
24//  Argument 2: a2: The value of DEX PC (memory address of the methods bytecode).
25ENTRY ExecuteSwitchImplAsm
26    INCREASE_FRAME 16
27    SAVE_GPR s1, 0
28    SAVE_GPR ra, 8
29
30    mv s1, a2   // s1 = DEX PC
31    CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* a0 */, 9 /* s1, a.k.a. x9 */, 0)
32    jalr a1     // Call the wrapped method.
33
34    RESTORE_GPR s1, 0
35    RESTORE_GPR ra, 8
36    DECREASE_FRAME 16
37    ret
38END ExecuteSwitchImplAsm
39
40
41.macro INVOKE_STUB_CREATE_FRAME
42    // Save ra, fp, xSELF (current thread) a4, a5 (they will be needed in the invoke stub return)
43    // and callee-save regs s3 - s5 that are clobbered here and in art_quick_invoke_(static_)_stub.
44    INCREASE_FRAME 48
45    SAVE_GPR fp,    (8*0)
46    SAVE_GPR xSELF, (8*1)
47    SAVE_GPR a4,    (8*2)
48    SAVE_GPR a5,    (8*3)
49    SAVE_GPR s3,    (8*4)
50    SAVE_GPR ra,    (8*5)
51
52    mv fp, sp  // save frame pointer
53    .cfi_def_cfa_register fp
54
55    addi t0, a2, (__SIZEOF_POINTER__ + 0xf) // Reserve space for ArtMethod*, arguments and
56    andi t0, t0, ~0xf                       // round up for 16-byte stack alignment.
57    sub  sp, sp, t0
58
59    mv xSELF, a3
60
61    // Copy arguments on stack (4 bytes per slot):
62    //   a1: source address
63    //   a2: arguments length
64    //   s3: destination address.
65
66    add s3, sp, 8  // destination address is bottom of the stack + 8 bytes for ArtMethod* (null)
67
68    beqz a2, 2f      // loop through 4-byte arguments from the last to the first
691:
70    addi a2, a2, -4
71    add  t0, a1, a2  // t0 is the source address of the next copied argument
72    lw   t1, (t0)    // t1 is the 4 bytes at address t0
73    add  t0, s3, a2  // t0 is the destination address of the next copied argument
74    sw   t1, (t0)    // save t1 at the destination address t0
75    bnez a2, 1b
762:
77    sd zero, (sp)  // Store null into ArtMethod* at bottom of frame.
78.endm
79
80
81.macro INVOKE_STUB_CALL_AND_RETURN
82    // Call the method.
83    ld   t0, ART_METHOD_QUICK_CODE_OFFSET_64(a0)
84    jalr t0
85
86    mv sp, fp  // restore frame pointer
87    .cfi_def_cfa_register sp
88
89    // Restore ra, fp, xSELF (current thread) a4 (shorty), a5 (result pointer) and callee-save
90    // regs s3 - s5 from stack.
91    RESTORE_GPR fp,    (8*0)
92    RESTORE_GPR xSELF, (8*1)
93    RESTORE_GPR a4,    (8*2)
94    RESTORE_GPR a5,    (8*3)
95    RESTORE_GPR s3,    (8*4)
96    RESTORE_GPR ra,    (8*5)
97    DECREASE_FRAME 48
98
99    // Load result type (1-byte symbol) from a5.
100    // Check result type and store the correct register into the jvalue in memory at a4 address.
101    lbu t0, (a5)
102
103    li t1, 'V'  // void (do not store result at all)
104    beq t1, t0, 1f
105
106    li t1, 'D'  // double
107    beq t1, t0, 2f
108
109    li t1, 'F'  // float
110    beq t1, t0, 3f
111
112    // Otherwise, result is in a0 (either 8 or 4 bytes, but it is fine to store 8 bytes as the
113    // upper bytes in a0 in that case are zero, and jvalue has enough space).
114    sd a0, (a4)
1151:
116    ret
117
1182:  // double: result in fa0 (8 bytes)
119    fsd fa0, (a4)
120    ret
121
1223:  // float: result in fa0 (4 bytes)
123    fsw fa0, (a4)
124    ret
125.endm
126
127
128ENTRY art_deliver_pending_exception
129    DELIVER_PENDING_EXCEPTION
130END art_deliver_pending_exception
131
132
133// Macros for loading an argument into a register.
134//  label - the base name of the label of the load routine,
135//  reg - the register to load,
136//  args - pointer to current argument, incremented by size,
137//  size - the size of the register - 4 or 8 bytes,
138//  load - instruction used for loading,
139//  nh4_reg - the register to fill with the address of the next handler for 4-byte values,
140//  nh4_l - the base name of the label of the next handler for 4-byte values,
141//  nh8_reg - the register to fill with the address of the next handler for 8-byte values,
142//  nh8_l - the base name of the label of the next handler for 8-byte values,
143//  cont - the base name of the label for continuing the shorty processing loop,
144//  sfx - suffix added to all labels to make labels unique for different users.
145.macro INVOKE_STUB_LOAD_REG label, reg, args, size, load, nh4_reg, nh4_l, nh8_reg, nh8_l, cont, sfx
146\label\sfx:
147    \load \reg, (\args)
148    addi  \args, \args, \size
149    la    \nh4_reg, \nh4_l\sfx
150    la    \nh8_reg, \nh8_l\sfx
151    j     \cont\sfx
152.endm
153
154
155// Macro for skipping an argument that does not fit into argument registers.
156//  label - the base name of the label of the skip routine,
157//  args - pointer to current argument, incremented by size,
158//  size - the size of the argument - 4 or 8 bytes,
159//  cont - the base name of the label for continuing the shorty processing loop,
160//  sfx - suffix added to all labels to make labels unique for different users.
161.macro INVOKE_STUB_SKIP_ARG label, args, size, cont, sfx
162\label\sfx:
163    addi \args, \args, \size
164    j    \cont\sfx
165.endm
166
167
168// Fill registers a1 to a7 and fa0 to fa7 with parameters.
169// Parse the passed shorty to determine which register to load.
170//  a5 - shorty,
171//  s3 - points to arguments on the stack,
172//  sfx - suffix added to all labels to make labels unique for different users.
173.macro INVOKE_STUB_LOAD_ALL_ARGS sfx
174    mv   t0, a5                        // Load shorty address,
175    addi t0, t0, 1                     // plus one to skip the return type.
176
177    // Load this (if instance method) and addresses for routines that load argument GPRs and FPRs.
178    .ifc \sfx, _instance
179        lw   a1, (s3)                  // Load "this" parameter,
180        addi s3, s3, 4                 // and increment arg pointer.
181        la   t3, .Lload4i2\sfx
182        la   t4, .Lload8i2\sfx
183    .else
184        la   t3, .Lload4i1\sfx
185        la   t4, .Lload8i1\sfx
186    .endif
187    la   t5, .Lload4f0\sfx
188    la   t6, .Lload8f0\sfx
189
190    // Loop to fill registers.
191.Lfill_regs\sfx:
192    lb   t1, (t0)                      // Load next character in signature, and increment.
193    addi t0, t0, 1                     // and increment.
194    beqz t1, .Lcall_method\sfx         // Exit at end of signature. Shorty 0 terminated.
195
196    li   t2, 'J'
197    beq  t1, t2, .Lload_long\sfx       // Is this a long?
198
199    li   t2, 'F'
200    beq  t1, t2, .Lload_float\sfx      // Is this a float?
201
202    li   t2, 'D'
203    beq  t1, t2, .Lload_double\sfx     // Is this a double?
204
205    // Everything else uses a 4-byte GPR.
206    jr   t3
207
208.Lload_long\sfx:
209    jr   t4
210
211.Lload_float\sfx:
212    jr   t5
213
214.Lload_double\sfx:
215    jr   t6
216
217// Handlers for loading other args (not float/double/long) into 4-byte GPRs.
218    .ifnc \sfx, _instance
219        INVOKE_STUB_LOAD_REG \
220            .Lload4i1, a1, s3, 4, lw, t3, .Lload4i2, t4, .Lload8i2, .Lfill_regs, \sfx
221    .endif
222    INVOKE_STUB_LOAD_REG .Lload4i2, a2, s3, 4, lw, t3, .Lload4i3, t4, .Lload8i3, .Lfill_regs, \sfx
223    INVOKE_STUB_LOAD_REG .Lload4i3, a3, s3, 4, lw, t3, .Lload4i4, t4, .Lload8i4, .Lfill_regs, \sfx
224    INVOKE_STUB_LOAD_REG .Lload4i4, a4, s3, 4, lw, t3, .Lload4i5, t4, .Lload8i5, .Lfill_regs, \sfx
225    INVOKE_STUB_LOAD_REG .Lload4i5, a5, s3, 4, lw, t3, .Lload4i6, t4, .Lload8i6, .Lfill_regs, \sfx
226    INVOKE_STUB_LOAD_REG .Lload4i6, a6, s3, 4, lw, t3, .Lload4i7, t4, .Lload8i7, .Lfill_regs, \sfx
227    INVOKE_STUB_LOAD_REG .Lload4i7, a7, s3, 4, lw, t3, .Lskip4, t4, .Lskip8, .Lfill_regs, \sfx
228
229// Handlers for loading longs into 8-byte GPRs.
230    .ifnc \sfx, _instance
231        INVOKE_STUB_LOAD_REG \
232            .Lload8i1, a1, s3, 8, ld, t3, .Lload4i2, t4, .Lload8i2, .Lfill_regs, \sfx
233    .endif
234    INVOKE_STUB_LOAD_REG .Lload8i2, a2, s3, 8, ld, t3, .Lload4i3, t4, .Lload8i3, .Lfill_regs, \sfx
235    INVOKE_STUB_LOAD_REG .Lload8i3, a3, s3, 8, ld, t3, .Lload4i4, t4, .Lload8i4, .Lfill_regs, \sfx
236    INVOKE_STUB_LOAD_REG .Lload8i4, a4, s3, 8, ld, t3, .Lload4i5, t4, .Lload8i5, .Lfill_regs, \sfx
237    INVOKE_STUB_LOAD_REG .Lload8i5, a5, s3, 8, ld, t3, .Lload4i6, t4, .Lload8i6, .Lfill_regs, \sfx
238    INVOKE_STUB_LOAD_REG .Lload8i6, a6, s3, 8, ld, t3, .Lload4i7, t4, .Lload8i7, .Lfill_regs, \sfx
239    INVOKE_STUB_LOAD_REG .Lload8i7, a7, s3, 8, ld, t3, .Lskip4, t4, .Lskip8, .Lfill_regs, \sfx
240
241// Handlers for loading floats into FPRs.
242    INVOKE_STUB_LOAD_REG .Lload4f0, fa0, s3, 4, flw, t5, .Lload4f1, t6, .Lload8f1, .Lfill_regs, \sfx
243    INVOKE_STUB_LOAD_REG .Lload4f1, fa1, s3, 4, flw, t5, .Lload4f2, t6, .Lload8f2, .Lfill_regs, \sfx
244    INVOKE_STUB_LOAD_REG .Lload4f2, fa2, s3, 4, flw, t5, .Lload4f3, t6, .Lload8f3, .Lfill_regs, \sfx
245    INVOKE_STUB_LOAD_REG .Lload4f3, fa3, s3, 4, flw, t5, .Lload4f4, t6, .Lload8f4, .Lfill_regs, \sfx
246    INVOKE_STUB_LOAD_REG .Lload4f4, fa4, s3, 4, flw, t5, .Lload4f5, t6, .Lload8f5, .Lfill_regs, \sfx
247    INVOKE_STUB_LOAD_REG .Lload4f5, fa5, s3, 4, flw, t5, .Lload4f6, t6, .Lload8f6, .Lfill_regs, \sfx
248    INVOKE_STUB_LOAD_REG .Lload4f6, fa6, s3, 4, flw, t5, .Lload4f7, t6, .Lload8f7, .Lfill_regs, \sfx
249    INVOKE_STUB_LOAD_REG .Lload4f7, fa7, s3, 4, flw, t5, .Lskip4, t6, .Lskip8, .Lfill_regs, \sfx
250
251// Handlers for loading doubles into FPRs.
252    INVOKE_STUB_LOAD_REG .Lload8f0, fa0, s3, 8, fld, t5, .Lload4f1, t6, .Lload8f1, .Lfill_regs, \sfx
253    INVOKE_STUB_LOAD_REG .Lload8f1, fa1, s3, 8, fld, t5, .Lload4f2, t6, .Lload8f2, .Lfill_regs, \sfx
254    INVOKE_STUB_LOAD_REG .Lload8f2, fa2, s3, 8, fld, t5, .Lload4f3, t6, .Lload8f3, .Lfill_regs, \sfx
255    INVOKE_STUB_LOAD_REG .Lload8f3, fa3, s3, 8, fld, t5, .Lload4f4, t6, .Lload8f4, .Lfill_regs, \sfx
256    INVOKE_STUB_LOAD_REG .Lload8f4, fa4, s3, 8, fld, t5, .Lload4f5, t6, .Lload8f5, .Lfill_regs, \sfx
257    INVOKE_STUB_LOAD_REG .Lload8f5, fa5, s3, 8, fld, t5, .Lload4f6, t6, .Lload8f6, .Lfill_regs, \sfx
258    INVOKE_STUB_LOAD_REG .Lload8f6, fa6, s3, 8, fld, t5, .Lload4f7, t6, .Lload8f7, .Lfill_regs, \sfx
259    INVOKE_STUB_LOAD_REG .Lload8f7, fa7, s3, 8, fld, t5, .Lskip4, t6, .Lskip8, .Lfill_regs, \sfx
260
261// Handlers for skipping arguments that do not fit into registers.
262    INVOKE_STUB_SKIP_ARG .Lskip4, s3, 4, .Lfill_regs, \sfx
263    INVOKE_STUB_SKIP_ARG .Lskip8, s3, 8, .Lfill_regs, \sfx
264
265.Lcall_method\sfx:
266.endm
267
268
269// void art_quick_invoke_stub(ArtMethod* method,   // a0
270//                            uint32_t*  args,     // a1
271//                            uint32_t   argsize,  // a2
272//                            Thread*    self,     // a3
273//                            JValue*    result,   // a4
274//                            char*      shorty)   // a5
275ENTRY art_quick_invoke_stub
276    INVOKE_STUB_CREATE_FRAME
277
278    // Load args into registers.
279    INVOKE_STUB_LOAD_ALL_ARGS _instance
280
281    // Call the method and return.
282    INVOKE_STUB_CALL_AND_RETURN
283END art_quick_invoke_stub
284
285
286// void art_quick_invoke_static_stub(ArtMethod* method,   // a0
287//                                   uint32_t*  args,     // a1
288//                                   uint32_t   argsize,  // a2
289//                                   Thread*    self,     // a3
290//                                   JValue*    result,   // a4
291//                                   char*      shorty)   // a5
292ENTRY art_quick_invoke_static_stub
293    INVOKE_STUB_CREATE_FRAME
294
295    // Load args into registers.
296    INVOKE_STUB_LOAD_ALL_ARGS _static
297
298    // Call the method and return.
299    INVOKE_STUB_CALL_AND_RETURN
300END art_quick_invoke_static_stub
301
302
303ENTRY art_quick_generic_jni_trampoline
304    SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
305
306    // Save sp, so we can have static CFI info.
307    mv   fp, sp
308    .cfi_def_cfa_register fp
309
310    li   t0, GENERIC_JNI_TRAMPOLINE_RESERVED_AREA
311    sub  sp, sp, t0
312
313    mv   a0, xSELF    // Thread*
314    mv   a1, fp       // SP for the managed frame.
315    mv   a2, sp       // reserved area for arguments and other saved data (up to managed frame)
316    call artQuickGenericJniTrampoline
317
318    // Check for error (class init check or locking for synchronized native method can throw).
319    beqz a0, .Lexception_in_native
320
321    mv   t0, a0       // save pointer to native method code into temporary
322
323    // Load argument GPRs from stack (saved there by artQuickGenericJniTrampoline).
324    ld  a0, 8*0(sp)   // JniEnv* for the native method
325    ld  a1, 8*1(sp)
326    ld  a2, 8*2(sp)
327    ld  a3, 8*3(sp)
328    ld  a4, 8*4(sp)
329    ld  a5, 8*5(sp)
330    ld  a6, 8*6(sp)
331    ld  a7, 8*7(sp)
332
333    // Load argument FPRs from stack (saved there by artQuickGenericJniTrampoline).
334    fld  fa0, 8*8(sp)
335    fld  fa1, 8*9(sp)
336    fld  fa2, 8*10(sp)
337    fld  fa3, 8*11(sp)
338    fld  fa4, 8*12(sp)
339    fld  fa5, 8*13(sp)
340    fld  fa6, 8*14(sp)
341    fld  fa7, 8*15(sp)
342
343    ld  t6, 8*16(sp)  // @CriticalNative arg, used by art_jni_dlsym_lookup_critical_stub
344
345    ld  t1, 8*17(sp)  // restore stack
346    mv  sp, t1
347
348    jalr  t0  // call native method
349
350    // result sign extension is handled in C code, prepare for artQuickGenericJniEndTrampoline call:
351    // uint64_t artQuickGenericJniEndTrampoline(Thread* self,       // a0
352    //                                          jvalue result,      // a1 (need to move from a0)
353    //                                          uint64_t result_f)  // a2 (need to move from fa0)
354    mv  a1, a0
355    mv  a0, xSELF
356    fmv.x.d  a2, fa0
357    call artQuickGenericJniEndTrampoline
358
359    // Pending exceptions possible.
360    ld   t0, THREAD_EXCEPTION_OFFSET(xSELF)
361    bnez t0, .Lexception_in_native
362
363    // Tear down the alloca.
364    mv   sp, fp
365    .cfi_remember_state
366    .cfi_def_cfa_register sp
367
368    LOAD_RUNTIME_INSTANCE a1
369    lb   a1, RUN_EXIT_HOOKS_OFFSET_FROM_RUNTIME_INSTANCE(a1)
370    bnez a1, .Lcall_method_exit_hook
371
372.Lcall_method_exit_hook_done:
373    // This does not clobber the result register a0. a1 is not used for result as the managed code
374    // does not have a 128-bit type. Alternatively we could restore a subset of these registers.
375    RESTORE_SAVE_REFS_AND_ARGS_FRAME
376    fmv.d.x  fa0, a0
377    ret
378    CFI_RESTORE_STATE_AND_DEF_CFA sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
379
380.Lcall_method_exit_hook:
381    fmv.d.x  fa0, a0
382    li   a4, FRAME_SIZE_SAVE_REFS_AND_ARGS
383    jal  art_quick_method_exit_hook
384    j    .Lcall_method_exit_hook_done
385
386.Lexception_in_native:
387    // Move to a1 then sp to please assembler.
388    ld   a1, THREAD_TOP_QUICK_FRAME_OFFSET(xSELF)
389    addi sp, a1, -1  // Remove the GenericJNI tag.
390    call art_deliver_pending_exception
391END art_quick_generic_jni_trampoline
392
393
394ENTRY art_quick_to_interpreter_bridge
395    SETUP_SAVE_REFS_AND_ARGS_FRAME
396
397    // uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp)
398    // a0 will contain ArtMethod*
399    mv   a1, xSELF
400    mv   a2, sp
401    call artQuickToInterpreterBridge
402
403    // TODO: no need to restore arguments in this case.
404    RESTORE_SAVE_REFS_AND_ARGS_FRAME
405
406    fmv.d.x  fa0, a0  // copy the result to FP result register
407
408    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG t0
409END art_quick_to_interpreter_bridge
410
411
412    .extern artMethodExitHook
413ENTRY art_quick_method_exit_hook
414    SETUP_SAVE_EVERYTHING_FRAME
415
416    addi a3, sp, SAVE_EVERYTHING_FRAME_OFFSET_FA0  // FP result ptr in kSaveEverything frame
417    addi a2, sp, SAVE_EVERYTHING_FRAME_OFFSET_A0   // integer result ptr in kSaveEverything frame
418    addi a1, sp, FRAME_SIZE_SAVE_EVERYTHING        // ArtMethod**
419    mv   a0, xSELF                                 // Thread::Current
420    call artMethodExitHook                         // (Thread*, ArtMethod**, gpr_res*, fpr_res*,
421                                                   // frame_size)
422
423    // Normal return.
424    RESTORE_SAVE_EVERYTHING_FRAME
425    ret
426END art_quick_method_exit_hook
427
428
429// On entry a0 is uintptr_t* gprs_ and a1 is uint64_t* fprs_.
430// Both must reside on the stack, between current sp and target sp.
431ENTRY art_quick_do_long_jump
432    // Load FPRs
433    fld  ft0,  8*0(a1)   // f0
434    fld  ft1,  8*1(a1)   // f1
435    fld  ft2,  8*2(a1)   // f2
436    fld  ft3,  8*3(a1)   // f3
437    fld  ft4,  8*4(a1)   // f4
438    fld  ft5,  8*5(a1)   // f5
439    fld  ft6,  8*6(a1)   // f6
440    fld  ft7,  8*7(a1)   // f7
441    fld  fs0,  8*8(a1)   // f8
442    fld  fs1,  8*9(a1)   // f9
443    fld  fa0,  8*10(a1)  // f10
444    fld  fa1,  8*11(a1)  // f11
445    fld  fa2,  8*12(a1)  // f12
446    fld  fa3,  8*13(a1)  // f13
447    fld  fa4,  8*14(a1)  // f14
448    fld  fa5,  8*15(a1)  // f15
449    fld  fa6,  8*16(a1)  // f16
450    fld  fa7,  8*17(a1)  // f17
451    fld  fs2,  8*18(a1)  // f18
452    fld  fs3,  8*19(a1)  // f19
453    fld  fs4,  8*20(a1)  // f20
454    fld  fs5,  8*21(a1)  // f21
455    fld  fs6,  8*22(a1)  // f22
456    fld  fs7,  8*23(a1)  // f23
457    fld  fs8,  8*24(a1)  // f24
458    fld  fs9,  8*25(a1)  // f25
459    fld  fs10, 8*26(a1)  // f26
460    fld  fs11, 8*27(a1)  // f27
461    fld  ft8,  8*28(a1)  // f28
462    fld  ft9,  8*29(a1)  // f29
463    fld  ft10, 8*30(a1)  // f30
464    fld  ft11, 8*31(a1)  // f31
465
466    // Load GPRs.
467    // Skip slot 8*0(a0) for zero/x0 as it is hard-wired zero.
468    ld  ra,   8*1(a0)   // x1
469    // Skip slot 8*2(a0) for sp/x2 as it is set below.
470    // Skip slot 8*3(a0) for platform-specific thread pointer gp/x3.
471    // Skip slot 8*4(a0) for platform-specific global pointer tp/x4.
472    // Skip slot 8*5(a0) for t0/x5 as it is clobbered below.
473    // Skip slot 8*6(a0) for t1/x6 as it is clobbered below.
474    ld  t2,   8*7(a0)   // x7
475    ld  s0,   8*8(a0)   // x8
476    ld  s1,   8*9(a0)   // x9
477    // Delay loading a0 as the base is in a0.
478    ld  a1,   8*11(a0)  // x11
479    ld  a2,   8*12(a0)  // x12
480    ld  a3,   8*13(a0)  // x13
481    ld  a4,   8*14(a0)  // x14
482    ld  a5,   8*15(a0)  // x15
483    ld  a6,   8*16(a0)  // x16
484    ld  a7,   8*17(a0)  // x17
485    ld  s2,   8*18(a0)  // x18
486    ld  s3,   8*19(a0)  // x19
487    ld  s4,   8*20(a0)  // x20
488    ld  s5,   8*21(a0)  // x21
489    ld  s6,   8*22(a0)  // x22
490    ld  s7,   8*23(a0)  // x23
491    ld  s8,   8*24(a0)  // x24
492    ld  s9,   8*25(a0)  // x25
493    ld  s10,  8*26(a0)  // x26
494    ld  s11,  8*27(a0)  // x27
495    ld  t3,   8*28(a0)  // x28
496    ld  t4,   8*29(a0)  // x29
497    ld  t5,   8*30(a0)  // x30
498    ld  t6,   8*31(a0)  // x31
499
500    // Load sp to t0.
501    ld  t0, 8*2(a0)
502
503    // Load PC to t1, it is in the last stack slot.
504    ld  t1, 8*32(a0)
505
506    // Now load a0.
507    ld  a0, 8*10(a0)  // x10
508
509    // Set sp. Do not access fprs_ and gprs_ from now, they are below sp.
510    mv sp, t0
511
512    jr  t1
513END art_quick_do_long_jump
514
515
516// Called by managed code that is attempting to call a method on a proxy class. On entry a0 holds
517// the proxy method and a1 holds the receiver. The frame size of the invoked proxy method agrees
518// with kSaveRefsAndArgs frame.
519.extern artQuickProxyInvokeHandler
520ENTRY art_quick_proxy_invoke_handler
521    SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0
522
523    // uint64_t artQuickProxyInvokeHandler(ArtMethod* proxy_method,   // a0
524    //                                     mirror::Object* receiver,  // a1
525    //                                     Thread* self,              // a2
526    //                                     ArtMethod** sp)            // a3
527    mv    a2, xSELF                   // pass Thread::Current
528    mv    a3, sp                      // pass sp
529    call  artQuickProxyInvokeHandler  // (Method* proxy method, receiver, Thread*, sp)
530
531    ld    a2, THREAD_EXCEPTION_OFFSET(xSELF)
532    bnez  a2, .Lexception_in_proxy    // success if no exception is pending
533    .cfi_remember_state
534    RESTORE_SAVE_REFS_AND_ARGS_FRAME  // Restore frame
535    fmv.d.x  fa0, a0                  // Store result in fa0 in case it was float or double
536    ret                               // return on success
537
538.Lexception_in_proxy:
539    CFI_RESTORE_STATE_AND_DEF_CFA sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
540    RESTORE_SAVE_REFS_AND_ARGS_FRAME
541    DELIVER_PENDING_EXCEPTION
542END art_quick_proxy_invoke_handler
543
544
545.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
546.extern \cxx_name
547ENTRY \c_name
548    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context.
549    mv  a1, xSELF                     // pass Thread::Current.
550    jal \cxx_name                     // \cxx_name(arg, Thread*).
551    ebreak
552END \c_name
553.endm
554
555
556// Called to attempt to execute an obsolete method.
557ONE_ARG_RUNTIME_EXCEPTION art_invoke_obsolete_method_stub, artInvokeObsoleteMethod
558
559
560ENTRY art_quick_resolution_trampoline
561    SETUP_SAVE_REFS_AND_ARGS_FRAME
562
563    // const void* artQuickResolutionTrampoline(ArtMethod* called,         // a0
564    //                                          mirror::Object* receiver,  // a1
565    //                                          Thread* self,              // a2
566    //                                          ArtMethod** sp)            // a3
567    mv   a2, xSELF
568    mv   a3, sp
569    call artQuickResolutionTrampoline
570
571    beqz a0, 1f
572    .cfi_remember_state
573    mv   t0, a0    // Remember returned code pointer in t0.
574    ld   a0, (sp)  // artQuickResolutionTrampoline puts called method in *sp.
575
576    RESTORE_SAVE_REFS_AND_ARGS_FRAME
577    jr   t0
5781:
579    CFI_RESTORE_STATE_AND_DEF_CFA sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
580    RESTORE_SAVE_REFS_AND_ARGS_FRAME
581    DELIVER_PENDING_EXCEPTION
582END art_quick_resolution_trampoline
583
584
585UNDEFINED art_quick_imt_conflict_trampoline
586UNDEFINED art_quick_deoptimize_from_compiled_code
587UNDEFINED art_quick_string_builder_append
588UNDEFINED art_quick_compile_optimized
589UNDEFINED art_quick_method_entry_hook
590UNDEFINED art_quick_check_instance_of
591UNDEFINED art_quick_osr_stub
592
593UNDEFINED art_quick_alloc_array_resolved_dlmalloc
594UNDEFINED art_quick_alloc_array_resolved_dlmalloc_instrumented
595UNDEFINED art_quick_alloc_array_resolved8_dlmalloc
596UNDEFINED art_quick_alloc_array_resolved8_dlmalloc_instrumented
597UNDEFINED art_quick_alloc_array_resolved16_dlmalloc
598UNDEFINED art_quick_alloc_array_resolved16_dlmalloc_instrumented
599UNDEFINED art_quick_alloc_array_resolved32_dlmalloc
600UNDEFINED art_quick_alloc_array_resolved32_dlmalloc_instrumented
601UNDEFINED art_quick_alloc_array_resolved64_dlmalloc
602UNDEFINED art_quick_alloc_array_resolved64_dlmalloc_instrumented
603UNDEFINED art_quick_alloc_object_resolved_dlmalloc
604UNDEFINED art_quick_alloc_object_resolved_dlmalloc_instrumented
605UNDEFINED art_quick_alloc_object_initialized_dlmalloc
606UNDEFINED art_quick_alloc_object_initialized_dlmalloc_instrumented
607UNDEFINED art_quick_alloc_object_with_checks_dlmalloc
608UNDEFINED art_quick_alloc_object_with_checks_dlmalloc_instrumented
609UNDEFINED art_quick_alloc_string_object_dlmalloc
610UNDEFINED art_quick_alloc_string_object_dlmalloc_instrumented
611UNDEFINED art_quick_alloc_string_from_bytes_dlmalloc
612UNDEFINED art_quick_alloc_string_from_bytes_dlmalloc_instrumented
613UNDEFINED art_quick_alloc_string_from_chars_dlmalloc
614UNDEFINED art_quick_alloc_string_from_chars_dlmalloc_instrumented
615UNDEFINED art_quick_alloc_string_from_string_dlmalloc
616UNDEFINED art_quick_alloc_string_from_string_dlmalloc_instrumented
617UNDEFINED art_quick_alloc_array_resolved_rosalloc
618UNDEFINED art_quick_alloc_array_resolved_rosalloc_instrumented
619UNDEFINED art_quick_alloc_array_resolved8_rosalloc
620UNDEFINED art_quick_alloc_array_resolved8_rosalloc_instrumented
621UNDEFINED art_quick_alloc_array_resolved16_rosalloc
622UNDEFINED art_quick_alloc_array_resolved16_rosalloc_instrumented
623UNDEFINED art_quick_alloc_array_resolved32_rosalloc
624UNDEFINED art_quick_alloc_array_resolved32_rosalloc_instrumented
625UNDEFINED art_quick_alloc_array_resolved64_rosalloc
626UNDEFINED art_quick_alloc_array_resolved64_rosalloc_instrumented
627UNDEFINED art_quick_alloc_object_resolved_rosalloc
628UNDEFINED art_quick_alloc_object_resolved_rosalloc_instrumented
629UNDEFINED art_quick_alloc_object_initialized_rosalloc
630UNDEFINED art_quick_alloc_object_initialized_rosalloc_instrumented
631UNDEFINED art_quick_alloc_object_with_checks_rosalloc
632UNDEFINED art_quick_alloc_object_with_checks_rosalloc_instrumented
633UNDEFINED art_quick_alloc_string_object_rosalloc
634UNDEFINED art_quick_alloc_string_object_rosalloc_instrumented
635UNDEFINED art_quick_alloc_string_from_bytes_rosalloc
636UNDEFINED art_quick_alloc_string_from_bytes_rosalloc_instrumented
637UNDEFINED art_quick_alloc_string_from_chars_rosalloc
638UNDEFINED art_quick_alloc_string_from_chars_rosalloc_instrumented
639UNDEFINED art_quick_alloc_string_from_string_rosalloc
640UNDEFINED art_quick_alloc_string_from_string_rosalloc_instrumented
641UNDEFINED art_quick_alloc_array_resolved_bump_pointer
642UNDEFINED art_quick_alloc_array_resolved_bump_pointer_instrumented
643UNDEFINED art_quick_alloc_array_resolved8_bump_pointer
644UNDEFINED art_quick_alloc_array_resolved8_bump_pointer_instrumented
645UNDEFINED art_quick_alloc_array_resolved16_bump_pointer
646UNDEFINED art_quick_alloc_array_resolved16_bump_pointer_instrumented
647UNDEFINED art_quick_alloc_array_resolved32_bump_pointer
648UNDEFINED art_quick_alloc_array_resolved32_bump_pointer_instrumented
649UNDEFINED art_quick_alloc_array_resolved64_bump_pointer
650UNDEFINED art_quick_alloc_array_resolved64_bump_pointer_instrumented
651UNDEFINED art_quick_alloc_object_resolved_bump_pointer
652UNDEFINED art_quick_alloc_object_resolved_bump_pointer_instrumented
653UNDEFINED art_quick_alloc_object_initialized_bump_pointer
654UNDEFINED art_quick_alloc_object_initialized_bump_pointer_instrumented
655UNDEFINED art_quick_alloc_object_with_checks_bump_pointer
656UNDEFINED art_quick_alloc_object_with_checks_bump_pointer_instrumented
657UNDEFINED art_quick_alloc_string_object_bump_pointer
658UNDEFINED art_quick_alloc_string_object_bump_pointer_instrumented
659UNDEFINED art_quick_alloc_string_from_bytes_bump_pointer
660UNDEFINED art_quick_alloc_string_from_bytes_bump_pointer_instrumented
661UNDEFINED art_quick_alloc_string_from_chars_bump_pointer
662UNDEFINED art_quick_alloc_string_from_chars_bump_pointer_instrumented
663UNDEFINED art_quick_alloc_string_from_string_bump_pointer
664UNDEFINED art_quick_alloc_string_from_string_bump_pointer_instrumented
665UNDEFINED art_quick_alloc_array_resolved_tlab
666UNDEFINED art_quick_alloc_array_resolved_tlab_instrumented
667UNDEFINED art_quick_alloc_array_resolved8_tlab
668UNDEFINED art_quick_alloc_array_resolved8_tlab_instrumented
669UNDEFINED art_quick_alloc_array_resolved16_tlab
670UNDEFINED art_quick_alloc_array_resolved16_tlab_instrumented
671UNDEFINED art_quick_alloc_array_resolved32_tlab
672UNDEFINED art_quick_alloc_array_resolved32_tlab_instrumented
673UNDEFINED art_quick_alloc_array_resolved64_tlab
674UNDEFINED art_quick_alloc_array_resolved64_tlab_instrumented
675UNDEFINED art_quick_alloc_object_resolved_tlab
676UNDEFINED art_quick_alloc_object_resolved_tlab_instrumented
677UNDEFINED art_quick_alloc_object_initialized_tlab
678UNDEFINED art_quick_alloc_object_initialized_tlab_instrumented
679UNDEFINED art_quick_alloc_object_with_checks_tlab
680UNDEFINED art_quick_alloc_object_with_checks_tlab_instrumented
681UNDEFINED art_quick_alloc_string_object_tlab
682UNDEFINED art_quick_alloc_string_object_tlab_instrumented
683UNDEFINED art_quick_alloc_string_from_bytes_tlab
684UNDEFINED art_quick_alloc_string_from_bytes_tlab_instrumented
685UNDEFINED art_quick_alloc_string_from_chars_tlab
686UNDEFINED art_quick_alloc_string_from_chars_tlab_instrumented
687UNDEFINED art_quick_alloc_string_from_string_tlab
688UNDEFINED art_quick_alloc_string_from_string_tlab_instrumented
689UNDEFINED art_quick_alloc_array_resolved_region
690UNDEFINED art_quick_alloc_array_resolved_region_instrumented
691UNDEFINED art_quick_alloc_array_resolved8_region
692UNDEFINED art_quick_alloc_array_resolved8_region_instrumented
693UNDEFINED art_quick_alloc_array_resolved16_region
694UNDEFINED art_quick_alloc_array_resolved16_region_instrumented
695UNDEFINED art_quick_alloc_array_resolved32_region
696UNDEFINED art_quick_alloc_array_resolved32_region_instrumented
697UNDEFINED art_quick_alloc_array_resolved64_region
698UNDEFINED art_quick_alloc_array_resolved64_region_instrumented
699UNDEFINED art_quick_alloc_object_resolved_region
700UNDEFINED art_quick_alloc_object_resolved_region_instrumented
701UNDEFINED art_quick_alloc_object_initialized_region
702UNDEFINED art_quick_alloc_object_initialized_region_instrumented
703UNDEFINED art_quick_alloc_object_with_checks_region
704UNDEFINED art_quick_alloc_object_with_checks_region_instrumented
705UNDEFINED art_quick_alloc_string_object_region
706UNDEFINED art_quick_alloc_string_object_region_instrumented
707UNDEFINED art_quick_alloc_string_from_bytes_region
708UNDEFINED art_quick_alloc_string_from_bytes_region_instrumented
709UNDEFINED art_quick_alloc_string_from_chars_region
710UNDEFINED art_quick_alloc_string_from_chars_region_instrumented
711UNDEFINED art_quick_alloc_string_from_string_region
712UNDEFINED art_quick_alloc_string_from_string_region_instrumented
713UNDEFINED art_quick_alloc_array_resolved_region_tlab
714UNDEFINED art_quick_alloc_array_resolved_region_tlab_instrumented
715UNDEFINED art_quick_alloc_array_resolved8_region_tlab
716UNDEFINED art_quick_alloc_array_resolved8_region_tlab_instrumented
717UNDEFINED art_quick_alloc_array_resolved16_region_tlab
718UNDEFINED art_quick_alloc_array_resolved16_region_tlab_instrumented
719UNDEFINED art_quick_alloc_array_resolved32_region_tlab
720UNDEFINED art_quick_alloc_array_resolved32_region_tlab_instrumented
721UNDEFINED art_quick_alloc_array_resolved64_region_tlab
722UNDEFINED art_quick_alloc_array_resolved64_region_tlab_instrumented
723UNDEFINED art_quick_alloc_object_resolved_region_tlab
724UNDEFINED art_quick_alloc_object_resolved_region_tlab_instrumented
725UNDEFINED art_quick_alloc_object_initialized_region_tlab
726UNDEFINED art_quick_alloc_object_initialized_region_tlab_instrumented
727UNDEFINED art_quick_alloc_object_with_checks_region_tlab
728UNDEFINED art_quick_alloc_object_with_checks_region_tlab_instrumented
729UNDEFINED art_quick_alloc_string_object_region_tlab
730UNDEFINED art_quick_alloc_string_object_region_tlab_instrumented
731UNDEFINED art_quick_alloc_string_from_bytes_region_tlab
732UNDEFINED art_quick_alloc_string_from_bytes_region_tlab_instrumented
733UNDEFINED art_quick_alloc_string_from_chars_region_tlab
734UNDEFINED art_quick_alloc_string_from_chars_region_tlab_instrumented
735UNDEFINED art_quick_alloc_string_from_string_region_tlab
736UNDEFINED art_quick_alloc_string_from_string_region_tlab_instrumented
737UNDEFINED art_quick_initialize_static_storage
738UNDEFINED art_quick_resolve_type_and_verify_access
739UNDEFINED art_quick_resolve_type
740UNDEFINED art_quick_resolve_method_handle
741UNDEFINED art_quick_resolve_method_type
742UNDEFINED art_quick_resolve_string
743UNDEFINED art_quick_set8_instance
744UNDEFINED art_quick_set8_static
745UNDEFINED art_quick_set16_instance
746UNDEFINED art_quick_set16_static
747UNDEFINED art_quick_set32_instance
748UNDEFINED art_quick_set32_static
749UNDEFINED art_quick_set64_instance
750UNDEFINED art_quick_set64_static
751UNDEFINED art_quick_set_obj_instance
752UNDEFINED art_quick_set_obj_static
753UNDEFINED art_quick_get_byte_instance
754UNDEFINED art_quick_get_boolean_instance
755UNDEFINED art_quick_get_short_instance
756UNDEFINED art_quick_get_char_instance
757UNDEFINED art_quick_get32_instance
758UNDEFINED art_quick_get64_instance
759UNDEFINED art_quick_get_obj_instance
760UNDEFINED art_quick_get_byte_static
761UNDEFINED art_quick_get_boolean_static
762UNDEFINED art_quick_get_short_static
763UNDEFINED art_quick_get_char_static
764UNDEFINED art_quick_get32_static
765UNDEFINED art_quick_get64_static
766UNDEFINED art_quick_get_obj_static
767UNDEFINED art_quick_aput_obj
768UNDEFINED art_quick_lock_object_no_inline
769UNDEFINED art_quick_lock_object
770UNDEFINED art_quick_unlock_object_no_inline
771UNDEFINED art_quick_unlock_object
772UNDEFINED art_quick_invoke_direct_trampoline_with_access_check
773UNDEFINED art_quick_invoke_interface_trampoline_with_access_check
774UNDEFINED art_quick_invoke_static_trampoline_with_access_check
775UNDEFINED art_quick_invoke_super_trampoline_with_access_check
776UNDEFINED art_quick_invoke_virtual_trampoline_with_access_check
777UNDEFINED art_quick_invoke_polymorphic
778UNDEFINED art_quick_invoke_custom
779UNDEFINED art_quick_test_suspend
780UNDEFINED art_quick_deliver_exception
781UNDEFINED art_quick_throw_array_bounds
782UNDEFINED art_quick_throw_div_zero
783UNDEFINED art_quick_throw_null_pointer_exception
784UNDEFINED art_quick_throw_stack_overflow
785UNDEFINED art_quick_throw_string_bounds
786UNDEFINED art_quick_update_inline_cache
787UNDEFINED art_jni_monitored_method_start
788UNDEFINED art_jni_monitored_method_end
789UNDEFINED art_quick_indexof
790