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