blob: 308227382dfa378f3850443a7df2229e3c4d7d79 [file] [log] [blame]
Stuart Monteithb95a5342014-03-12 13:32:32 +00001/*
2 * Copyright (C) 2014 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_arm64.S"
18
19#include "arch/quick_alloc_entrypoints.S"
20
21
22 /*
23 * Macro that sets up the callee save frame to conform with
24 * Runtime::CreateCalleeSaveMethod(kSaveAll)
25 */
26.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
27 adrp x9, :got:_ZN3art7Runtime9instance_E
28 ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E]
29
30 // Our registers aren't intermixed - just spill in order.
31 ldr x9,[x9] // x9 = & (art::Runtime * art::Runtime.instance_) .
32
33 // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs] .
34 ldr x9, [x9, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
35
36 sub sp, sp, #368
37 .cfi_adjust_cfa_offset 368
38
39 // FP args
40 stp d1, d2, [sp, #8]
41 stp d2, d3, [sp, #24]
42 stp d4, d5, [sp, #40]
43 stp d6, d7, [sp, #56]
44
45 // FP callee-saves
46 stp d8, d9, [sp, #72]
47 stp d10, d11, [sp, #88]
48 stp d12, d13, [sp, #104]
49 stp d14, d15, [sp, #120]
50
51 stp d16, d17, [sp, #136]
52 stp d18, d19, [sp, #152]
53 stp d20, d21, [sp, #168]
54 stp d22, d23, [sp, #184]
55 stp d24, d25, [sp, #200]
56 stp d26, d27, [sp, #216]
57 stp d28, d29, [sp, #232]
58 stp d30, d31, [sp, #248]
59
60
61 // Callee saved.
62 stp xSELF, x19, [sp, #264]
63 stp x20, x21, [sp, #280]
64 stp x22, x23, [sp, #296]
65 stp x24, x25, [sp, #312]
66 stp x26, x27, [sp, #328]
67 stp x28, xFP, [sp, #344] // Save FP.
68 str xLR, [sp, #360]
69
70 .cfi_offset x18,72
71 .cfi_offset x19,80
72 .cfi_offset x20,88
73 .cfi_offset x21,96
74 .cfi_offset x22,104
75 .cfi_offset x23,112
76 .cfi_offset x24,120
77 .cfi_offset x25,128
78 .cfi_offset x26,136
79 .cfi_offset x27,144
80 .cfi_offset x28,152
81 .cfi_offset x29,160
82 .cfi_offset x30,168
83
84 // Loads appropriate callee-save-method
85 str x9, [sp] // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
86
87.endm
88
89 /*
90 * Macro that sets up the callee save frame to conform with
91 * Runtime::CreateCalleeSaveMethod(kRefsOnly).
92 */
93.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
94 brk 0
95.endm
96
97.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
98 brk 0
99.endm
100
101.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
102 brk 0
103.endm
104
105
106.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
107 sub sp, sp, #304
108 .cfi_adjust_cfa_offset 304
109
110 stp d0, d1, [sp, #16]
111 stp d2, d3, [sp, #32]
112 stp d4, d5, [sp, #48]
113 stp d6, d7, [sp, #64]
114 stp d8, d9, [sp, #80]
115 stp d10, d11, [sp, #96]
116 stp d12, d13, [sp, #112]
117 stp d14, d15, [sp, #128]
118
119 stp x1, x2, [sp, #144]
120 stp x3, x4, [sp, #160]
121 stp x5, x6, [sp, #176]
122 stp x7, xSELF, [sp, #192]
123 stp x19, x20, [sp, #208]
124 stp x21, x22, [sp, #224]
125 stp x23, x24, [sp, #240]
126 stp x25, x26, [sp, #256]
127 stp x27, x28, [sp, #272]
128 stp xFP, xLR, [sp, #288]
129
130 .cfi_offset x1,144
131 .cfi_offset x2,152
132 .cfi_offset x3,160
133 .cfi_offset x4,168
134 .cfi_offset x5,176
135 .cfi_offset x6,184
136 .cfi_offset x7,192
137 .cfi_offset x18,200
138 .cfi_offset x19,208
139 .cfi_offset x20,216
140 .cfi_offset x21,224
141 .cfi_offset x22,232
142 .cfi_offset x23,240
143 .cfi_offset x24,248
144 .cfi_offset x25,256
145 .cfi_offset x26,264
146 .cfi_offset x27,272
147 .cfi_offset x28,280
148 .cfi_offset x29,288
149 .cfi_offset x30,296
150.endm
151
152 /*
153 * Macro that sets up the callee save frame to conform with
154 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs).
155 *
156 * TODO This is probably too conservative - saving FP & LR.
157 */
158.macro SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
159 adrp x9, :got:_ZN3art7Runtime9instance_E
160 ldr x9, [x9, #:got_lo12:_ZN3art7Runtime9instance_E]
161
162 // Our registers aren't intermixed - just spill in order.
163 ldr x9,[x9] // x9 = & (art::Runtime * art::Runtime.instance_) .
164
165 // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs] .
166 ldr x9, [x9, RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
167
168 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
169
170 str x9, [sp] // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
171.endm
172
173.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
174
175 ldp d0, d1, [sp, #16]
176 ldp d2, d3, [sp, #32]
177 ldp d4, d5, [sp, #48]
178 ldp d6, d7, [sp, #64]
179 ldp d8, d9, [sp, #80]
180 ldp d10, d11, [sp, #96]
181 ldp d12, d13, [sp, #112]
182 ldp d14, d15, [sp, #128]
183
184 // args.
185 ldp x1, x2, [sp, #144]
186 ldp x3, x4, [sp, #160]
187 ldp x5, x6, [sp, #176]
188 ldp x7, xSELF, [sp, #192]
189 ldp x19, x20, [sp, #208]
190 ldp x21, x22, [sp, #224]
191 ldp x23, x24, [sp, #240]
192 ldp x25, x26, [sp, #256]
193 ldp x27, x28, [sp, #272]
194 ldp xFP, xLR, [sp, #288]
195
196 add sp, sp, #304
197 .cfi_adjust_cfa_offset -304
198.endm
199
Andreas Gampee62a07e2014-03-26 14:53:21 -0700200.macro RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME_NO_D0
201
202 ldr d1, [sp, #24]
203 ldp d2, d3, [sp, #32]
204 ldp d4, d5, [sp, #48]
205 ldp d6, d7, [sp, #64]
206 ldp d8, d9, [sp, #80]
207 ldp d10, d11, [sp, #96]
208 ldp d12, d13, [sp, #112]
209 ldp d14, d15, [sp, #128]
210
211 // args.
212 ldp x1, x2, [sp, #144]
213 ldp x3, x4, [sp, #160]
214 ldp x5, x6, [sp, #176]
215 ldp x7, xSELF, [sp, #192]
216 ldp x19, x20, [sp, #208]
217 ldp x21, x22, [sp, #224]
218 ldp x23, x24, [sp, #240]
219 ldp x25, x26, [sp, #256]
220 ldp x27, x28, [sp, #272]
221 ldp xFP, xLR, [sp, #288]
222
223 add sp, sp, #304
224 .cfi_adjust_cfa_offset -304
225.endm
226
Stuart Monteithb95a5342014-03-12 13:32:32 +0000227.macro RETURN_IF_RESULT_IS_ZERO
228 brk 0
229.endm
230
231.macro RETURN_IF_RESULT_IS_NON_ZERO
232 brk 0
233.endm
234
235 /*
236 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
237 * exception is Thread::Current()->exception_
238 */
239.macro DELIVER_PENDING_EXCEPTION
240 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
241 mov x0, xSELF
242 mov x1, sp
243
244 // Point of no return.
245 b artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*, SP)
246 brk 0 // Unreached
247.endm
248
249.macro RETURN_OR_DELIVER_PENDING_EXCEPTION
250 ldr x9, [xSELF, # THREAD_EXCEPTION_OFFSET] // Get exception field.
251 cbnz x9, 1f
252 ret
2531:
254 DELIVER_PENDING_EXCEPTION
255.endm
256
257.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
258 .extern \cxx_name
259ENTRY \c_name
260 brk 0
261END \c_name
262.endm
263
264.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
265 .extern \cxx_name
266ENTRY \c_name
267 brk 0
268END \c_name
269.endm
270
271.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
272 .extern \cxx_name
273ENTRY \c_name
274 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
275 brk 0
276END \c_name
277.endm
278
279 /*
280 * Called by managed code, saves callee saves and then calls artThrowException
281 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
282 */
283ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
284
285 /*
286 * Called by managed code to create and deliver a NullPointerException.
287 */
288NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
289
290 /*
291 * Called by managed code to create and deliver an ArithmeticException.
292 */
293NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
294
295 /*
296 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
297 * index, arg2 holds limit.
298 */
299TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
300
301 /*
302 * Called by managed code to create and deliver a StackOverflowError.
303 */
304NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
305
306 /*
307 * Called by managed code to create and deliver a NoSuchMethodError.
308 */
309ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
310
311 /*
312 * TODO arm64 specifics need to be fleshed out.
313 * All generated callsites for interface invokes and invocation slow paths will load arguments
314 * as usual - except instead of loading x0 with the target Method*, x0 will contain
315 * the method_idx. This wrapper will save x1-x3, load the caller's Method*, align the
316 * stack and call the appropriate C helper.
317 * NOTE: "this" is first visible argument of the target, and so can be found in x1.
318 *
319 * The helper will attempt to locate the target and return a result in x0 consisting
320 * of the target Method* in x0 and method->code_ in x1.
321 *
322 * If unsuccessful, the helper will return NULL/NULL. There will be a pending exception in the
323 * thread and we branch to another stub to deliver it.
324 *
325 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
326 * pointing back to the original caller.
327 */
328.macro INVOKE_TRAMPOLINE c_name, cxx_name
329 .extern \cxx_name
330ENTRY \c_name
331 brk 0
332END \c_name
333.endm
334
335INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
336INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
337
338INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
339INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
340INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
341INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
342
343/*
344 * extern"C" void art_quick_invoke_stub(ArtMethod *method, x0
345 * uint32_t *args, x1
346 * uint32_t argsize, w2
347 * Thread *self, x3
348 * JValue *result, x4
349 * char *shorty); x5
350 * +----------------------+
351 * | |
352 * | C/C++ frame |
353 * | LR'' |
354 * | FP'' | <- SP'
355 * +----------------------+
356 * +----------------------+
357 * | SP' |
358 * | X5 |
359 * | X4 | Saved registers
360 * | LR' |
361 * | FP' | <- FP
362 * +----------------------+
363 * | uint32_t out[n-1] |
364 * | : : | Outs
365 * | uint32_t out[0] |
366 * | ArtMethod* NULL | <- SP
367 * +----------------------+
368 *
369 * Outgoing registers:
370 * x0 - Method*
371 * x1-x7 - integer parameters.
372 * d0-d7 - Floating point parameters.
373 * xSELF = self
374 * SP = & of ArtMethod*
375 * x1 = "this" pointer.
376 *
377 */
378ENTRY art_quick_invoke_stub
379 // Spill registers as per AACPS64 calling convention.
380
381SAVE_SIZE=5*8 // x4, x5, LR & FP saved.
382SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
383
384 mov x9, sp // Save stack pointer.
385
386 mov x10, xFP // Save frame pointer
387 .cfi_register x29,x10
388 add x11, x2, # SAVE_SIZE_AND_METHOD // calculate size of frame.
389
390 sub x11, sp, x11 // Calculate SP position - saves + ArtMethod* + args
391
392 and x11, x11, # ~0xf // Enforce 16 byte stack alignment.
393
394 sub xFP, x9, #SAVE_SIZE // Calculate new FP. Don't store here until SP moved.
395 .cfi_def_cfa_register x29
396
397 mov sp, x11 // set new SP.
398
399 str x9, [xFP, #32] // Save old stack pointer.
400
401 .cfi_offset x9, 32
402
403 stp x4, x5, [xFP, #16] // Save result and shorty addresses.
404
405 .cfi_offset x4, 16
406 .cfi_offset x5, 24
407
408 stp x10, xLR, [xFP] // Store lr & old fp @ fp
409
410 .cfi_offset x30, 0
411 .cfi_offset x10, 8
412
413 mov xSELF, x3 // Move thread pointer into SELF register.
414
415 // Copy arguments into stack frame.
416 // Use simple copy routine for now.
417 // 4 bytes per slot.
418 // X1 - source address
419 // W2 - args length
420 // X10 - destination address.
421 add x9, sp, #8 // Destination address is bottom of stack + NULL.
422
423 // w2 = argsize parameter.
424.LcopyParams:
425 cmp w2, #0
426 beq .LendCopyParams
427 sub w2, w2, #4 // Need 65536 bytes of range.
428 ldr w10, [x1, x2]
429 str w10, [x9, x2]
430
431 b .LcopyParams
432
433.LendCopyParams:
434
435 // Store NULL into Method* at bottom of frame.
436 str xzr, [sp]
437
438 // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
439 // Parse the passed shorty to determine which register to load.
440 // Load addresses for routines that load WXSD registers.
441 adr x11, .LstoreW2
442 adr x12, .LstoreX2
443 adr x13, .LstoreS0
444 adr x14, .LstoreD0
445
446 // Initialize routine offsets to 0 for integers and floats.
447 // x8 for integers, x15 for floating point.
448 mov x8, #0
449 mov x15, #0
450
451 add x10, x5, #1 // Load shorty address, plus one to skip return value.
452 ldr w1, [x9],#4 // Load "this" parameter, and increment arg pointer.
453
454 // Loop to fill registers.
455.LfillRegisters:
456 ldrb w17, [x10], #1 // Load next character in signature, and increment.
457 cbz w17, .LcallFunction // Exit at end of signature. Shorty 0 terminated.
458
459 cmp w17, #'F' // is this a float?
460 bne .LisDouble
461
462 cmp x15, # 8*12 // Skip this load if all registers full.
463 beq .LfillRegisters
464
465 add x17, x13, x15 // Calculate subroutine to jump to.
466 br x17
467
468.LisDouble:
469 cmp w17, #'D' // is this a double?
470 bne .LisLong
471
472 cmp x15, # 8*12 // Skip this load if all registers full.
473 beq .LfillRegisters
474
475
476 add x17, x14, x15 // Calculate subroutine to jump to.
477 br x17
478
479.LisLong:
480 cmp w17, #'J' // is this a long?
481 bne .LisOther
482
Andreas Gampe9de65ff2014-03-21 17:25:57 -0700483 cmp x8, # 6*12 // Skip this load if all registers full.
Stuart Monteithb95a5342014-03-12 13:32:32 +0000484 beq .LfillRegisters
485
486 add x17, x12, x8 // Calculate subroutine to jump to.
487 br x17
488
489
490.LisOther: // Everything else takes one vReg.
Andreas Gampe9de65ff2014-03-21 17:25:57 -0700491 cmp x8, # 6*12 // Skip this load if all registers full.
Stuart Monteithb95a5342014-03-12 13:32:32 +0000492 beq .LfillRegisters
493 add x17, x11, x8 // Calculate subroutine to jump to.
494 br x17
495
496// Macro for loading a parameter into a register.
497// counter - the register with offset into these tables
498// size - the size of the register - 4 or 8 bytes.
499// register - the name of the register to be loaded.
500.macro LOADREG counter size register return
501 ldr \register , [x9], #\size
502 add \counter, \counter, 12
503 b \return
504.endm
505
506// Store ints.
507.LstoreW2:
508 LOADREG x8 4 w2 .LfillRegisters
509 LOADREG x8 4 w3 .LfillRegisters
510 LOADREG x8 4 w4 .LfillRegisters
511 LOADREG x8 4 w5 .LfillRegisters
512 LOADREG x8 4 w6 .LfillRegisters
513 LOADREG x8 4 w7 .LfillRegisters
514
515// Store longs.
516.LstoreX2:
517 LOADREG x8 8 x2 .LfillRegisters
518 LOADREG x8 8 x3 .LfillRegisters
519 LOADREG x8 8 x4 .LfillRegisters
520 LOADREG x8 8 x5 .LfillRegisters
521 LOADREG x8 8 x6 .LfillRegisters
522 LOADREG x8 8 x7 .LfillRegisters
523
524// Store singles.
525.LstoreS0:
526 LOADREG x15 4 s0 .LfillRegisters
527 LOADREG x15 4 s1 .LfillRegisters
528 LOADREG x15 4 s2 .LfillRegisters
529 LOADREG x15 4 s3 .LfillRegisters
530 LOADREG x15 4 s4 .LfillRegisters
531 LOADREG x15 4 s5 .LfillRegisters
532 LOADREG x15 4 s6 .LfillRegisters
533 LOADREG x15 4 s7 .LfillRegisters
534
535// Store doubles.
536.LstoreD0:
537 LOADREG x15 8 d0 .LfillRegisters
538 LOADREG x15 8 d1 .LfillRegisters
539 LOADREG x15 8 d2 .LfillRegisters
540 LOADREG x15 8 d3 .LfillRegisters
541 LOADREG x15 8 d4 .LfillRegisters
542 LOADREG x15 8 d5 .LfillRegisters
543 LOADREG x15 8 d6 .LfillRegisters
544 LOADREG x15 8 d7 .LfillRegisters
545
546
547.LcallFunction:
548
549 // load method-> METHOD_QUICK_CODE_OFFSET
550 ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET]
551 // Branch to method.
552 blr x9
553
554 // Restore return value address and shorty address.
555 ldp x4,x5, [xFP, #16]
556 .cfi_restore x4
557 .cfi_restore x5
558
559 // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
560 ldrb w10, [x5]
561
562 // Don't set anything for a void type.
563 cmp w10, #'V'
564 beq .Lexit_art_quick_invoke_stub
565
566 cmp w10, #'D'
567 bne .Lreturn_is_float
568 str d0, [x4]
569 b .Lexit_art_quick_invoke_stub
570
571.Lreturn_is_float:
572 cmp w10, #'F'
573 bne .Lreturn_is_int
574 str s0, [x4]
575 b .Lexit_art_quick_invoke_stub
576
577 // Just store x0. Doesn't matter if it is 64 or 32 bits.
578.Lreturn_is_int:
579 str x0, [x4]
580
581.Lexit_art_quick_invoke_stub:
582 ldr x2, [x29, #32] // Restore stack pointer.
583 mov sp, x2
584 .cfi_restore sp
585
586 ldp x29, x30, [x29] // Restore old frame pointer and link register.
587 .cfi_restore x29
588 .cfi_restore x30
589
590 ret
591END art_quick_invoke_stub
592
593/* extern"C"
594 * void art_quick_invoke_static_stub(ArtMethod *method, x0
595 * uint32_t *args, x1
596 * uint32_t argsize, w2
597 * Thread *self, x3
598 * JValue *result, x4
599 * char *shorty); x5
600 */
601ENTRY art_quick_invoke_static_stub
602 // Spill registers as per AACPS64 calling convention.
603
604SAVE_SIZE=5*8 // x4, x5, SP, LR & FP saved
605SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
606
607 mov x9, sp // Save stack pointer.
608
609 mov x10, xFP // Save frame pointer
610 .cfi_register x29,x10
611 add x11, x2, # SAVE_SIZE_AND_METHOD // calculate size of frame.
612
613 sub x11, sp, x11 // Calculate SP position - saves + ArtMethod* + args
614
615 and x11, x11, # ~0xf // Enforce 16 byte stack alignment.
616
617 sub xFP, x9, #SAVE_SIZE // Calculate new FP. Don't store here until SP moved.
618
619 mov sp, x11 // set new SP.
620
621 .cfi_def_cfa_register 29
622
623 str x9, [xFP, #32] // Save old stack pointer.
624
625 .cfi_offset x9, 32
626
627 stp x4, x5, [xFP, #16] // Save result and shorty addresses.
628
629 .cfi_offset x4, 16
630 .cfi_offset x5, 24
631
632 stp x10, xLR, [x29] // Store lr & old fp @ fp
633
634 .cfi_offset x30, 0
635 .cfi_offset x10, 8
636
637 mov xSELF, x3 // Move thread pointer into SELF register.
638
639 // Copy arguments into stack frame.
640 // Use simple copy routine for now.
641 // 4 bytes per slot.
642 // X1 - source address
643 // W2 - args length
644 // X10 - destination address.
645 add x9, sp, #8 // Destination address is bottom of stack + NULL.
646
647 // w2 = argsize parameter.
648.LcopyParams2:
649 cmp w2, #0
650 beq .LendCopyParams2
651 sub w2, w2, #4 // Need 65536 bytes of range.
652 ldr w10, [x1, x2]
653 str w10, [x9, x2]
654
655 b .LcopyParams2
656
657.LendCopyParams2:
658
659 // Store NULL into Method* at bottom of frame.
660 str xzr, [sp]
661
662 // Fill registers x/w1 to x/w7 and s/d0 to s/d7 with parameters.
663 // Parse the passed shorty to determine which register to load.
664 // Load addresses for routines that load WXSD registers.
665 adr x11, .LstoreW1_2
666 adr x12, .LstoreX1_2
667 adr x13, .LstoreS0_2
668 adr x14, .LstoreD0_2
669
670 // Initialize routine offsets to 0 for integers and floats.
671 // x8 for integers, x15 for floating point.
672 mov x8, #0
673 mov x15, #0
674
675 add x10, x5, #1 // Load shorty address, plus one to skip return value.
676
677 // Loop to fill registers.
678.LfillRegisters2:
679 ldrb w17, [x10], #1 // Load next character in signature, and increment.
680 cbz w17, .LcallFunction2 // Exit at end of signature. Shorty 0 terminated.
681
682 cmp w17, #'F' // is this a float?
683 bne .LisDouble2
684
685 cmp x15, # 8*12 // Skip this load if all registers full.
686 beq .LfillRegisters2
687
688 add x17, x13, x15 // Calculate subroutine to jump to.
689 br x17
690
691.LisDouble2:
692 cmp w17, #'D' // is this a double?
693 bne .LisLong2
694
695 cmp x15, # 8*12 // Skip this load if all registers full.
696 beq .LfillRegisters2
697
698
699 add x17, x14, x15 // Calculate subroutine to jump to.
700 br x17
701
702.LisLong2:
703 cmp w17, #'J' // is this a long?
704 bne .LisOther2
705
706 cmp x8, # 7*12 // Skip this load if all registers full.
707 beq .LfillRegisters2
708
709 add x17, x12, x8 // Calculate subroutine to jump to.
710 br x17
711
712
713.LisOther2: // Everything else takes one vReg.
714 cmp x8, # 7*12 // Skip this load if all registers full.
715 beq .LfillRegisters2
716 add x17, x11, x8 // Calculate subroutine to jump to.
717 br x17
718
719// Store ints.
720.LstoreW1_2:
721 LOADREG x8 4 w1 .LfillRegisters2
722 LOADREG x8 4 w2 .LfillRegisters2
723 LOADREG x8 4 w3 .LfillRegisters2
724 LOADREG x8 4 w4 .LfillRegisters2
725 LOADREG x8 4 w5 .LfillRegisters2
726 LOADREG x8 4 w6 .LfillRegisters2
727 LOADREG x8 4 w7 .LfillRegisters2
728
729// Store longs.
730.LstoreX1_2:
731 LOADREG x8 8 x1 .LfillRegisters2
732 LOADREG x8 8 x2 .LfillRegisters2
733 LOADREG x8 8 x3 .LfillRegisters2
734 LOADREG x8 8 x4 .LfillRegisters2
735 LOADREG x8 8 x5 .LfillRegisters2
736 LOADREG x8 8 x6 .LfillRegisters2
737 LOADREG x8 8 x7 .LfillRegisters2
738
739// Store singles.
740.LstoreS0_2:
741 LOADREG x15 4 s0 .LfillRegisters2
742 LOADREG x15 4 s1 .LfillRegisters2
743 LOADREG x15 4 s2 .LfillRegisters2
744 LOADREG x15 4 s3 .LfillRegisters2
745 LOADREG x15 4 s4 .LfillRegisters2
746 LOADREG x15 4 s5 .LfillRegisters2
747 LOADREG x15 4 s6 .LfillRegisters2
748 LOADREG x15 4 s7 .LfillRegisters2
749
750// Store doubles.
751.LstoreD0_2:
752 LOADREG x15 8 d0 .LfillRegisters2
753 LOADREG x15 8 d1 .LfillRegisters2
754 LOADREG x15 8 d2 .LfillRegisters2
755 LOADREG x15 8 d3 .LfillRegisters2
756 LOADREG x15 8 d4 .LfillRegisters2
757 LOADREG x15 8 d5 .LfillRegisters2
758 LOADREG x15 8 d6 .LfillRegisters2
759 LOADREG x15 8 d7 .LfillRegisters2
760
761
762.LcallFunction2:
763
764 // load method-> METHOD_QUICK_CODE_OFFSET.
765 ldr x9, [x0 , #METHOD_QUICK_CODE_OFFSET]
766 // Branch to method.
767 blr x9
768
769 // Restore return value address and shorty address.
770 ldp x4, x5, [xFP, #16]
771 .cfi_restore x4
772 .cfi_restore x5
773
774 // Store result (w0/x0/s0/d0) appropriately, depending on resultType.
775 ldrb w10, [x5]
776
777 // Don't set anything for a void type.
778 cmp w10, #'V'
779 beq .Lexit_art_quick_invoke_stub2
780
781 cmp w10, #'D'
782 bne .Lreturn_is_float2
783 str d0, [x4]
784 b .Lexit_art_quick_invoke_stub2
785
786.Lreturn_is_float2:
787 cmp w10, #'F'
788 bne .Lreturn_is_int2
789 str s0, [x4]
790 b .Lexit_art_quick_invoke_stub2
791
792 // Just store x0. Doesn't matter if it is 64 or 32 bits.
793.Lreturn_is_int2:
794 str x0, [x4]
795
796.Lexit_art_quick_invoke_stub2:
797
798 ldr x2, [xFP, #32] // Restore stack pointer.
799 mov sp, x2
800 .cfi_restore sp
801
802 ldp xFP, xLR, [xFP] // Restore old frame pointer and link register.
803 .cfi_restore x29
804 .cfi_restore x30
805
806 ret
807END art_quick_invoke_static_stub
808
809// UNIMPLEMENTED art_quick_do_long_jump
810
811 /*
812 * On entry x0 is uintptr_t* gprs_ and x1 is uint64_t* fprs_
813 */
814
815ENTRY art_quick_do_long_jump
816 // Load FPRs
817 ldp d0, d1, [x1], #16
818 ldp d2, d3, [x1], #16
819 ldp d4, d5, [x1], #16
820 ldp d6, d7, [x1], #16
821 ldp d8, d9, [x1], #16
822 ldp d10, d11, [x1], #16
823 ldp d12, d13, [x1], #16
824 ldp d14, d15, [x1], #16
825 ldp d16, d17, [x1], #16
826 ldp d18, d19, [x1], #16
827 ldp d20, d21, [x1], #16
828 ldp d22, d23, [x1], #16
829 ldp d24, d25, [x1], #16
830 ldp d26, d27, [x1], #16
831 ldp d28, d29, [x1], #16
832 ldp d30, d31, [x1]
833
834 // Load GPRs
835 // TODO: lots of those are smashed, could optimize.
836 add x0, x0, #30*8
837 ldp x30, x1, [x0], #-16
838 ldp x28, x29, [x0], #-16
839 ldp x26, x27, [x0], #-16
840 ldp x24, x25, [x0], #-16
841 ldp x22, x23, [x0], #-16
842 ldp x20, x21, [x0], #-16
843 ldp x18, x19, [x0], #-16
844 ldp x16, x17, [x0], #-16
845 ldp x14, x15, [x0], #-16
846 ldp x12, x13, [x0], #-16
847 ldp x10, x11, [x0], #-16
848 ldp x8, x9, [x0], #-16
849 ldp x6, x7, [x0], #-16
850 ldp x4, x5, [x0], #-16
851 ldp x2, x3, [x0], #-16
852 mov sp, x1
853
854 // TODO: Is it really OK to use LR for the target PC?
855 mov x0, #0
856 mov x1, #0
857 br xLR
858END art_quick_do_long_jump
859
860UNIMPLEMENTED art_quick_handle_fill_data
861
862UNIMPLEMENTED art_quick_lock_object
863UNIMPLEMENTED art_quick_unlock_object
864UNIMPLEMENTED art_quick_check_cast
865UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
866UNIMPLEMENTED art_quick_aput_obj_with_bound_check
867UNIMPLEMENTED art_quick_aput_obj
868UNIMPLEMENTED art_quick_initialize_static_storage
869UNIMPLEMENTED art_quick_initialize_type
870UNIMPLEMENTED art_quick_initialize_type_and_verify_access
871UNIMPLEMENTED art_quick_get32_static
872UNIMPLEMENTED art_quick_get64_static
873UNIMPLEMENTED art_quick_get_obj_static
874UNIMPLEMENTED art_quick_get32_instance
875UNIMPLEMENTED art_quick_get64_instance
876UNIMPLEMENTED art_quick_get_obj_instance
877UNIMPLEMENTED art_quick_set32_static
878UNIMPLEMENTED art_quick_set64_static
879UNIMPLEMENTED art_quick_set_obj_static
880UNIMPLEMENTED art_quick_set32_instance
881UNIMPLEMENTED art_quick_set64_instance
882UNIMPLEMENTED art_quick_set_obj_instance
883UNIMPLEMENTED art_quick_resolve_string
884
885// Macro to facilitate adding new allocation entrypoints.
886.macro TWO_ARG_DOWNCALL name, entrypoint, return
887 .extern \entrypoint
888ENTRY \name
889 brk 0
890END \name
891.endm
892
893// Macro to facilitate adding new array allocation entrypoints.
894.macro THREE_ARG_DOWNCALL name, entrypoint, return
895 .extern \entrypoint
896ENTRY \name
897 brk 0
898END \name
899.endm
900
901// Generate the allocation entrypoints for each allocator.
902GENERATE_ALL_ALLOC_ENTRYPOINTS
903
904UNIMPLEMENTED art_quick_test_suspend
905
Andreas Gampee62a07e2014-03-26 14:53:21 -0700906 /*
907 * Called by managed code that is attempting to call a method on a proxy class. On entry
908 * x0 holds the proxy method and x1 holds the receiver; The frame size of the invoked proxy
909 * method agrees with a ref and args callee save frame.
910 */
911 .extern artQuickProxyInvokeHandler
912ENTRY art_quick_proxy_invoke_handler
913 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
914 str x0, [sp, #0] // place proxy method at bottom of frame
915 mov x2, xSELF // pass Thread::Current
916 mov x3, sp // pass SP
917 bl artQuickProxyInvokeHandler // (Method* proxy method, receiver, Thread*, SP)
918 ldr xSELF, [sp, #200] // Restore self pointer.
919 ldr x2, [xSELF, THREAD_EXCEPTION_OFFSET]
920 cbnz x2, .Lexception_in_proxy // success if no exception is pending
921 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME_NO_D0 // keep d0
922 ret // return on success
923.Lexception_in_proxy:
924 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
925 DELIVER_PENDING_EXCEPTION
926END art_quick_proxy_invoke_handler
Stuart Monteithb95a5342014-03-12 13:32:32 +0000927
928UNIMPLEMENTED art_quick_imt_conflict_trampoline
929
930
931ENTRY art_quick_resolution_trampoline
932 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
Andreas Gampec6ee54e2014-03-24 16:45:44 -0700933 mov x19, x0 // save the called method
Stuart Monteithb95a5342014-03-12 13:32:32 +0000934 mov x2, xSELF
935 mov x3, sp
936 bl artQuickResolutionTrampoline // (called, receiver, Thread*, SP)
Andreas Gampec6ee54e2014-03-24 16:45:44 -0700937 mov x9, x0 // Remember returned code pointer in x9.
938 mov x0, x19 // Restore the method, before x19 is restored to on-call value
Stuart Monteithb95a5342014-03-12 13:32:32 +0000939 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
940 cbz x9, 1f
Andreas Gampec6ee54e2014-03-24 16:45:44 -0700941 br x9
Stuart Monteithb95a5342014-03-12 13:32:32 +00009421:
943 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
944 DELIVER_PENDING_EXCEPTION
945END art_quick_resolution_trampoline
946
947/*
948 * Generic JNI frame layout:
949 *
950 * #-------------------#
951 * | |
952 * | caller method... |
953 * #-------------------# <--- SP on entry
954 * | Return X30/LR |
955 * | X29/FP | callee save
956 * | X28 | callee save
957 * | X27 | callee save
958 * | X26 | callee save
959 * | X25 | callee save
960 * | X24 | callee save
961 * | X23 | callee save
962 * | X22 | callee save
963 * | X21 | callee save
964 * | X20 | callee save
965 * | X19 | callee save
966 * | X7 | arg7
967 * | X6 | arg6
968 * | X5 | arg5
969 * | X4 | arg4
970 * | X3 | arg3
971 * | X2 | arg2
972 * | X1 | arg1
973 * | D15 | float arg 8
974 * | D14 | float arg 8
975 * | D13 | float arg 8
976 * | D12 | callee save
977 * | D11 | callee save
978 * | D10 | callee save
979 * | D9 | callee save
980 * | D8 | callee save
981 * | D7 | float arg 8
982 * | D6 | float arg 7
983 * | D5 | float arg 6
984 * | D4 | float arg 5
985 * | D3 | float arg 4
986 * | D2 | float arg 3
987 * | D1 | float arg 2
988 * | D0 | float arg 1
989 * | RDI/Method* | <- X0
990 * #-------------------#
991 * | local ref cookie | // 4B
992 * | SIRT size | // 4B
993 * #-------------------#
994 * | JNI Call Stack |
995 * #-------------------# <--- SP on native call
996 * | |
997 * | Stack for Regs | The trampoline assembly will pop these values
998 * | | into registers for native call
999 * #-------------------#
1000 * | Native code ptr |
1001 * #-------------------#
1002 * | Free scratch |
1003 * #-------------------#
1004 * | Ptr to (1) | <--- SP
1005 * #-------------------#
1006 */
1007 /*
1008 * Called to do a generic JNI down-call
1009 */
1010ENTRY art_quick_generic_jni_trampoline
1011 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
1012 str x0, [sp, #0] // Store native ArtMethod* to bottom of stack.
1013
1014 // Save SP , so we can have static CFI info.
1015 mov x28, sp
1016 .cfi_def_cfa_register x28
1017
1018 // This looks the same, but is different: this will be updated to point to the bottom
1019 // of the frame when the SIRT is inserted.
1020 mov xFP, sp
1021
1022 mov x8, #5120
1023 sub sp, sp, x8
1024
1025 // prepare for artQuickGenericJniTrampoline call
1026 // (Thread*, SP)
1027 // x0 x1 <= C calling convention
1028 // xSELF xFP <= where they are
1029
1030 mov x0, xSELF // Thread*
1031 mov x1, xFP
1032 bl artQuickGenericJniTrampoline // (Thread*, sp)
1033
1034 // Get the updated pointer. This is the bottom of the frame _with_ SIRT.
1035 ldr xFP, [sp]
1036 add x9, sp, #8
1037
1038 cmp x0, #0
1039 b.mi .Lentry_error // Check for error, negative value.
1040
1041 // release part of the alloca.
1042 add x9, x9, x0
1043
1044 // Get the code pointer
1045 ldr xIP0, [x9, #0]
1046
1047 // Load parameters from frame into registers.
1048 // TODO Check with artQuickGenericJniTrampoline.
1049 // Also, check again APPCS64 - the stack arguments are interleaved.
1050 ldp x0, x1, [x9, #8]
1051 ldp x2, x3, [x9, #24]
1052 ldp x4, x5, [x9, #40]
1053 ldp x6, x7, [x9, #56]
1054
1055 ldp d0, d1, [x9, #72]
1056 ldp d2, d3, [x9, #88]
1057 ldp d4, d5, [x9, #104]
1058 ldp d6, d7, [x9, #120]
1059
1060 add sp, x9, #136
1061
1062 blr xIP0 // native call.
1063
1064 // Restore self pointer.
1065 ldr xSELF, [x28, #200]
1066
1067 // result sign extension is handled in C code
1068 // prepare for artQuickGenericJniEndTrampoline call
1069 // (Thread*, SP, result, result_f)
1070 // x0 x1 x2 x3 <= C calling convention
1071 mov x5, x0 // Save return value
1072 mov x0, xSELF // Thread register
1073 mov x1, xFP // Stack pointer
1074 mov x2, x5 // Result (from saved)
1075 fmov x3, d0 // d0 will contain floating point result, but needs to go into x3
1076
1077 bl artQuickGenericJniEndTrampoline
1078
1079 // Tear down the alloca.
1080 mov sp, x28
1081 .cfi_def_cfa_register sp
1082
1083 // Restore self pointer.
1084 ldr xSELF, [x28, #200]
1085
1086 // Pending exceptions possible.
1087 ldr x1, [xSELF, THREAD_EXCEPTION_OFFSET]
1088 cbnz x1, .Lexception_in_native
1089
1090 // Tear down the callee-save frame.
1091 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1092
1093 // store into fpr, for when it's a fpr return...
1094 fmov d0, x0
1095 ret
1096
1097.Lentry_error:
1098 mov sp, x28
1099 .cfi_def_cfa_register sp
1100 ldr xSELF, [x28, #200]
1101.Lexception_in_native:
1102 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
1103 DELIVER_PENDING_EXCEPTION
1104
1105END art_quick_generic_jni_trampoline
1106
1107/*
1108 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
1109 * of a quick call:
1110 * x0 = method being called/to bridge to.
1111 * x1..x7, d0..d7 = arguments to that method.
1112 */
1113ENTRY art_quick_to_interpreter_bridge
1114 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // Set up frame and save arguments.
1115
1116 // x0 will contain mirror::ArtMethod* method.
1117 mov x1, xSELF // How to get Thread::Current() ???
1118 mov x2, sp
1119
1120 // uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
1121 // mirror::ArtMethod** sp)
1122 bl artQuickToInterpreterBridge
1123
1124 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME // TODO: no need to restore arguments in this case.
1125
1126 fmov d0, x0
1127
1128 RETURN_OR_DELIVER_PENDING_EXCEPTION
1129END art_quick_to_interpreter_bridge
1130
1131UNIMPLEMENTED art_quick_instrumentation_entry
1132UNIMPLEMENTED art_quick_instrumentation_exit
1133UNIMPLEMENTED art_quick_deoptimize
1134UNIMPLEMENTED art_quick_mul_long
1135UNIMPLEMENTED art_quick_shl_long
1136UNIMPLEMENTED art_quick_shr_long
1137UNIMPLEMENTED art_quick_ushr_long
1138UNIMPLEMENTED art_quick_indexof
1139UNIMPLEMENTED art_quick_string_compareto