1*795d594fSAndroid Build Coastguard Worker%def header(): 2*795d594fSAndroid Build Coastguard Worker/* 3*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project 4*795d594fSAndroid Build Coastguard Worker * 5*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 6*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 7*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 8*795d594fSAndroid Build Coastguard Worker * 9*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 10*795d594fSAndroid Build Coastguard Worker * 11*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 12*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 13*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 15*795d594fSAndroid Build Coastguard Worker * limitations under the License. 16*795d594fSAndroid Build Coastguard Worker */ 17*795d594fSAndroid Build Coastguard Worker 18*795d594fSAndroid Build Coastguard Worker/* 19*795d594fSAndroid Build Coastguard Worker * This is a #include, not a %include, because we want the C pre-processor 20*795d594fSAndroid Build Coastguard Worker * to expand the macros into assembler assignment statements. 21*795d594fSAndroid Build Coastguard Worker */ 22*795d594fSAndroid Build Coastguard Worker#include "asm_support.h" 23*795d594fSAndroid Build Coastguard Worker#include "arch/x86_64/asm_support_x86_64.S" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker/** 26*795d594fSAndroid Build Coastguard Worker * x86_64 ABI general notes: 27*795d594fSAndroid Build Coastguard Worker * 28*795d594fSAndroid Build Coastguard Worker * Caller save set: 29*795d594fSAndroid Build Coastguard Worker * rax, rdx, rcx, rsi, rdi, r8-r11, st(0)-st(7) 30*795d594fSAndroid Build Coastguard Worker * Callee save set: 31*795d594fSAndroid Build Coastguard Worker * rbx, rbp, r12-r15 32*795d594fSAndroid Build Coastguard Worker * Return regs: 33*795d594fSAndroid Build Coastguard Worker * 32-bit in eax 34*795d594fSAndroid Build Coastguard Worker * 64-bit in rax 35*795d594fSAndroid Build Coastguard Worker * fp on xmm0 36*795d594fSAndroid Build Coastguard Worker * 37*795d594fSAndroid Build Coastguard Worker * First 8 fp parameters came in xmm0-xmm7. 38*795d594fSAndroid Build Coastguard Worker * First 6 non-fp parameters came in rdi, rsi, rdx, rcx, r8, r9. 39*795d594fSAndroid Build Coastguard Worker * Other parameters passed on stack, pushed right-to-left. On entry to target, first 40*795d594fSAndroid Build Coastguard Worker * param is at 8(%esp). 41*795d594fSAndroid Build Coastguard Worker * 42*795d594fSAndroid Build Coastguard Worker * Stack must be 16-byte aligned to support SSE in native code. 43*795d594fSAndroid Build Coastguard Worker */ 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker#define IN_ARG3 %rcx 46*795d594fSAndroid Build Coastguard Worker#define IN_ARG2 %rdx 47*795d594fSAndroid Build Coastguard Worker#define IN_ARG1 %rsi 48*795d594fSAndroid Build Coastguard Worker#define IN_ARG0 %rdi 49*795d594fSAndroid Build Coastguard Worker/* Out Args */ 50*795d594fSAndroid Build Coastguard Worker#define OUT_ARG3 %rcx 51*795d594fSAndroid Build Coastguard Worker#define OUT_ARG2 %rdx 52*795d594fSAndroid Build Coastguard Worker#define OUT_ARG1 %rsi 53*795d594fSAndroid Build Coastguard Worker#define OUT_ARG0 %rdi 54*795d594fSAndroid Build Coastguard Worker#define OUT_32_ARG3 %ecx 55*795d594fSAndroid Build Coastguard Worker#define OUT_32_ARG2 %edx 56*795d594fSAndroid Build Coastguard Worker#define OUT_32_ARG1 %esi 57*795d594fSAndroid Build Coastguard Worker#define OUT_32_ARG0 %edi 58*795d594fSAndroid Build Coastguard Worker#define OUT_FP_ARG1 %xmm1 59*795d594fSAndroid Build Coastguard Worker#define OUT_FP_ARG0 %xmm0 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker/* 62*795d594fSAndroid Build Coastguard Worker * single-purpose registers, given names for clarity 63*795d594fSAndroid Build Coastguard Worker */ 64*795d594fSAndroid Build Coastguard Worker#define rSELF %gs 65*795d594fSAndroid Build Coastguard Worker#define rPC %r12 66*795d594fSAndroid Build Coastguard Worker#define CFI_DEX 12 // DWARF register number of the register holding dex-pc (rPC). 67*795d594fSAndroid Build Coastguard Worker#define CFI_TMP 5 // DWARF register number of the first argument register (rdi). 68*795d594fSAndroid Build Coastguard Worker#define rFP %r13 69*795d594fSAndroid Build Coastguard Worker#define rINST %ebx 70*795d594fSAndroid Build Coastguard Worker#define rINSTq %rbx 71*795d594fSAndroid Build Coastguard Worker#define rINSTw %bx 72*795d594fSAndroid Build Coastguard Worker#define rINSTbh %bh 73*795d594fSAndroid Build Coastguard Worker#define rINSTbl %bl 74*795d594fSAndroid Build Coastguard Worker#define rIBASE %r14 75*795d594fSAndroid Build Coastguard Worker#define rREFS %r15 76*795d594fSAndroid Build Coastguard Worker#define rREFS32 %r15d 77*795d594fSAndroid Build Coastguard Worker#define CFI_REFS 15 // DWARF register number of the reference array (r15). 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker// Temporary registers while setting up a frame. 80*795d594fSAndroid Build Coastguard Worker#define rNEW_FP %r8 81*795d594fSAndroid Build Coastguard Worker#define rNEW_REFS %r9 82*795d594fSAndroid Build Coastguard Worker#define rNEW_REFS32 %r9d 83*795d594fSAndroid Build Coastguard Worker#define CFI_NEW_REFS 9 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker/* 86*795d594fSAndroid Build Coastguard Worker * Get/set the 32-bit value from a Dalvik register. 87*795d594fSAndroid Build Coastguard Worker */ 88*795d594fSAndroid Build Coastguard Worker#define VREG_ADDRESS(_vreg) (rFP,_vreg,4) 89*795d594fSAndroid Build Coastguard Worker#define VREG_HIGH_ADDRESS(_vreg) 4(rFP,_vreg,4) 90*795d594fSAndroid Build Coastguard Worker#define VREG_REF_ADDRESS(_vreg) (rREFS,_vreg,4) 91*795d594fSAndroid Build Coastguard Worker#define VREG_REF_HIGH_ADDRESS(_vreg) 4(rREFS,_vreg,4) 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker// Includes the return address implictly pushed on stack by 'call'. 94*795d594fSAndroid Build Coastguard Worker#define CALLEE_SAVES_SIZE (6 * 8 + 4 * 8 + 1 * 8) 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker// +8 for the ArtMethod of the caller. 97*795d594fSAndroid Build Coastguard Worker#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 8) 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker/* 100*795d594fSAndroid Build Coastguard Worker * Refresh rINST. 101*795d594fSAndroid Build Coastguard Worker * At enter to handler rINST does not contain the opcode number. 102*795d594fSAndroid Build Coastguard Worker * However some utilities require the full value, so this macro 103*795d594fSAndroid Build Coastguard Worker * restores the opcode number. 104*795d594fSAndroid Build Coastguard Worker */ 105*795d594fSAndroid Build Coastguard Worker.macro REFRESH_INST _opnum 106*795d594fSAndroid Build Coastguard Worker movb rINSTbl, rINSTbh 107*795d594fSAndroid Build Coastguard Worker movb $$\_opnum, rINSTbl 108*795d594fSAndroid Build Coastguard Worker.endm 109*795d594fSAndroid Build Coastguard Worker 110*795d594fSAndroid Build Coastguard Worker/* 111*795d594fSAndroid Build Coastguard Worker * Fetch the next instruction from rPC into rINSTw. Does not advance rPC. 112*795d594fSAndroid Build Coastguard Worker */ 113*795d594fSAndroid Build Coastguard Worker.macro FETCH_INST 114*795d594fSAndroid Build Coastguard Worker movzwq (rPC), rINSTq 115*795d594fSAndroid Build Coastguard Worker.endm 116*795d594fSAndroid Build Coastguard Worker 117*795d594fSAndroid Build Coastguard Worker/* 118*795d594fSAndroid Build Coastguard Worker * Remove opcode from rINST, compute the address of handler and jump to it. 119*795d594fSAndroid Build Coastguard Worker */ 120*795d594fSAndroid Build Coastguard Worker.macro GOTO_NEXT 121*795d594fSAndroid Build Coastguard Worker movzx rINSTbl,%ecx 122*795d594fSAndroid Build Coastguard Worker movzbl rINSTbh,rINST 123*795d594fSAndroid Build Coastguard Worker shll MACRO_LITERAL(${handler_size_bits}), %ecx 124*795d594fSAndroid Build Coastguard Worker addq rIBASE, %rcx 125*795d594fSAndroid Build Coastguard Worker jmp *%rcx 126*795d594fSAndroid Build Coastguard Worker.endm 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Worker/* 129*795d594fSAndroid Build Coastguard Worker * Advance rPC by instruction count. 130*795d594fSAndroid Build Coastguard Worker */ 131*795d594fSAndroid Build Coastguard Worker.macro ADVANCE_PC _count 132*795d594fSAndroid Build Coastguard Worker leaq 2*\_count(rPC), rPC 133*795d594fSAndroid Build Coastguard Worker.endm 134*795d594fSAndroid Build Coastguard Worker 135*795d594fSAndroid Build Coastguard Worker/* 136*795d594fSAndroid Build Coastguard Worker * Advance rPC by instruction count, fetch instruction and jump to handler. 137*795d594fSAndroid Build Coastguard Worker */ 138*795d594fSAndroid Build Coastguard Worker.macro ADVANCE_PC_FETCH_AND_GOTO_NEXT _count 139*795d594fSAndroid Build Coastguard Worker ADVANCE_PC \_count 140*795d594fSAndroid Build Coastguard Worker FETCH_INST 141*795d594fSAndroid Build Coastguard Worker GOTO_NEXT 142*795d594fSAndroid Build Coastguard Worker.endm 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker.macro GET_VREG _reg _vreg 145*795d594fSAndroid Build Coastguard Worker movl VREG_ADDRESS(\_vreg), \_reg 146*795d594fSAndroid Build Coastguard Worker.endm 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_OBJECT _reg _vreg 149*795d594fSAndroid Build Coastguard Worker movl VREG_REF_ADDRESS(\_vreg), \_reg 150*795d594fSAndroid Build Coastguard Worker.endm 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker/* Read wide value. */ 153*795d594fSAndroid Build Coastguard Worker.macro GET_WIDE_VREG _reg _vreg 154*795d594fSAndroid Build Coastguard Worker movq VREG_ADDRESS(\_vreg), \_reg 155*795d594fSAndroid Build Coastguard Worker.endm 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker.macro SET_VREG _reg _vreg 158*795d594fSAndroid Build Coastguard Worker movl \_reg, VREG_ADDRESS(\_vreg) 159*795d594fSAndroid Build Coastguard Worker movl MACRO_LITERAL(0), VREG_REF_ADDRESS(\_vreg) 160*795d594fSAndroid Build Coastguard Worker.endm 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker/* Write wide value. reg is clobbered. */ 163*795d594fSAndroid Build Coastguard Worker.macro SET_WIDE_VREG _reg _vreg 164*795d594fSAndroid Build Coastguard Worker movq \_reg, VREG_ADDRESS(\_vreg) 165*795d594fSAndroid Build Coastguard Worker xorq \_reg, \_reg 166*795d594fSAndroid Build Coastguard Worker movq \_reg, VREG_REF_ADDRESS(\_vreg) 167*795d594fSAndroid Build Coastguard Worker.endm 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_OBJECT _reg _vreg 170*795d594fSAndroid Build Coastguard Worker movl \_reg, VREG_ADDRESS(\_vreg) 171*795d594fSAndroid Build Coastguard Worker movl \_reg, VREG_REF_ADDRESS(\_vreg) 172*795d594fSAndroid Build Coastguard Worker.endm 173*795d594fSAndroid Build Coastguard Worker 174*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_HIGH _reg _vreg 175*795d594fSAndroid Build Coastguard Worker movl VREG_HIGH_ADDRESS(\_vreg), \_reg 176*795d594fSAndroid Build Coastguard Worker.endm 177*795d594fSAndroid Build Coastguard Worker 178*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_HIGH _reg _vreg 179*795d594fSAndroid Build Coastguard Worker movl \_reg, VREG_HIGH_ADDRESS(\_vreg) 180*795d594fSAndroid Build Coastguard Worker movl MACRO_LITERAL(0), VREG_REF_HIGH_ADDRESS(\_vreg) 181*795d594fSAndroid Build Coastguard Worker.endm 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker.macro CLEAR_REF _vreg 184*795d594fSAndroid Build Coastguard Worker movl MACRO_LITERAL(0), VREG_REF_ADDRESS(\_vreg) 185*795d594fSAndroid Build Coastguard Worker.endm 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker.macro CLEAR_WIDE_REF _vreg 188*795d594fSAndroid Build Coastguard Worker movl MACRO_LITERAL(0), VREG_REF_ADDRESS(\_vreg) 189*795d594fSAndroid Build Coastguard Worker movl MACRO_LITERAL(0), VREG_REF_HIGH_ADDRESS(\_vreg) 190*795d594fSAndroid Build Coastguard Worker.endm 191*795d594fSAndroid Build Coastguard Worker 192*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_XMMs _xmmreg _vreg 193*795d594fSAndroid Build Coastguard Worker movss VREG_ADDRESS(\_vreg), \_xmmreg 194*795d594fSAndroid Build Coastguard Worker.endm 195*795d594fSAndroid Build Coastguard Worker.macro GET_VREG_XMMd _xmmreg _vreg 196*795d594fSAndroid Build Coastguard Worker movsd VREG_ADDRESS(\_vreg), \_xmmreg 197*795d594fSAndroid Build Coastguard Worker.endm 198*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_XMMs _xmmreg _vreg 199*795d594fSAndroid Build Coastguard Worker movss \_xmmreg, VREG_ADDRESS(\_vreg) 200*795d594fSAndroid Build Coastguard Worker.endm 201*795d594fSAndroid Build Coastguard Worker.macro SET_VREG_XMMd _xmmreg _vreg 202*795d594fSAndroid Build Coastguard Worker movsd \_xmmreg, VREG_ADDRESS(\_vreg) 203*795d594fSAndroid Build Coastguard Worker.endm 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker// An assembly entry for nterp. 206*795d594fSAndroid Build Coastguard Worker.macro OAT_ENTRY name 207*795d594fSAndroid Build Coastguard Worker FUNCTION_TYPE(\name) 208*795d594fSAndroid Build Coastguard Worker ASM_HIDDEN SYMBOL(\name) 209*795d594fSAndroid Build Coastguard Worker .global SYMBOL(\name) 210*795d594fSAndroid Build Coastguard Worker .balign 16 211*795d594fSAndroid Build Coastguard WorkerSYMBOL(\name): 212*795d594fSAndroid Build Coastguard Worker.endm 213*795d594fSAndroid Build Coastguard Worker 214*795d594fSAndroid Build Coastguard Worker.macro ENTRY name 215*795d594fSAndroid Build Coastguard Worker .text 216*795d594fSAndroid Build Coastguard Worker ASM_HIDDEN SYMBOL(\name) 217*795d594fSAndroid Build Coastguard Worker .global SYMBOL(\name) 218*795d594fSAndroid Build Coastguard Worker FUNCTION_TYPE(\name) 219*795d594fSAndroid Build Coastguard WorkerSYMBOL(\name): 220*795d594fSAndroid Build Coastguard Worker.endm 221*795d594fSAndroid Build Coastguard Worker 222*795d594fSAndroid Build Coastguard Worker.macro END name 223*795d594fSAndroid Build Coastguard Worker SIZE(\name) 224*795d594fSAndroid Build Coastguard Worker.endm 225*795d594fSAndroid Build Coastguard Worker 226*795d594fSAndroid Build Coastguard Worker// Macro for defining entrypoints into runtime. We don't need to save registers 227*795d594fSAndroid Build Coastguard Worker// (we're not holding references there), but there is no 228*795d594fSAndroid Build Coastguard Worker// kDontSave runtime method. So just use the kSaveRefsOnly runtime method. 229*795d594fSAndroid Build Coastguard Worker.macro NTERP_TRAMPOLINE name, helper 230*795d594fSAndroid Build Coastguard WorkerDEFINE_FUNCTION \name 231*795d594fSAndroid Build Coastguard Worker SETUP_SAVE_REFS_ONLY_FRAME 232*795d594fSAndroid Build Coastguard Worker call \helper 233*795d594fSAndroid Build Coastguard Worker RESTORE_SAVE_REFS_ONLY_FRAME 234*795d594fSAndroid Build Coastguard Worker cmpq LITERAL(0), %gs:THREAD_EXCEPTION_OFFSET 235*795d594fSAndroid Build Coastguard Worker jne nterp_deliver_pending_exception 236*795d594fSAndroid Build Coastguard Worker ret 237*795d594fSAndroid Build Coastguard WorkerEND_FUNCTION \name 238*795d594fSAndroid Build Coastguard Worker.endm 239*795d594fSAndroid Build Coastguard Worker 240*795d594fSAndroid Build Coastguard Worker.macro CLEAR_VOLATILE_MARKER reg 241*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(-2), \reg 242*795d594fSAndroid Build Coastguard Worker.endm 243*795d594fSAndroid Build Coastguard Worker 244*795d594fSAndroid Build Coastguard Worker.macro EXPORT_PC 245*795d594fSAndroid Build Coastguard Worker movq rPC, -16(rREFS) 246*795d594fSAndroid Build Coastguard Worker.endm 247*795d594fSAndroid Build Coastguard Worker 248*795d594fSAndroid Build Coastguard Worker 249*795d594fSAndroid Build Coastguard Worker.macro BRANCH 250*795d594fSAndroid Build Coastguard Worker leaq (rPC, rINSTq, 2), rPC 251*795d594fSAndroid Build Coastguard Worker // Update method counter and do a suspend check if the branch is negative or zero. 252*795d594fSAndroid Build Coastguard Worker testq rINSTq, rINSTq 253*795d594fSAndroid Build Coastguard Worker jle 3f 254*795d594fSAndroid Build Coastguard Worker2: // We use 2 and not 1 for this local label as the users of the BRANCH macro have a 1 label. 255*795d594fSAndroid Build Coastguard Worker FETCH_INST 256*795d594fSAndroid Build Coastguard Worker GOTO_NEXT 257*795d594fSAndroid Build Coastguard Worker3: 258*795d594fSAndroid Build Coastguard Worker movq (%rsp), %rdi 259*795d594fSAndroid Build Coastguard Worker movzwl ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi), %esi 260*795d594fSAndroid Build Coastguard Worker#if (NTERP_HOTNESS_VALUE != 0) 261*795d594fSAndroid Build Coastguard Worker#error Expected 0 for hotness value 262*795d594fSAndroid Build Coastguard Worker#endif 263*795d594fSAndroid Build Coastguard Worker // If the counter is at zero, handle this in the runtime. 264*795d594fSAndroid Build Coastguard Worker testw %si, %si 265*795d594fSAndroid Build Coastguard Worker je NterpHandleHotnessOverflow 266*795d594fSAndroid Build Coastguard Worker // Update counter. 267*795d594fSAndroid Build Coastguard Worker addl $$-1, %esi 268*795d594fSAndroid Build Coastguard Worker movw %si, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi) 269*795d594fSAndroid Build Coastguard Worker DO_SUSPEND_CHECK continue_label=2b 270*795d594fSAndroid Build Coastguard Worker jmp 2b 271*795d594fSAndroid Build Coastguard Worker.endm 272*795d594fSAndroid Build Coastguard Worker 273*795d594fSAndroid Build Coastguard Worker// Expects: 274*795d594fSAndroid Build Coastguard Worker// - r10, and r11 to be available. 275*795d594fSAndroid Build Coastguard Worker// Outputs: 276*795d594fSAndroid Build Coastguard Worker// - \registers contains the dex registers size 277*795d594fSAndroid Build Coastguard Worker// - \outs contains the outs size 278*795d594fSAndroid Build Coastguard Worker// - if load_ins is 1, \ins contains the ins 279*795d594fSAndroid Build Coastguard Worker// - \code_item is replace with a pointer to the instructions 280*795d594fSAndroid Build Coastguard Worker.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins 281*795d594fSAndroid Build Coastguard Worker // Fetch dex register size. 282*795d594fSAndroid Build Coastguard Worker movzwl CODE_ITEM_REGISTERS_SIZE_OFFSET(\code_item), \registers 283*795d594fSAndroid Build Coastguard Worker // Fetch outs size. 284*795d594fSAndroid Build Coastguard Worker movzwl CODE_ITEM_OUTS_SIZE_OFFSET(\code_item), \outs 285*795d594fSAndroid Build Coastguard Worker .if \load_ins 286*795d594fSAndroid Build Coastguard Worker movzwl CODE_ITEM_INS_SIZE_OFFSET(\code_item), \ins 287*795d594fSAndroid Build Coastguard Worker .endif 288*795d594fSAndroid Build Coastguard Worker addq $$CODE_ITEM_INSNS_OFFSET, \code_item 289*795d594fSAndroid Build Coastguard Worker.endm 290*795d594fSAndroid Build Coastguard Worker 291*795d594fSAndroid Build Coastguard Worker// Setup the stack to start executing the method. Expects: 292*795d594fSAndroid Build Coastguard Worker// - rdi to contain the ArtMethod 293*795d594fSAndroid Build Coastguard Worker// - rbx, r10, r11 to be available. 294*795d594fSAndroid Build Coastguard Worker// 295*795d594fSAndroid Build Coastguard Worker// Outputs 296*795d594fSAndroid Build Coastguard Worker// - rbx contains the dex registers size 297*795d594fSAndroid Build Coastguard Worker// - r11 contains the old stack pointer. 298*795d594fSAndroid Build Coastguard Worker// - \code_item is replace with a pointer to the instructions 299*795d594fSAndroid Build Coastguard Worker// - if load_ins is 1, r14 contains the ins 300*795d594fSAndroid Build Coastguard Worker.macro SETUP_STACK_FRAME code_item, refs, refs32, fp, cfi_refs, load_ins 301*795d594fSAndroid Build Coastguard Worker FETCH_CODE_ITEM_INFO \code_item, %ebx, \refs32, %r14d, \load_ins 302*795d594fSAndroid Build Coastguard Worker 303*795d594fSAndroid Build Coastguard Worker // Compute required frame size for dex registers: ((2 * ebx) + refs) 304*795d594fSAndroid Build Coastguard Worker leaq (\refs, %rbx, 2), %r11 305*795d594fSAndroid Build Coastguard Worker salq $$2, %r11 306*795d594fSAndroid Build Coastguard Worker 307*795d594fSAndroid Build Coastguard Worker // Compute new stack pointer in r10: add 24 for saving the previous frame, 308*795d594fSAndroid Build Coastguard Worker // pc, and method being executed. 309*795d594fSAndroid Build Coastguard Worker leaq -24(%rsp), %r10 310*795d594fSAndroid Build Coastguard Worker subq %r11, %r10 311*795d594fSAndroid Build Coastguard Worker // Alignment 312*795d594fSAndroid Build Coastguard Worker // Note: There may be two pieces of alignment but there is no need to align 313*795d594fSAndroid Build Coastguard Worker // out args to `kPointerSize` separately before aligning to kStackAlignment. 314*795d594fSAndroid Build Coastguard Worker andq $$-16, %r10 315*795d594fSAndroid Build Coastguard Worker 316*795d594fSAndroid Build Coastguard Worker // Set reference and dex registers, align to pointer size for previous frame and dex pc. 317*795d594fSAndroid Build Coastguard Worker leaq 24 + 4(%r10, \refs, 4), \refs 318*795d594fSAndroid Build Coastguard Worker andq LITERAL(-__SIZEOF_POINTER__), \refs 319*795d594fSAndroid Build Coastguard Worker leaq (\refs, %rbx, 4), \fp 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker // Now setup the stack pointer. 322*795d594fSAndroid Build Coastguard Worker movq %rsp, %r11 323*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_REGISTER(r11) 324*795d594fSAndroid Build Coastguard Worker movq %r10, %rsp 325*795d594fSAndroid Build Coastguard Worker movq %r11, -8(\refs) 326*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -8, ((6 + 4 + 1) * 8) 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker // Put nulls in reference frame. 329*795d594fSAndroid Build Coastguard Worker testl %ebx, %ebx 330*795d594fSAndroid Build Coastguard Worker je 2f 331*795d594fSAndroid Build Coastguard Worker movq \refs, %r10 332*795d594fSAndroid Build Coastguard Worker1: 333*795d594fSAndroid Build Coastguard Worker movl $$0, (%r10) 334*795d594fSAndroid Build Coastguard Worker addq $$4, %r10 335*795d594fSAndroid Build Coastguard Worker cmpq %r10, \fp 336*795d594fSAndroid Build Coastguard Worker jne 1b 337*795d594fSAndroid Build Coastguard Worker2: 338*795d594fSAndroid Build Coastguard Worker // Save the ArtMethod. 339*795d594fSAndroid Build Coastguard Worker movq %rdi, (%rsp) 340*795d594fSAndroid Build Coastguard Worker.endm 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker// Puts the next floating point argument into the expected register, 343*795d594fSAndroid Build Coastguard Worker// fetching values based on a non-range invoke. 344*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 345*795d594fSAndroid Build Coastguard Worker// 346*795d594fSAndroid Build Coastguard Worker// TODO: We could simplify a lot of code by loading the G argument into 347*795d594fSAndroid Build Coastguard Worker// the "inst" register. Given that we enter the handler with "1(rPC)" in 348*795d594fSAndroid Build Coastguard Worker// the rINST, we can just add rINST<<16 to the args and we don't even 349*795d594fSAndroid Build Coastguard Worker// need to pass "arg_index" around. 350*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_SHORTY_LOADING_XMMS xmm_reg, inst, shorty, arg_index, finished 351*795d594fSAndroid Build Coastguard Worker1: // LOOP 352*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // bl := *shorty 353*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 354*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 355*795d594fSAndroid Build Coastguard Worker je VAR(finished) 356*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 357*795d594fSAndroid Build Coastguard Worker je 2f 358*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 359*795d594fSAndroid Build Coastguard Worker je 3f 360*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 361*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 362*795d594fSAndroid Build Coastguard Worker // Handle extra argument in arg array taken by a long. 363*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 364*795d594fSAndroid Build Coastguard Worker jne 1b 365*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 366*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 367*795d594fSAndroid Build Coastguard Worker jmp 1b // goto LOOP 368*795d594fSAndroid Build Coastguard Worker2: // FOUND_DOUBLE 369*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(8), %rsp 370*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 371*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 372*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, %rax 373*795d594fSAndroid Build Coastguard Worker movl %eax, (%rsp) 374*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 375*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 376*795d594fSAndroid Build Coastguard Worker cmpq MACRO_LITERAL(4), REG_VAR(arg_index) 377*795d594fSAndroid Build Coastguard Worker je 5f 378*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 379*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 380*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 381*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 382*795d594fSAndroid Build Coastguard Worker jmp 6f 383*795d594fSAndroid Build Coastguard Worker5: 384*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %eax 385*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 386*795d594fSAndroid Build Coastguard Worker6: 387*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, %rax 388*795d594fSAndroid Build Coastguard Worker movl %eax, 4(%rsp) 389*795d594fSAndroid Build Coastguard Worker movsd (%rsp), REG_VAR(xmm_reg) 390*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(8), %rsp 391*795d594fSAndroid Build Coastguard Worker jmp 4f 392*795d594fSAndroid Build Coastguard Worker3: // FOUND_FLOAT 393*795d594fSAndroid Build Coastguard Worker cmpq MACRO_LITERAL(4), REG_VAR(arg_index) 394*795d594fSAndroid Build Coastguard Worker je 7f 395*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 396*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 397*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 398*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 399*795d594fSAndroid Build Coastguard Worker jmp 8f 400*795d594fSAndroid Build Coastguard Worker7: 401*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %eax 402*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 403*795d594fSAndroid Build Coastguard Worker8: 404*795d594fSAndroid Build Coastguard Worker GET_VREG_XMMs REG_VAR(xmm_reg), %rax 405*795d594fSAndroid Build Coastguard Worker4: 406*795d594fSAndroid Build Coastguard Worker.endm 407*795d594fSAndroid Build Coastguard Worker 408*795d594fSAndroid Build Coastguard Worker// Puts the next int/long/object argument in the expected register, 409*795d594fSAndroid Build Coastguard Worker// fetching values based on a non-range invoke. 410*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 411*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished 412*795d594fSAndroid Build Coastguard Worker1: // LOOP 413*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 414*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 415*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 416*795d594fSAndroid Build Coastguard Worker je VAR(finished) 417*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 418*795d594fSAndroid Build Coastguard Worker je 2f 419*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 420*795d594fSAndroid Build Coastguard Worker je 3f 421*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 422*795d594fSAndroid Build Coastguard Worker je 4f 423*795d594fSAndroid Build Coastguard Worker cmpq MACRO_LITERAL(4), REG_VAR(arg_index) 424*795d594fSAndroid Build Coastguard Worker je 7f 425*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 426*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 427*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 428*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 429*795d594fSAndroid Build Coastguard Worker jmp 8f 430*795d594fSAndroid Build Coastguard Worker7: 431*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %eax 432*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 433*795d594fSAndroid Build Coastguard Worker8: 434*795d594fSAndroid Build Coastguard Worker GET_VREG REG_VAR(gpr_reg32), %rax 435*795d594fSAndroid Build Coastguard Worker jmp 5f 436*795d594fSAndroid Build Coastguard Worker2: // FOUND_LONG 437*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(8), %rsp 438*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 439*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 440*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, %rax 441*795d594fSAndroid Build Coastguard Worker movl %eax, (%rsp) 442*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 443*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 444*795d594fSAndroid Build Coastguard Worker cmpq MACRO_LITERAL(4), REG_VAR(arg_index) 445*795d594fSAndroid Build Coastguard Worker je 9f 446*795d594fSAndroid Build Coastguard Worker movq REG_VAR(inst), %rax 447*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 448*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 449*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 450*795d594fSAndroid Build Coastguard Worker jmp 10f 451*795d594fSAndroid Build Coastguard Worker9: 452*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %eax 453*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0xf), %rax 454*795d594fSAndroid Build Coastguard Worker10: 455*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, %rax 456*795d594fSAndroid Build Coastguard Worker movl %eax, 4(%rsp) 457*795d594fSAndroid Build Coastguard Worker movq (%rsp), REG_VAR(gpr_reg64) 458*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(8), %rsp 459*795d594fSAndroid Build Coastguard Worker jmp 5f 460*795d594fSAndroid Build Coastguard Worker3: // SKIP_FLOAT 461*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 462*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 463*795d594fSAndroid Build Coastguard Worker jmp 1b 464*795d594fSAndroid Build Coastguard Worker4: // SKIP_DOUBLE 465*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 466*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 467*795d594fSAndroid Build Coastguard Worker cmpq MACRO_LITERAL(4), REG_VAR(arg_index) 468*795d594fSAndroid Build Coastguard Worker je 1b 469*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), REG_VAR(inst) 470*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 471*795d594fSAndroid Build Coastguard Worker jmp 1b 472*795d594fSAndroid Build Coastguard Worker5: 473*795d594fSAndroid Build Coastguard Worker.endm 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker// Puts the next floating point argument into the expected register, 476*795d594fSAndroid Build Coastguard Worker// fetching values based on a range invoke. 477*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 478*795d594fSAndroid Build Coastguard Worker.macro LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm_reg, shorty, arg_index, stack_index, finished 479*795d594fSAndroid Build Coastguard Worker1: // LOOP 480*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 481*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 482*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 483*795d594fSAndroid Build Coastguard Worker je VAR(finished) 484*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 485*795d594fSAndroid Build Coastguard Worker je 2f 486*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 487*795d594fSAndroid Build Coastguard Worker je 3f 488*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 489*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 490*795d594fSAndroid Build Coastguard Worker // Handle extra argument in arg array taken by a long. 491*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 492*795d594fSAndroid Build Coastguard Worker jne 1b 493*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 494*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 495*795d594fSAndroid Build Coastguard Worker jmp 1b // goto LOOP 496*795d594fSAndroid Build Coastguard Worker2: // FOUND_DOUBLE 497*795d594fSAndroid Build Coastguard Worker GET_VREG_XMMd REG_VAR(xmm_reg), REG_VAR(arg_index) 498*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 499*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 500*795d594fSAndroid Build Coastguard Worker jmp 4f 501*795d594fSAndroid Build Coastguard Worker3: // FOUND_FLOAT 502*795d594fSAndroid Build Coastguard Worker GET_VREG_XMMs REG_VAR(xmm_reg), REG_VAR(arg_index) 503*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 504*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 505*795d594fSAndroid Build Coastguard Worker4: 506*795d594fSAndroid Build Coastguard Worker.endm 507*795d594fSAndroid Build Coastguard Worker 508*795d594fSAndroid Build Coastguard Worker// Puts the next floating point argument into the expected stack slot, 509*795d594fSAndroid Build Coastguard Worker// fetching values based on a range invoke. 510*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 511*795d594fSAndroid Build Coastguard Worker// 512*795d594fSAndroid Build Coastguard Worker// TODO: We could just copy all the vregs to the stack slots in a simple loop 513*795d594fSAndroid Build Coastguard Worker// (or REP MOVSD) without looking at the shorty at all. (We could also drop 514*795d594fSAndroid Build Coastguard Worker// the "stack_index" from the macros for loading registers.) We could also do 515*795d594fSAndroid Build Coastguard Worker// that conditionally if argument word count > 6; otherwise we know that all 516*795d594fSAndroid Build Coastguard Worker// args fit into registers. 517*795d594fSAndroid Build Coastguard Worker.macro LOOP_RANGE_OVER_FPs shorty, arg_index, stack_index, finished 518*795d594fSAndroid Build Coastguard Worker1: // LOOP 519*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // bl := *shorty 520*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 521*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 522*795d594fSAndroid Build Coastguard Worker je VAR(finished) 523*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 524*795d594fSAndroid Build Coastguard Worker je 2f 525*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 526*795d594fSAndroid Build Coastguard Worker je 3f 527*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 528*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 529*795d594fSAndroid Build Coastguard Worker // Handle extra argument in arg array taken by a long. 530*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 531*795d594fSAndroid Build Coastguard Worker jne 1b 532*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 533*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 534*795d594fSAndroid Build Coastguard Worker jmp 1b // goto LOOP 535*795d594fSAndroid Build Coastguard Worker2: // FOUND_DOUBLE 536*795d594fSAndroid Build Coastguard Worker movq (rFP, REG_VAR(arg_index), 4), %rax 537*795d594fSAndroid Build Coastguard Worker movq %rax, 8(%rsp, REG_VAR(stack_index), 4) 538*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 539*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 540*795d594fSAndroid Build Coastguard Worker jmp 1b 541*795d594fSAndroid Build Coastguard Worker3: // FOUND_FLOAT 542*795d594fSAndroid Build Coastguard Worker movl (rFP, REG_VAR(arg_index), 4), %eax 543*795d594fSAndroid Build Coastguard Worker movl %eax, 8(%rsp, REG_VAR(stack_index), 4) 544*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 545*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 546*795d594fSAndroid Build Coastguard Worker jmp 1b 547*795d594fSAndroid Build Coastguard Worker.endm 548*795d594fSAndroid Build Coastguard Worker 549*795d594fSAndroid Build Coastguard Worker// Puts the next int/long/object argument in the expected register, 550*795d594fSAndroid Build Coastguard Worker// fetching values based on a range invoke. 551*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 552*795d594fSAndroid Build Coastguard Worker.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, stack_index, finished 553*795d594fSAndroid Build Coastguard Worker1: // LOOP 554*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 555*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 556*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 557*795d594fSAndroid Build Coastguard Worker je VAR(finished) 558*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 559*795d594fSAndroid Build Coastguard Worker je 2f 560*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 561*795d594fSAndroid Build Coastguard Worker je 3f 562*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 563*795d594fSAndroid Build Coastguard Worker je 4f 564*795d594fSAndroid Build Coastguard Worker movl (rFP, REG_VAR(arg_index), 4), REG_VAR(gpr_reg32) 565*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 566*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 567*795d594fSAndroid Build Coastguard Worker jmp 5f 568*795d594fSAndroid Build Coastguard Worker2: // FOUND_LONG 569*795d594fSAndroid Build Coastguard Worker movq (rFP, REG_VAR(arg_index), 4), REG_VAR(gpr_reg64) 570*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 571*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 572*795d594fSAndroid Build Coastguard Worker jmp 5f 573*795d594fSAndroid Build Coastguard Worker3: // SKIP_FLOAT 574*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 575*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 576*795d594fSAndroid Build Coastguard Worker jmp 1b 577*795d594fSAndroid Build Coastguard Worker4: // SKIP_DOUBLE 578*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 579*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 580*795d594fSAndroid Build Coastguard Worker jmp 1b 581*795d594fSAndroid Build Coastguard Worker5: 582*795d594fSAndroid Build Coastguard Worker.endm 583*795d594fSAndroid Build Coastguard Worker 584*795d594fSAndroid Build Coastguard Worker// Puts the next int/long/object argument in the expected stack slot, 585*795d594fSAndroid Build Coastguard Worker// fetching values based on a range invoke. 586*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 587*795d594fSAndroid Build Coastguard Worker.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished 588*795d594fSAndroid Build Coastguard Worker1: // LOOP 589*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 590*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 591*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 592*795d594fSAndroid Build Coastguard Worker je VAR(finished) 593*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 594*795d594fSAndroid Build Coastguard Worker je 2f 595*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 596*795d594fSAndroid Build Coastguard Worker je 3f 597*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 598*795d594fSAndroid Build Coastguard Worker je 4f 599*795d594fSAndroid Build Coastguard Worker movl (rFP, REG_VAR(arg_index), 4), %eax 600*795d594fSAndroid Build Coastguard Worker movl %eax, 8(%rsp, REG_VAR(stack_index), 4) 601*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 602*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 603*795d594fSAndroid Build Coastguard Worker jmp 1b 604*795d594fSAndroid Build Coastguard Worker2: // FOUND_LONG 605*795d594fSAndroid Build Coastguard Worker movq (rFP, REG_VAR(arg_index), 4), %rax 606*795d594fSAndroid Build Coastguard Worker movq %rax, 8(%rsp, REG_VAR(stack_index), 4) 607*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 608*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 609*795d594fSAndroid Build Coastguard Worker jmp 1b 610*795d594fSAndroid Build Coastguard Worker3: // SKIP_FLOAT 611*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 612*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(stack_index) 613*795d594fSAndroid Build Coastguard Worker jmp 1b 614*795d594fSAndroid Build Coastguard Worker4: // SKIP_DOUBLE 615*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 616*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(stack_index) 617*795d594fSAndroid Build Coastguard Worker jmp 1b 618*795d594fSAndroid Build Coastguard Worker.endm 619*795d594fSAndroid Build Coastguard Worker 620*795d594fSAndroid Build Coastguard Worker// Puts the next floating point parameter passed in physical register 621*795d594fSAndroid Build Coastguard Worker// in the expected dex register array entry. 622*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 623*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_SHORTY_STORING_XMMS xmm_reg, shorty, arg_index, fp, finished 624*795d594fSAndroid Build Coastguard Worker1: // LOOP 625*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 626*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 627*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 628*795d594fSAndroid Build Coastguard Worker je VAR(finished) 629*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 630*795d594fSAndroid Build Coastguard Worker je 2f 631*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 632*795d594fSAndroid Build Coastguard Worker je 3f 633*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 634*795d594fSAndroid Build Coastguard Worker // Handle extra argument in arg array taken by a long. 635*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 636*795d594fSAndroid Build Coastguard Worker jne 1b 637*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 638*795d594fSAndroid Build Coastguard Worker jmp 1b // goto LOOP 639*795d594fSAndroid Build Coastguard Worker2: // FOUND_DOUBLE 640*795d594fSAndroid Build Coastguard Worker movsd REG_VAR(xmm_reg),(REG_VAR(fp), REG_VAR(arg_index), 4) 641*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 642*795d594fSAndroid Build Coastguard Worker jmp 4f 643*795d594fSAndroid Build Coastguard Worker3: // FOUND_FLOAT 644*795d594fSAndroid Build Coastguard Worker movss REG_VAR(xmm_reg), (REG_VAR(fp), REG_VAR(arg_index), 4) 645*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 646*795d594fSAndroid Build Coastguard Worker4: 647*795d594fSAndroid Build Coastguard Worker.endm 648*795d594fSAndroid Build Coastguard Worker 649*795d594fSAndroid Build Coastguard Worker// Puts the next int/long/object parameter passed in physical register 650*795d594fSAndroid Build Coastguard Worker// in the expected dex register array entry, and in case of object in the 651*795d594fSAndroid Build Coastguard Worker// expected reference array entry. 652*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 653*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_reg64, gpr_reg32, shorty, arg_index, regs, refs, finished 654*795d594fSAndroid Build Coastguard Worker1: // LOOP 655*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 656*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 657*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 658*795d594fSAndroid Build Coastguard Worker je VAR(finished) 659*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 660*795d594fSAndroid Build Coastguard Worker je 2f 661*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 662*795d594fSAndroid Build Coastguard Worker je 3f 663*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 664*795d594fSAndroid Build Coastguard Worker je 4f 665*795d594fSAndroid Build Coastguard Worker movl REG_VAR(gpr_reg32), (REG_VAR(regs), REG_VAR(arg_index), 4) 666*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(76), %al // if (al != 'L') goto NOT_REFERENCE 667*795d594fSAndroid Build Coastguard Worker jne 6f 668*795d594fSAndroid Build Coastguard Worker movl REG_VAR(gpr_reg32), (REG_VAR(refs), REG_VAR(arg_index), 4) 669*795d594fSAndroid Build Coastguard Worker6: // NOT_REFERENCE 670*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 671*795d594fSAndroid Build Coastguard Worker jmp 5f 672*795d594fSAndroid Build Coastguard Worker2: // FOUND_LONG 673*795d594fSAndroid Build Coastguard Worker movq REG_VAR(gpr_reg64), (REG_VAR(regs), REG_VAR(arg_index), 4) 674*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 675*795d594fSAndroid Build Coastguard Worker jmp 5f 676*795d594fSAndroid Build Coastguard Worker3: // SKIP_FLOAT 677*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 678*795d594fSAndroid Build Coastguard Worker jmp 1b 679*795d594fSAndroid Build Coastguard Worker4: // SKIP_DOUBLE 680*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 681*795d594fSAndroid Build Coastguard Worker jmp 1b 682*795d594fSAndroid Build Coastguard Worker5: 683*795d594fSAndroid Build Coastguard Worker.endm 684*795d594fSAndroid Build Coastguard Worker 685*795d594fSAndroid Build Coastguard Worker// Puts the next floating point parameter passed in stack 686*795d594fSAndroid Build Coastguard Worker// in the expected dex register array entry. 687*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 688*795d594fSAndroid Build Coastguard Worker// 689*795d594fSAndroid Build Coastguard Worker// TODO: Or we could just spill regs to the reserved slots in the caller's 690*795d594fSAndroid Build Coastguard Worker// frame and copy all regs in a simple loop. This time, however, we would 691*795d594fSAndroid Build Coastguard Worker// need to look at the shorty anyway to look for the references. 692*795d594fSAndroid Build Coastguard Worker// (The trade-off is different for passing arguments and receiving them.) 693*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_FPs shorty, arg_index, regs, stack_ptr, finished 694*795d594fSAndroid Build Coastguard Worker1: // LOOP 695*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 696*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 697*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 698*795d594fSAndroid Build Coastguard Worker je VAR(finished) 699*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 700*795d594fSAndroid Build Coastguard Worker je 2f 701*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 702*795d594fSAndroid Build Coastguard Worker je 3f 703*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 704*795d594fSAndroid Build Coastguard Worker // Handle extra argument in arg array taken by a long. 705*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 706*795d594fSAndroid Build Coastguard Worker jne 1b 707*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 708*795d594fSAndroid Build Coastguard Worker jmp 1b // goto LOOP 709*795d594fSAndroid Build Coastguard Worker2: // FOUND_DOUBLE 710*795d594fSAndroid Build Coastguard Worker movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %rax 711*795d594fSAndroid Build Coastguard Worker movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 4) 712*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 713*795d594fSAndroid Build Coastguard Worker jmp 1b 714*795d594fSAndroid Build Coastguard Worker3: // FOUND_FLOAT 715*795d594fSAndroid Build Coastguard Worker movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax 716*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4) 717*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 718*795d594fSAndroid Build Coastguard Worker jmp 1b 719*795d594fSAndroid Build Coastguard Worker.endm 720*795d594fSAndroid Build Coastguard Worker 721*795d594fSAndroid Build Coastguard Worker// Puts the next int/long/object parameter passed in stack 722*795d594fSAndroid Build Coastguard Worker// in the expected dex register array entry, and in case of object in the 723*795d594fSAndroid Build Coastguard Worker// expected reference array entry. 724*795d594fSAndroid Build Coastguard Worker// Uses rax as temporary. 725*795d594fSAndroid Build Coastguard Worker.macro LOOP_OVER_INTs shorty, arg_index, regs, refs, stack_ptr, finished 726*795d594fSAndroid Build Coastguard Worker1: // LOOP 727*795d594fSAndroid Build Coastguard Worker movb (REG_VAR(shorty)), %al // al := *shorty 728*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 729*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto finished 730*795d594fSAndroid Build Coastguard Worker je VAR(finished) 731*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 732*795d594fSAndroid Build Coastguard Worker je 2f 733*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(76), %al // if (al == 'L') goto FOUND_REFERENCE 734*795d594fSAndroid Build Coastguard Worker je 6f 735*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 736*795d594fSAndroid Build Coastguard Worker je 3f 737*795d594fSAndroid Build Coastguard Worker cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 738*795d594fSAndroid Build Coastguard Worker je 4f 739*795d594fSAndroid Build Coastguard Worker movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax 740*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4) 741*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 742*795d594fSAndroid Build Coastguard Worker jmp 1b 743*795d594fSAndroid Build Coastguard Worker6: // FOUND_REFERENCE 744*795d594fSAndroid Build Coastguard Worker movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %eax 745*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(regs), REG_VAR(arg_index), 4) 746*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(refs), REG_VAR(arg_index), 4) 747*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 748*795d594fSAndroid Build Coastguard Worker jmp 1b 749*795d594fSAndroid Build Coastguard Worker2: // FOUND_LONG 750*795d594fSAndroid Build Coastguard Worker movq OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_index), 4), %rax 751*795d594fSAndroid Build Coastguard Worker movq %rax, (REG_VAR(regs), REG_VAR(arg_index), 4) 752*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 753*795d594fSAndroid Build Coastguard Worker jmp 1b 754*795d594fSAndroid Build Coastguard Worker3: // SKIP_FLOAT 755*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(1), REG_VAR(arg_index) 756*795d594fSAndroid Build Coastguard Worker jmp 1b 757*795d594fSAndroid Build Coastguard Worker4: // SKIP_DOUBLE 758*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(2), REG_VAR(arg_index) 759*795d594fSAndroid Build Coastguard Worker jmp 1b 760*795d594fSAndroid Build Coastguard Worker.endm 761*795d594fSAndroid Build Coastguard Worker 762*795d594fSAndroid Build Coastguard Worker// Increase method hotness and do suspend check before starting executing the method. 763*795d594fSAndroid Build Coastguard Worker.macro START_EXECUTING_INSTRUCTIONS 764*795d594fSAndroid Build Coastguard Worker movq (%rsp), %rdi 765*795d594fSAndroid Build Coastguard Worker movzwl ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi), %esi 766*795d594fSAndroid Build Coastguard Worker#if (NTERP_HOTNESS_VALUE != 0) 767*795d594fSAndroid Build Coastguard Worker#error Expected 0 for hotness value 768*795d594fSAndroid Build Coastguard Worker#endif 769*795d594fSAndroid Build Coastguard Worker // If the counter is at zero, handle this in the runtime. 770*795d594fSAndroid Build Coastguard Worker testl %esi, %esi 771*795d594fSAndroid Build Coastguard Worker je 3f 772*795d594fSAndroid Build Coastguard Worker // Update counter. 773*795d594fSAndroid Build Coastguard Worker addl $$-1, %esi 774*795d594fSAndroid Build Coastguard Worker movw %si, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi) 775*795d594fSAndroid Build Coastguard Worker1: 776*795d594fSAndroid Build Coastguard Worker DO_SUSPEND_CHECK continue_label=2f 777*795d594fSAndroid Build Coastguard Worker2: 778*795d594fSAndroid Build Coastguard Worker FETCH_INST 779*795d594fSAndroid Build Coastguard Worker GOTO_NEXT 780*795d594fSAndroid Build Coastguard Worker3: 781*795d594fSAndroid Build Coastguard Worker CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=4f, if_not_hot=1b 782*795d594fSAndroid Build Coastguard Worker4: 783*795d594fSAndroid Build Coastguard Worker movq $$0, %rsi 784*795d594fSAndroid Build Coastguard Worker movq rFP, %rdx 785*795d594fSAndroid Build Coastguard Worker call nterp_hot_method 786*795d594fSAndroid Build Coastguard Worker jmp 2b 787*795d594fSAndroid Build Coastguard Worker.endm 788*795d594fSAndroid Build Coastguard Worker 789*795d594fSAndroid Build Coastguard Worker.macro SPILL_ALL_CALLEE_SAVES 790*795d594fSAndroid Build Coastguard Worker PUSH r15 791*795d594fSAndroid Build Coastguard Worker PUSH r14 792*795d594fSAndroid Build Coastguard Worker PUSH r13 793*795d594fSAndroid Build Coastguard Worker PUSH r12 794*795d594fSAndroid Build Coastguard Worker PUSH rbp 795*795d594fSAndroid Build Coastguard Worker PUSH rbx 796*795d594fSAndroid Build Coastguard Worker SETUP_FP_CALLEE_SAVE_FRAME 797*795d594fSAndroid Build Coastguard Worker.endm 798*795d594fSAndroid Build Coastguard Worker 799*795d594fSAndroid Build Coastguard Worker.macro RESTORE_ALL_CALLEE_SAVES 800*795d594fSAndroid Build Coastguard Worker RESTORE_FP_CALLEE_SAVE_FRAME 801*795d594fSAndroid Build Coastguard Worker POP rbx 802*795d594fSAndroid Build Coastguard Worker POP rbp 803*795d594fSAndroid Build Coastguard Worker POP r12 804*795d594fSAndroid Build Coastguard Worker POP r13 805*795d594fSAndroid Build Coastguard Worker POP r14 806*795d594fSAndroid Build Coastguard Worker POP r15 807*795d594fSAndroid Build Coastguard Worker.endm 808*795d594fSAndroid Build Coastguard Worker 809*795d594fSAndroid Build Coastguard Worker// Helper to setup the stack after doing a nterp to nterp call. This will setup: 810*795d594fSAndroid Build Coastguard Worker// - rNEW_FP: the new pointer to dex registers 811*795d594fSAndroid Build Coastguard Worker// - rNEW_REFS: the new pointer to references 812*795d594fSAndroid Build Coastguard Worker// - rPC: the new PC pointer to execute 813*795d594fSAndroid Build Coastguard Worker// - edi: number of arguments 814*795d594fSAndroid Build Coastguard Worker// - ecx: first dex register 815*795d594fSAndroid Build Coastguard Worker// 816*795d594fSAndroid Build Coastguard Worker// This helper expects: 817*795d594fSAndroid Build Coastguard Worker// - rax to contain the code item 818*795d594fSAndroid Build Coastguard Worker.macro SETUP_STACK_FOR_INVOKE 819*795d594fSAndroid Build Coastguard Worker // We do the same stack overflow check as the compiler. See CanMethodUseNterp 820*795d594fSAndroid Build Coastguard Worker // in how we limit the maximum nterp frame size. 821*795d594fSAndroid Build Coastguard Worker testq %rax, -STACK_OVERFLOW_RESERVED_BYTES(%rsp) 822*795d594fSAndroid Build Coastguard Worker 823*795d594fSAndroid Build Coastguard Worker // Spill all callee saves to have a consistent stack frame whether we 824*795d594fSAndroid Build Coastguard Worker // are called by compiled code or nterp. 825*795d594fSAndroid Build Coastguard Worker SPILL_ALL_CALLEE_SAVES 826*795d594fSAndroid Build Coastguard Worker 827*795d594fSAndroid Build Coastguard Worker // Setup the frame. 828*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FRAME %rax, rNEW_REFS, rNEW_REFS32, rNEW_FP, CFI_NEW_REFS, load_ins=0 829*795d594fSAndroid Build Coastguard Worker // Make r11 point to the top of the dex register array. 830*795d594fSAndroid Build Coastguard Worker leaq (rNEW_FP, %rbx, 4), %r11 831*795d594fSAndroid Build Coastguard Worker 832*795d594fSAndroid Build Coastguard Worker // Fetch instruction information before replacing rPC. 833*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %edi 834*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %ecx 835*795d594fSAndroid Build Coastguard Worker 836*795d594fSAndroid Build Coastguard Worker // Set the dex pc pointer. 837*795d594fSAndroid Build Coastguard Worker movq %rax, rPC 838*795d594fSAndroid Build Coastguard Worker CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) 839*795d594fSAndroid Build Coastguard Worker.endm 840*795d594fSAndroid Build Coastguard Worker 841*795d594fSAndroid Build Coastguard Worker// Setup arguments based on a non-range nterp to nterp call, and start executing 842*795d594fSAndroid Build Coastguard Worker// the method. We expect: 843*795d594fSAndroid Build Coastguard Worker// - rNEW_FP: the new pointer to dex registers 844*795d594fSAndroid Build Coastguard Worker// - rNEW_REFS: the new pointer to references 845*795d594fSAndroid Build Coastguard Worker// - rPC: the new PC pointer to execute 846*795d594fSAndroid Build Coastguard Worker// - edi: number of arguments 847*795d594fSAndroid Build Coastguard Worker// - ecx: first dex register 848*795d594fSAndroid Build Coastguard Worker// - r11: top of dex register array 849*795d594fSAndroid Build Coastguard Worker// - esi: receiver if non-static. 850*795d594fSAndroid Build Coastguard Worker.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 851*795d594fSAndroid Build Coastguard Worker // Now all temporary registers (except r11 containing top of registers array) 852*795d594fSAndroid Build Coastguard Worker // are available, copy the parameters. 853*795d594fSAndroid Build Coastguard Worker // /* op vA, vB, {vC...vG} */ 854*795d594fSAndroid Build Coastguard Worker movl %edi, %eax 855*795d594fSAndroid Build Coastguard Worker shrl $$4, %eax # Number of arguments 856*795d594fSAndroid Build Coastguard Worker jz 6f # shl sets the Z flag 857*795d594fSAndroid Build Coastguard Worker movq MACRO_LITERAL(-1), %r10 858*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(2), %eax 859*795d594fSAndroid Build Coastguard Worker jl 1f 860*795d594fSAndroid Build Coastguard Worker je 2f 861*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(4), %eax 862*795d594fSAndroid Build Coastguard Worker jl 3f 863*795d594fSAndroid Build Coastguard Worker je 4f 864*795d594fSAndroid Build Coastguard Worker 865*795d594fSAndroid Build Coastguard Worker // We use a decrementing r10 to store references relative 866*795d594fSAndroid Build Coastguard Worker // to rNEW_FP and dex registers relative to r11. 867*795d594fSAndroid Build Coastguard Worker // 868*795d594fSAndroid Build Coastguard Worker // TODO: We could set up r10 as the number of registers (this can be an additional output from 869*795d594fSAndroid Build Coastguard Worker // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg to 870*795d594fSAndroid Build Coastguard Worker // (rNEW_FP, r10, 4) and (rNEW_REFS, r10, 4). 871*795d594fSAndroid Build Coastguard Worker // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS. 872*795d594fSAndroid Build Coastguard Worker5: 873*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(15), %rdi 874*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT %edx, %rdi 875*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 4) 876*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rdi 877*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 4) 878*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(1), %r10 879*795d594fSAndroid Build Coastguard Worker4: 880*795d594fSAndroid Build Coastguard Worker movl %ecx, %eax 881*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(12), %eax 882*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT %edx, %rax 883*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 4) 884*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rax 885*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 4) 886*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(1), %r10 887*795d594fSAndroid Build Coastguard Worker3: 888*795d594fSAndroid Build Coastguard Worker movl %ecx, %eax 889*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(8), %eax 890*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %eax 891*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT %edx, %rax 892*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 4) 893*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rax 894*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 4) 895*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(1), %r10 896*795d594fSAndroid Build Coastguard Worker2: 897*795d594fSAndroid Build Coastguard Worker movl %ecx, %eax 898*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(4), %eax 899*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %eax 900*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT %edx, %rax 901*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 4) 902*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rax 903*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 4) 904*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(1), %r10 905*795d594fSAndroid Build Coastguard Worker1: 906*795d594fSAndroid Build Coastguard Worker .if \is_string_init 907*795d594fSAndroid Build Coastguard Worker // Ignore the first argument 908*795d594fSAndroid Build Coastguard Worker .elseif \is_static 909*795d594fSAndroid Build Coastguard Worker movl %ecx, %eax 910*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(0x000f), %rax 911*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT %edx, %rax 912*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 4) 913*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rax 914*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 4) 915*795d594fSAndroid Build Coastguard Worker .else 916*795d594fSAndroid Build Coastguard Worker movl %esi, (rNEW_FP, %r10, 4) 917*795d594fSAndroid Build Coastguard Worker movl %esi, (%r11, %r10, 4) 918*795d594fSAndroid Build Coastguard Worker .endif 919*795d594fSAndroid Build Coastguard Worker 920*795d594fSAndroid Build Coastguard Worker6: 921*795d594fSAndroid Build Coastguard Worker // Start executing the method. 922*795d594fSAndroid Build Coastguard Worker movq rNEW_FP, rFP 923*795d594fSAndroid Build Coastguard Worker movq rNEW_REFS, rREFS 924*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, ((6 + 4 + 1) * 8) 925*795d594fSAndroid Build Coastguard Worker START_EXECUTING_INSTRUCTIONS 926*795d594fSAndroid Build Coastguard Worker.endm 927*795d594fSAndroid Build Coastguard Worker 928*795d594fSAndroid Build Coastguard Worker// Setup arguments based on a range nterp to nterp call, and start executing 929*795d594fSAndroid Build Coastguard Worker// the method. 930*795d594fSAndroid Build Coastguard Worker.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 931*795d594fSAndroid Build Coastguard Worker // edi is number of arguments 932*795d594fSAndroid Build Coastguard Worker // ecx is first register 933*795d594fSAndroid Build Coastguard Worker movq MACRO_LITERAL(-4), %r10 934*795d594fSAndroid Build Coastguard Worker .if \is_string_init 935*795d594fSAndroid Build Coastguard Worker // Ignore the first argument 936*795d594fSAndroid Build Coastguard Worker subl $$1, %edi 937*795d594fSAndroid Build Coastguard Worker addl $$1, %ecx 938*795d594fSAndroid Build Coastguard Worker .elseif !\is_static 939*795d594fSAndroid Build Coastguard Worker subl $$1, %edi 940*795d594fSAndroid Build Coastguard Worker addl $$1, %ecx 941*795d594fSAndroid Build Coastguard Worker .endif 942*795d594fSAndroid Build Coastguard Worker 943*795d594fSAndroid Build Coastguard Worker testl %edi, %edi 944*795d594fSAndroid Build Coastguard Worker je 2f 945*795d594fSAndroid Build Coastguard Worker leaq (rREFS, %rcx, 4), %rax # pointer to first argument in reference array 946*795d594fSAndroid Build Coastguard Worker leaq (%rax, %rdi, 4), %rax # pointer to last argument in reference array 947*795d594fSAndroid Build Coastguard Worker leaq (rFP, %rcx, 4), %rcx # pointer to first argument in register array 948*795d594fSAndroid Build Coastguard Worker leaq (%rcx, %rdi, 4), %rdi # pointer to last argument in register array 949*795d594fSAndroid Build Coastguard Worker // TODO: Same comment for copying arguments as in SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE. 950*795d594fSAndroid Build Coastguard Worker1: 951*795d594fSAndroid Build Coastguard Worker movl -4(%rax), %edx 952*795d594fSAndroid Build Coastguard Worker movl %edx, (rNEW_FP, %r10, 1) 953*795d594fSAndroid Build Coastguard Worker movl -4(%rdi), %edx 954*795d594fSAndroid Build Coastguard Worker movl %edx, (%r11, %r10, 1) 955*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(4), %r10 956*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(4), %rax 957*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(4), %rdi 958*795d594fSAndroid Build Coastguard Worker cmpq %rcx, %rdi 959*795d594fSAndroid Build Coastguard Worker jne 1b 960*795d594fSAndroid Build Coastguard Worker 961*795d594fSAndroid Build Coastguard Worker2: 962*795d594fSAndroid Build Coastguard Worker .if \is_string_init 963*795d594fSAndroid Build Coastguard Worker // Ignore first argument 964*795d594fSAndroid Build Coastguard Worker .elseif !\is_static 965*795d594fSAndroid Build Coastguard Worker movl %esi, (rNEW_FP, %r10, 1) 966*795d594fSAndroid Build Coastguard Worker movl %esi, (%r11, %r10, 1) 967*795d594fSAndroid Build Coastguard Worker .endif 968*795d594fSAndroid Build Coastguard Worker movq rNEW_FP, rFP 969*795d594fSAndroid Build Coastguard Worker movq rNEW_REFS, rREFS 970*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, ((6 + 4 + 1) * 8) 971*795d594fSAndroid Build Coastguard Worker START_EXECUTING_INSTRUCTIONS 972*795d594fSAndroid Build Coastguard Worker.endm 973*795d594fSAndroid Build Coastguard Worker 974*795d594fSAndroid Build Coastguard Worker.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom 975*795d594fSAndroid Build Coastguard Worker push %rdi 976*795d594fSAndroid Build Coastguard Worker push %rsi 977*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 978*795d594fSAndroid Build Coastguard Worker movq 16(%rsp), %rdi 979*795d594fSAndroid Build Coastguard Worker movq rPC, %rsi 980*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShortyFromInvokePolymorphic) 981*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 982*795d594fSAndroid Build Coastguard Worker movq 16(%rsp), %rdi 983*795d594fSAndroid Build Coastguard Worker movq rPC, %rsi 984*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShortyFromInvokeCustom) 985*795d594fSAndroid Build Coastguard Worker .elseif \is_interface 986*795d594fSAndroid Build Coastguard Worker movq 16(%rsp), %rdi 987*795d594fSAndroid Build Coastguard Worker movzwl 2(rPC), %esi 988*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShortyFromMethodId) 989*795d594fSAndroid Build Coastguard Worker .else 990*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShorty) 991*795d594fSAndroid Build Coastguard Worker .endif 992*795d594fSAndroid Build Coastguard Worker pop %rsi 993*795d594fSAndroid Build Coastguard Worker pop %rdi 994*795d594fSAndroid Build Coastguard Worker movq %rax, \dest 995*795d594fSAndroid Build Coastguard Worker.endm 996*795d594fSAndroid Build Coastguard Worker 997*795d594fSAndroid Build Coastguard Worker.macro GET_SHORTY_SLOW_PATH dest, is_interface 998*795d594fSAndroid Build Coastguard Worker // Save all registers that can hold arguments in the fast path. 999*795d594fSAndroid Build Coastguard Worker push %rdi 1000*795d594fSAndroid Build Coastguard Worker push %rsi 1001*795d594fSAndroid Build Coastguard Worker push %rdx 1002*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(8), %rsp 1003*795d594fSAndroid Build Coastguard Worker mov %xmm0, (%rsp) 1004*795d594fSAndroid Build Coastguard Worker .if \is_interface 1005*795d594fSAndroid Build Coastguard Worker movq 32(%rsp), %rdi 1006*795d594fSAndroid Build Coastguard Worker movzwl 2(rPC), %esi 1007*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShortyFromMethodId) 1008*795d594fSAndroid Build Coastguard Worker .else 1009*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShorty) 1010*795d594fSAndroid Build Coastguard Worker .endif 1011*795d594fSAndroid Build Coastguard Worker mov (%rsp), %xmm0 1012*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(8), %rsp 1013*795d594fSAndroid Build Coastguard Worker pop %rdx 1014*795d594fSAndroid Build Coastguard Worker pop %rsi 1015*795d594fSAndroid Build Coastguard Worker pop %rdi 1016*795d594fSAndroid Build Coastguard Worker movq %rax, \dest 1017*795d594fSAndroid Build Coastguard Worker.endm 1018*795d594fSAndroid Build Coastguard Worker 1019*795d594fSAndroid Build Coastguard Worker// Uses r9 as temporary. 1020*795d594fSAndroid Build Coastguard Worker.macro DO_ENTRY_POINT_CHECK call_compiled_code 1021*795d594fSAndroid Build Coastguard Worker // On entry, the method is %rdi, the instance is %rsi 1022*795d594fSAndroid Build Coastguard Worker leaq ExecuteNterpImpl(%rip), %r9 1023*795d594fSAndroid Build Coastguard Worker cmpq %r9, ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) 1024*795d594fSAndroid Build Coastguard Worker jne VAR(call_compiled_code) 1025*795d594fSAndroid Build Coastguard Worker 1026*795d594fSAndroid Build Coastguard Worker movq ART_METHOD_DATA_OFFSET_64(%rdi), %rax 1027*795d594fSAndroid Build Coastguard Worker.endm 1028*795d594fSAndroid Build Coastguard Worker 1029*795d594fSAndroid Build Coastguard Worker// Uses r9 and r10 as temporary 1030*795d594fSAndroid Build Coastguard Worker.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value 1031*795d594fSAndroid Build Coastguard Worker movq rREFS, %r9 1032*795d594fSAndroid Build Coastguard Worker movq rFP, %r10 1033*795d594fSAndroid Build Coastguard Worker1: 1034*795d594fSAndroid Build Coastguard Worker cmpl (%r9), \old_value 1035*795d594fSAndroid Build Coastguard Worker jne 2f 1036*795d594fSAndroid Build Coastguard Worker movl \new_value, (%r9) 1037*795d594fSAndroid Build Coastguard Worker movl \new_value, (%r10) 1038*795d594fSAndroid Build Coastguard Worker2: 1039*795d594fSAndroid Build Coastguard Worker addq $$4, %r9 1040*795d594fSAndroid Build Coastguard Worker addq $$4, %r10 1041*795d594fSAndroid Build Coastguard Worker cmpq %r9, rFP 1042*795d594fSAndroid Build Coastguard Worker jne 1b 1043*795d594fSAndroid Build Coastguard Worker.endm 1044*795d594fSAndroid Build Coastguard Worker 1045*795d594fSAndroid Build Coastguard Worker.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0 1046*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1047*795d594fSAndroid Build Coastguard Worker // We always go to compiled code for polymorphic calls. 1048*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1049*795d594fSAndroid Build Coastguard Worker // We always go to compiled code for custom calls. 1050*795d594fSAndroid Build Coastguard Worker .else 1051*795d594fSAndroid Build Coastguard Worker DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix 1052*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1053*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_string_init_non_range 1054*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1055*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_static_non_range 1056*795d594fSAndroid Build Coastguard Worker .else 1057*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_instance_non_range 1058*795d594fSAndroid Build Coastguard Worker .endif 1059*795d594fSAndroid Build Coastguard Worker jmp .Ldone_return_\suffix 1060*795d594fSAndroid Build Coastguard Worker .endif 1061*795d594fSAndroid Build Coastguard Worker 1062*795d594fSAndroid Build Coastguard Worker.Lcall_compiled_code_\suffix: 1063*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1064*795d594fSAndroid Build Coastguard Worker // No fast path for polymorphic calls. 1065*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1066*795d594fSAndroid Build Coastguard Worker // No fast path for custom calls. 1067*795d594fSAndroid Build Coastguard Worker .elseif \is_string_init 1068*795d594fSAndroid Build Coastguard Worker // No fast path for string.init. 1069*795d594fSAndroid Build Coastguard Worker .else 1070*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1071*795d594fSAndroid Build Coastguard Worker je .Lfast_path_with_few_args_\suffix 1072*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %r9d 1073*795d594fSAndroid Build Coastguard Worker movl %r9d, %ebp 1074*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(4), %ebp # Number of arguments 1075*795d594fSAndroid Build Coastguard Worker .if \is_static 1076*795d594fSAndroid Build Coastguard Worker jz .Linvoke_fast_path_\suffix # shl sets the Z flag 1077*795d594fSAndroid Build Coastguard Worker .else 1078*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(1), %ebp 1079*795d594fSAndroid Build Coastguard Worker je .Linvoke_fast_path_\suffix 1080*795d594fSAndroid Build Coastguard Worker .endif 1081*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d 1082*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(2), %ebp 1083*795d594fSAndroid Build Coastguard Worker .if \is_static 1084*795d594fSAndroid Build Coastguard Worker jl .Lone_arg_fast_path_\suffix 1085*795d594fSAndroid Build Coastguard Worker .endif 1086*795d594fSAndroid Build Coastguard Worker je .Ltwo_args_fast_path_\suffix 1087*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(4), %ebp 1088*795d594fSAndroid Build Coastguard Worker jl .Lthree_args_fast_path_\suffix 1089*795d594fSAndroid Build Coastguard Worker je .Lfour_args_fast_path_\suffix 1090*795d594fSAndroid Build Coastguard Worker 1091*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %r9d 1092*795d594fSAndroid Build Coastguard Worker GET_VREG %r9d, %r9 1093*795d594fSAndroid Build Coastguard Worker.Lfour_args_fast_path_\suffix: 1094*795d594fSAndroid Build Coastguard Worker movl %r11d, %r8d 1095*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(12), %r8d 1096*795d594fSAndroid Build Coastguard Worker GET_VREG %r8d, %r8 1097*795d594fSAndroid Build Coastguard Worker.Lthree_args_fast_path_\suffix: 1098*795d594fSAndroid Build Coastguard Worker movl %r11d, %ecx 1099*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(8), %ecx 1100*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %ecx 1101*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rcx 1102*795d594fSAndroid Build Coastguard Worker.Ltwo_args_fast_path_\suffix: 1103*795d594fSAndroid Build Coastguard Worker movl %r11d, %edx 1104*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(4), %edx 1105*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %edx 1106*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %rdx 1107*795d594fSAndroid Build Coastguard Worker.Lone_arg_fast_path_\suffix: 1108*795d594fSAndroid Build Coastguard Worker .if \is_static 1109*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %r11d 1110*795d594fSAndroid Build Coastguard Worker GET_VREG %esi, %r11 1111*795d594fSAndroid Build Coastguard Worker .else 1112*795d594fSAndroid Build Coastguard Worker // First argument already in %esi. 1113*795d594fSAndroid Build Coastguard Worker .endif 1114*795d594fSAndroid Build Coastguard Worker.Linvoke_fast_path_\suffix: 1115*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1116*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1117*795d594fSAndroid Build Coastguard Worker 1118*795d594fSAndroid Build Coastguard Worker.Lfast_path_with_few_args_\suffix: 1119*795d594fSAndroid Build Coastguard Worker // Fast path when we have zero or one argument (modulo 'this'). If there 1120*795d594fSAndroid Build Coastguard Worker // is one argument, we can put it in both floating point and core register. 1121*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %r9d 1122*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(4), %r9d # Number of arguments 1123*795d594fSAndroid Build Coastguard Worker .if \is_static 1124*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(1), %r9d 1125*795d594fSAndroid Build Coastguard Worker jl .Linvoke_with_few_args_\suffix 1126*795d594fSAndroid Build Coastguard Worker jne .Lget_shorty_\suffix 1127*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r9d 1128*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %r9d // dex register of first argument 1129*795d594fSAndroid Build Coastguard Worker GET_VREG %esi, %r9 1130*795d594fSAndroid Build Coastguard Worker movd %esi, %xmm0 1131*795d594fSAndroid Build Coastguard Worker .else 1132*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(2), %r9d 1133*795d594fSAndroid Build Coastguard Worker jl .Linvoke_with_few_args_\suffix 1134*795d594fSAndroid Build Coastguard Worker jne .Lget_shorty_\suffix 1135*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r9d 1136*795d594fSAndroid Build Coastguard Worker shrl MACRO_LITERAL(4), %r9d 1137*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xf), %r9d // dex register of second argument 1138*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %r9 1139*795d594fSAndroid Build Coastguard Worker movd %edx, %xmm0 1140*795d594fSAndroid Build Coastguard Worker .endif 1141*795d594fSAndroid Build Coastguard Worker.Linvoke_with_few_args_\suffix: 1142*795d594fSAndroid Build Coastguard Worker // Check if the next instruction is move-result or move-result-wide. 1143*795d594fSAndroid Build Coastguard Worker // If it is, we fetch the shorty and jump to the regular invocation. 1144*795d594fSAndroid Build Coastguard Worker movzwq 6(rPC), %r9 1145*795d594fSAndroid Build Coastguard Worker andl MACRO_LITERAL(0xfe), %r9d 1146*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(0x0a), %r9d 1147*795d594fSAndroid Build Coastguard Worker je .Lget_shorty_and_invoke_\suffix 1148*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1149*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1150*795d594fSAndroid Build Coastguard Worker.Lget_shorty_and_invoke_\suffix: 1151*795d594fSAndroid Build Coastguard Worker .if \is_interface 1152*795d594fSAndroid Build Coastguard Worker // Save interface method, used for conflict resolution, in a callee-save register. 1153*795d594fSAndroid Build Coastguard Worker movq %rax, %xmm12 1154*795d594fSAndroid Build Coastguard Worker .endif 1155*795d594fSAndroid Build Coastguard Worker GET_SHORTY_SLOW_PATH rINSTq, \is_interface 1156*795d594fSAndroid Build Coastguard Worker jmp .Lgpr_setup_finished_\suffix 1157*795d594fSAndroid Build Coastguard Worker .endif 1158*795d594fSAndroid Build Coastguard Worker 1159*795d594fSAndroid Build Coastguard Worker.Lget_shorty_\suffix: 1160*795d594fSAndroid Build Coastguard Worker .if \is_interface 1161*795d594fSAndroid Build Coastguard Worker // Save interface method, used for conflict resolution, in a callee-save register. 1162*795d594fSAndroid Build Coastguard Worker movq %rax, %xmm12 1163*795d594fSAndroid Build Coastguard Worker .endif 1164*795d594fSAndroid Build Coastguard Worker GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom 1165*795d594fSAndroid Build Coastguard Worker // From this point: 1166*795d594fSAndroid Build Coastguard Worker // - rISNTq contains shorty (in callee-save to switch over return value after call). 1167*795d594fSAndroid Build Coastguard Worker // - rdi contains method 1168*795d594fSAndroid Build Coastguard Worker // - rsi contains 'this' pointer for instance method. 1169*795d594fSAndroid Build Coastguard Worker leaq 1(rINSTq), %r9 // shorty + 1 ; ie skip return arg character 1170*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 1171*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1172*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), %r11 1173*795d594fSAndroid Build Coastguard Worker movq $$1, %r10 // ignore first argument 1174*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1175*795d594fSAndroid Build Coastguard Worker movq $$0, %r10 // arg_index 1176*795d594fSAndroid Build Coastguard Worker .else 1177*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), %r11 1178*795d594fSAndroid Build Coastguard Worker movq $$1, %r10 // arg_index 1179*795d594fSAndroid Build Coastguard Worker .endif 1180*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_XMMS xmm0, r11, r9, r10, .Lxmm_setup_finished_\suffix 1181*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_XMMS xmm1, r11, r9, r10, .Lxmm_setup_finished_\suffix 1182*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_XMMS xmm2, r11, r9, r10, .Lxmm_setup_finished_\suffix 1183*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_XMMS xmm3, r11, r9, r10, .Lxmm_setup_finished_\suffix 1184*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_XMMS xmm4, r11, r9, r10, .Lxmm_setup_finished_\suffix 1185*795d594fSAndroid Build Coastguard Worker.Lxmm_setup_finished_\suffix: 1186*795d594fSAndroid Build Coastguard Worker leaq 1(rINSTq), %r9 // shorty + 1 ; ie skip return arg character 1187*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 1188*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1189*795d594fSAndroid Build Coastguard Worker movq $$1, %r10 // ignore first argument 1190*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), %r11 1191*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r9, r10, .Lgpr_setup_finished_\suffix 1192*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1193*795d594fSAndroid Build Coastguard Worker movq $$0, %r10 // arg_index 1194*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r9, r10, .Lgpr_setup_finished_\suffix 1195*795d594fSAndroid Build Coastguard Worker .else 1196*795d594fSAndroid Build Coastguard Worker shrq MACRO_LITERAL(4), %r11 1197*795d594fSAndroid Build Coastguard Worker movq $$1, %r10 // arg_index 1198*795d594fSAndroid Build Coastguard Worker .endif 1199*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, r11, r9, r10, .Lgpr_setup_finished_\suffix 1200*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, r11, r9, r10, .Lgpr_setup_finished_\suffix 1201*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, r11, r9, r10, .Lgpr_setup_finished_\suffix 1202*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, r11, r9, r10, .Lgpr_setup_finished_\suffix 1203*795d594fSAndroid Build Coastguard Worker.Lgpr_setup_finished_\suffix: 1204*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1205*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_invoke_polymorphic) 1206*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1207*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_invoke_custom) 1208*795d594fSAndroid Build Coastguard Worker .else 1209*795d594fSAndroid Build Coastguard Worker .if \is_interface 1210*795d594fSAndroid Build Coastguard Worker movq %xmm12, %rax 1211*795d594fSAndroid Build Coastguard Worker .endif 1212*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1213*795d594fSAndroid Build Coastguard Worker .endif 1214*795d594fSAndroid Build Coastguard Worker cmpb LITERAL(68), (rINSTq) // Test if result type char == 'D'. 1215*795d594fSAndroid Build Coastguard Worker je .Lreturn_double_\suffix 1216*795d594fSAndroid Build Coastguard Worker cmpb LITERAL(70), (rINSTq) // Test if result type char == 'F'. 1217*795d594fSAndroid Build Coastguard Worker jne .Ldone_return_\suffix 1218*795d594fSAndroid Build Coastguard Worker.Lreturn_float_\suffix: 1219*795d594fSAndroid Build Coastguard Worker movd %xmm0, %eax 1220*795d594fSAndroid Build Coastguard Worker jmp .Ldone_return_\suffix 1221*795d594fSAndroid Build Coastguard Worker.Lreturn_double_\suffix: 1222*795d594fSAndroid Build Coastguard Worker movq %xmm0, %rax 1223*795d594fSAndroid Build Coastguard Worker.Ldone_return_\suffix: 1224*795d594fSAndroid Build Coastguard Worker /* resume execution of caller */ 1225*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1226*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 1227*795d594fSAndroid Build Coastguard Worker andq $$0xf, %r11 1228*795d594fSAndroid Build Coastguard Worker GET_VREG %esi, %r11 1229*795d594fSAndroid Build Coastguard Worker UPDATE_REGISTERS_FOR_STRING_INIT %esi, %eax 1230*795d594fSAndroid Build Coastguard Worker .endif 1231*795d594fSAndroid Build Coastguard Worker 1232*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1233*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 4 1234*795d594fSAndroid Build Coastguard Worker .else 1235*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1236*795d594fSAndroid Build Coastguard Worker .endif 1237*795d594fSAndroid Build Coastguard Worker.endm 1238*795d594fSAndroid Build Coastguard Worker 1239*795d594fSAndroid Build Coastguard Worker.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0 1240*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1241*795d594fSAndroid Build Coastguard Worker // We always go to compiled code for polymorphic calls. 1242*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1243*795d594fSAndroid Build Coastguard Worker // We always go to compiled code for custom calls. 1244*795d594fSAndroid Build Coastguard Worker .else 1245*795d594fSAndroid Build Coastguard Worker DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix 1246*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1247*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_string_init_range 1248*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1249*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_static_range 1250*795d594fSAndroid Build Coastguard Worker .else 1251*795d594fSAndroid Build Coastguard Worker call nterp_to_nterp_instance_range 1252*795d594fSAndroid Build Coastguard Worker .endif 1253*795d594fSAndroid Build Coastguard Worker jmp .Ldone_return_range_\suffix 1254*795d594fSAndroid Build Coastguard Worker .endif 1255*795d594fSAndroid Build Coastguard Worker 1256*795d594fSAndroid Build Coastguard Worker.Lcall_compiled_code_range_\suffix: 1257*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1258*795d594fSAndroid Build Coastguard Worker // No fast path for polymorphic calls. 1259*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1260*795d594fSAndroid Build Coastguard Worker // No fast path for custom calls. 1261*795d594fSAndroid Build Coastguard Worker .elseif \is_string_init 1262*795d594fSAndroid Build Coastguard Worker // No fast path for string.init. 1263*795d594fSAndroid Build Coastguard Worker .else 1264*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1265*795d594fSAndroid Build Coastguard Worker je .Lfast_path_with_few_args_range_\suffix 1266*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %r9d // number of arguments 1267*795d594fSAndroid Build Coastguard Worker .if \is_static 1268*795d594fSAndroid Build Coastguard Worker testl %r9d, %r9d 1269*795d594fSAndroid Build Coastguard Worker je .Linvoke_fast_path_range_\suffix 1270*795d594fSAndroid Build Coastguard Worker .else 1271*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(1), %r9d 1272*795d594fSAndroid Build Coastguard Worker je .Linvoke_fast_path_range_\suffix 1273*795d594fSAndroid Build Coastguard Worker .endif 1274*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // dex register of first argument 1275*795d594fSAndroid Build Coastguard Worker leaq (rFP, %r11, 4), %r11 // location of first dex register value 1276*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(2), %r9d 1277*795d594fSAndroid Build Coastguard Worker .if \is_static 1278*795d594fSAndroid Build Coastguard Worker jl .Lone_arg_fast_path_range_\suffix 1279*795d594fSAndroid Build Coastguard Worker .endif 1280*795d594fSAndroid Build Coastguard Worker je .Ltwo_args_fast_path_range_\suffix 1281*795d594fSAndroid Build Coastguard Worker cmp MACRO_LITERAL(4), %r9d 1282*795d594fSAndroid Build Coastguard Worker jl .Lthree_args_fast_path_range_\suffix 1283*795d594fSAndroid Build Coastguard Worker je .Lfour_args_fast_path_range_\suffix 1284*795d594fSAndroid Build Coastguard Worker cmp MACRO_LITERAL(5), %r9d 1285*795d594fSAndroid Build Coastguard Worker je .Lfive_args_fast_path_range_\suffix 1286*795d594fSAndroid Build Coastguard Worker 1287*795d594fSAndroid Build Coastguard Worker.Lloop_over_fast_path_range_\suffix: 1288*795d594fSAndroid Build Coastguard Worker subl MACRO_LITERAL(1), %r9d 1289*795d594fSAndroid Build Coastguard Worker movl (%r11, %r9, 4), %r8d 1290*795d594fSAndroid Build Coastguard Worker movl %r8d, 8(%rsp, %r9, 4) // Add 8 for the ArtMethod 1291*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(5), %r9d 1292*795d594fSAndroid Build Coastguard Worker jne .Lloop_over_fast_path_range_\suffix 1293*795d594fSAndroid Build Coastguard Worker 1294*795d594fSAndroid Build Coastguard Worker.Lfive_args_fast_path_range_\suffix: 1295*795d594fSAndroid Build Coastguard Worker movl 16(%r11), %r9d 1296*795d594fSAndroid Build Coastguard Worker.Lfour_args_fast_path_range_\suffix: 1297*795d594fSAndroid Build Coastguard Worker movl 12(%r11), %r8d 1298*795d594fSAndroid Build Coastguard Worker.Lthree_args_fast_path_range_\suffix: 1299*795d594fSAndroid Build Coastguard Worker movl 8(%r11), %ecx 1300*795d594fSAndroid Build Coastguard Worker.Ltwo_args_fast_path_range_\suffix: 1301*795d594fSAndroid Build Coastguard Worker movl 4(%r11), %edx 1302*795d594fSAndroid Build Coastguard Worker.Lone_arg_fast_path_range_\suffix: 1303*795d594fSAndroid Build Coastguard Worker .if \is_static 1304*795d594fSAndroid Build Coastguard Worker movl 0(%r11), %esi 1305*795d594fSAndroid Build Coastguard Worker .else 1306*795d594fSAndroid Build Coastguard Worker // First argument already in %esi. 1307*795d594fSAndroid Build Coastguard Worker .endif 1308*795d594fSAndroid Build Coastguard Worker.Linvoke_fast_path_range_\suffix: 1309*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1310*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1311*795d594fSAndroid Build Coastguard Worker 1312*795d594fSAndroid Build Coastguard Worker.Lfast_path_with_few_args_range_\suffix: 1313*795d594fSAndroid Build Coastguard Worker // Fast path when we have zero or one argument (modulo 'this'). If there 1314*795d594fSAndroid Build Coastguard Worker // is one argument, we can put it in both floating point and core register. 1315*795d594fSAndroid Build Coastguard Worker movzbl 1(rPC), %r9d # Number of arguments 1316*795d594fSAndroid Build Coastguard Worker .if \is_static 1317*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(1), %r9d 1318*795d594fSAndroid Build Coastguard Worker jl .Linvoke_with_few_args_range_\suffix 1319*795d594fSAndroid Build Coastguard Worker jne .Lget_shorty_range_\suffix 1320*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r9d // Dex register of first argument 1321*795d594fSAndroid Build Coastguard Worker GET_VREG %esi, %r9 1322*795d594fSAndroid Build Coastguard Worker movd %esi, %xmm0 1323*795d594fSAndroid Build Coastguard Worker .else 1324*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(2), %r9d 1325*795d594fSAndroid Build Coastguard Worker jl .Linvoke_with_few_args_range_\suffix 1326*795d594fSAndroid Build Coastguard Worker jne .Lget_shorty_range_\suffix 1327*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r9d 1328*795d594fSAndroid Build Coastguard Worker addl MACRO_LITERAL(1), %r9d // dex register of second argument 1329*795d594fSAndroid Build Coastguard Worker GET_VREG %edx, %r9 1330*795d594fSAndroid Build Coastguard Worker movd %edx, %xmm0 1331*795d594fSAndroid Build Coastguard Worker .endif 1332*795d594fSAndroid Build Coastguard Worker.Linvoke_with_few_args_range_\suffix: 1333*795d594fSAndroid Build Coastguard Worker // Check if the next instruction is move-result or move-result-wide. 1334*795d594fSAndroid Build Coastguard Worker // If it is, we fetch the shorty and jump to the regular invocation. 1335*795d594fSAndroid Build Coastguard Worker movzwq 6(rPC), %r9 1336*795d594fSAndroid Build Coastguard Worker and MACRO_LITERAL(0xfe), %r9d 1337*795d594fSAndroid Build Coastguard Worker cmpl MACRO_LITERAL(0x0a), %r9d 1338*795d594fSAndroid Build Coastguard Worker je .Lget_shorty_and_invoke_range_\suffix 1339*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1340*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1341*795d594fSAndroid Build Coastguard Worker.Lget_shorty_and_invoke_range_\suffix: 1342*795d594fSAndroid Build Coastguard Worker .if \is_interface 1343*795d594fSAndroid Build Coastguard Worker // Save interface method, used for conflict resolution, in a callee-save register. 1344*795d594fSAndroid Build Coastguard Worker movq %rax, %xmm12 1345*795d594fSAndroid Build Coastguard Worker .endif 1346*795d594fSAndroid Build Coastguard Worker GET_SHORTY_SLOW_PATH rINSTq, \is_interface 1347*795d594fSAndroid Build Coastguard Worker jmp .Lgpr_setup_finished_range_\suffix 1348*795d594fSAndroid Build Coastguard Worker .endif 1349*795d594fSAndroid Build Coastguard Worker 1350*795d594fSAndroid Build Coastguard Worker.Lget_shorty_range_\suffix: 1351*795d594fSAndroid Build Coastguard Worker .if \is_interface 1352*795d594fSAndroid Build Coastguard Worker // Save interface method, used for conflict resolution, in a callee-saved register. 1353*795d594fSAndroid Build Coastguard Worker movq %rax, %xmm12 1354*795d594fSAndroid Build Coastguard Worker .endif 1355*795d594fSAndroid Build Coastguard Worker GET_SHORTY rINSTq, \is_interface, \is_polymorphic, \is_custom 1356*795d594fSAndroid Build Coastguard Worker // From this point: 1357*795d594fSAndroid Build Coastguard Worker // - rINSTq contains shorty (in callee-save to switch over return value after call). 1358*795d594fSAndroid Build Coastguard Worker // - rdi contains method 1359*795d594fSAndroid Build Coastguard Worker // - rsi contains 'this' pointer for instance method. 1360*795d594fSAndroid Build Coastguard Worker leaq 1(rINSTq), %r9 // shorty + 1 ; ie skip return arg character 1361*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r10d // arg start index 1362*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1363*795d594fSAndroid Build Coastguard Worker addq $$1, %r10 // arg start index 1364*795d594fSAndroid Build Coastguard Worker movq $$1, %rbp // index in stack 1365*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1366*795d594fSAndroid Build Coastguard Worker movq $$0, %rbp // index in stack 1367*795d594fSAndroid Build Coastguard Worker .else 1368*795d594fSAndroid Build Coastguard Worker addq $$1, %r10 // arg start index 1369*795d594fSAndroid Build Coastguard Worker movq $$1, %rbp // index in stack 1370*795d594fSAndroid Build Coastguard Worker .endif 1371*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm0, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1372*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm1, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1373*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm2, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1374*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm3, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1375*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm4, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1376*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm5, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1377*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm6, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1378*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_XMMS xmm7, r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1379*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_FPs r9, r10, rbp, .Lxmm_setup_finished_range_\suffix 1380*795d594fSAndroid Build Coastguard Worker.Lxmm_setup_finished_range_\suffix: 1381*795d594fSAndroid Build Coastguard Worker leaq 1(%rbx), %r11 // shorty + 1 ; ie skip return arg character 1382*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r10d // arg start index 1383*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1384*795d594fSAndroid Build Coastguard Worker addq $$1, %r10 // arg start index 1385*795d594fSAndroid Build Coastguard Worker movq $$1, %rbp // index in stack 1386*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1387*795d594fSAndroid Build Coastguard Worker .elseif \is_static 1388*795d594fSAndroid Build Coastguard Worker movq $$0, %rbp // index in stack 1389*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rsi, esi, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1390*795d594fSAndroid Build Coastguard Worker .else 1391*795d594fSAndroid Build Coastguard Worker addq $$1, %r10 // arg start index 1392*795d594fSAndroid Build Coastguard Worker movq $$1, %rbp // index in stack 1393*795d594fSAndroid Build Coastguard Worker .endif 1394*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rdx, edx, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1395*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS rcx, ecx, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1396*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r8, r8d, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1397*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_SHORTY_LOADING_GPRS r9, r9d, r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1398*795d594fSAndroid Build Coastguard Worker LOOP_RANGE_OVER_INTs r11, r10, rbp, .Lgpr_setup_finished_range_\suffix 1399*795d594fSAndroid Build Coastguard Worker 1400*795d594fSAndroid Build Coastguard Worker.Lgpr_setup_finished_range_\suffix: 1401*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1402*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_invoke_polymorphic) 1403*795d594fSAndroid Build Coastguard Worker .elseif \is_custom 1404*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_invoke_custom) 1405*795d594fSAndroid Build Coastguard Worker .else 1406*795d594fSAndroid Build Coastguard Worker .if \is_interface 1407*795d594fSAndroid Build Coastguard Worker // Set the hidden argument for conflict resolution. 1408*795d594fSAndroid Build Coastguard Worker movq %xmm12, %rax 1409*795d594fSAndroid Build Coastguard Worker .endif 1410*795d594fSAndroid Build Coastguard Worker call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 1411*795d594fSAndroid Build Coastguard Worker .endif 1412*795d594fSAndroid Build Coastguard Worker cmpb LITERAL(68), (%rbx) // Test if result type char == 'D'. 1413*795d594fSAndroid Build Coastguard Worker je .Lreturn_range_double_\suffix 1414*795d594fSAndroid Build Coastguard Worker cmpb LITERAL(70), (%rbx) // Test if result type char == 'F'. 1415*795d594fSAndroid Build Coastguard Worker je .Lreturn_range_float_\suffix 1416*795d594fSAndroid Build Coastguard Worker /* resume execution of caller */ 1417*795d594fSAndroid Build Coastguard Worker.Ldone_return_range_\suffix: 1418*795d594fSAndroid Build Coastguard Worker .if \is_string_init 1419*795d594fSAndroid Build Coastguard Worker movzwl 4(rPC), %r11d // arguments 1420*795d594fSAndroid Build Coastguard Worker GET_VREG %esi, %r11 1421*795d594fSAndroid Build Coastguard Worker UPDATE_REGISTERS_FOR_STRING_INIT %esi, %eax 1422*795d594fSAndroid Build Coastguard Worker .endif 1423*795d594fSAndroid Build Coastguard Worker 1424*795d594fSAndroid Build Coastguard Worker .if \is_polymorphic 1425*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 4 1426*795d594fSAndroid Build Coastguard Worker .else 1427*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 3 1428*795d594fSAndroid Build Coastguard Worker .endif 1429*795d594fSAndroid Build Coastguard Worker.Lreturn_range_double_\suffix: 1430*795d594fSAndroid Build Coastguard Worker movq %xmm0, %rax 1431*795d594fSAndroid Build Coastguard Worker jmp .Ldone_return_range_\suffix 1432*795d594fSAndroid Build Coastguard Worker.Lreturn_range_float_\suffix: 1433*795d594fSAndroid Build Coastguard Worker movd %xmm0, %eax 1434*795d594fSAndroid Build Coastguard Worker jmp .Ldone_return_range_\suffix 1435*795d594fSAndroid Build Coastguard Worker.endm 1436*795d594fSAndroid Build Coastguard Worker 1437*795d594fSAndroid Build Coastguard Worker// Helper for static field get. 1438*795d594fSAndroid Build Coastguard Worker.macro OP_SGET load="movl", wide="0" 1439*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1440*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1441*795d594fSAndroid Build Coastguard Worker1: 1442*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 1443*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 1444*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 1445*795d594fSAndroid Build Coastguard Worker jne 3f 1446*795d594fSAndroid Build Coastguard Worker4: 1447*795d594fSAndroid Build Coastguard Worker .if \wide 1448*795d594fSAndroid Build Coastguard Worker movq (%eax,%edx,1), %rax 1449*795d594fSAndroid Build Coastguard Worker SET_WIDE_VREG %rax, rINSTq # fp[A] <- value 1450*795d594fSAndroid Build Coastguard Worker .else 1451*795d594fSAndroid Build Coastguard Worker \load (%eax, %edx, 1), %eax 1452*795d594fSAndroid Build Coastguard Worker SET_VREG %eax, rINSTq # fp[A] <- value 1453*795d594fSAndroid Build Coastguard Worker .endif 1454*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1455*795d594fSAndroid Build Coastguard Worker2: 1456*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1457*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1458*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1459*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1460*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 1461*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field 1462*795d594fSAndroid Build Coastguard Worker // Clear the marker that we put for volatile fields. The x86 memory 1463*795d594fSAndroid Build Coastguard Worker // model doesn't require a barrier. 1464*795d594fSAndroid Build Coastguard Worker andq $$-2, %rax 1465*795d594fSAndroid Build Coastguard Worker jmp 1b 1466*795d594fSAndroid Build Coastguard Worker3: 1467*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 1468*795d594fSAndroid Build Coastguard Worker jmp 4b 1469*795d594fSAndroid Build Coastguard Worker.endm 1470*795d594fSAndroid Build Coastguard Worker 1471*795d594fSAndroid Build Coastguard Worker// Helper for static field put. 1472*795d594fSAndroid Build Coastguard Worker.macro OP_SPUT rINST_reg="rINST", store="movl", wide="0": 1473*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1474*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1475*795d594fSAndroid Build Coastguard Worker1: 1476*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 1477*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 1478*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 1479*795d594fSAndroid Build Coastguard Worker jne 3f 1480*795d594fSAndroid Build Coastguard Worker4: 1481*795d594fSAndroid Build Coastguard Worker .if \wide 1482*795d594fSAndroid Build Coastguard Worker GET_WIDE_VREG rINSTq, rINSTq # rINST <- v[A] 1483*795d594fSAndroid Build Coastguard Worker .else 1484*795d594fSAndroid Build Coastguard Worker GET_VREG rINST, rINSTq # rINST <- v[A] 1485*795d594fSAndroid Build Coastguard Worker .endif 1486*795d594fSAndroid Build Coastguard Worker \store \rINST_reg, (%rax,%rdx,1) 1487*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1488*795d594fSAndroid Build Coastguard Worker2: 1489*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1490*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1491*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1492*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1493*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 1494*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field 1495*795d594fSAndroid Build Coastguard Worker testq MACRO_LITERAL(1), %rax 1496*795d594fSAndroid Build Coastguard Worker je 1b 1497*795d594fSAndroid Build Coastguard Worker // Clear the marker that we put for volatile fields. The x86 memory 1498*795d594fSAndroid Build Coastguard Worker // model doesn't require a barrier. 1499*795d594fSAndroid Build Coastguard Worker CLEAR_VOLATILE_MARKER %rax 1500*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 1501*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 1502*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 1503*795d594fSAndroid Build Coastguard Worker jne 6f 1504*795d594fSAndroid Build Coastguard Worker5: 1505*795d594fSAndroid Build Coastguard Worker .if \wide 1506*795d594fSAndroid Build Coastguard Worker GET_WIDE_VREG rINSTq, rINSTq # rINST <- v[A] 1507*795d594fSAndroid Build Coastguard Worker .else 1508*795d594fSAndroid Build Coastguard Worker GET_VREG rINST, rINSTq # rINST <- v[A] 1509*795d594fSAndroid Build Coastguard Worker .endif 1510*795d594fSAndroid Build Coastguard Worker \store \rINST_reg, (%rax,%rdx,1) 1511*795d594fSAndroid Build Coastguard Worker lock addl $$0, (%rsp) 1512*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1513*795d594fSAndroid Build Coastguard Worker3: 1514*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 1515*795d594fSAndroid Build Coastguard Worker jmp 4b 1516*795d594fSAndroid Build Coastguard Worker6: 1517*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 1518*795d594fSAndroid Build Coastguard Worker jmp 5b 1519*795d594fSAndroid Build Coastguard Worker.endm 1520*795d594fSAndroid Build Coastguard Worker 1521*795d594fSAndroid Build Coastguard Worker 1522*795d594fSAndroid Build Coastguard Worker.macro OP_IPUT_INTERNAL rINST_reg="rINST", store="movl", wide="0": 1523*795d594fSAndroid Build Coastguard Worker movzbq rINSTbl, %rcx # rcx <- BA 1524*795d594fSAndroid Build Coastguard Worker sarl $$4, %ecx # ecx <- B 1525*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rcx # vB (object we're operating on) 1526*795d594fSAndroid Build Coastguard Worker testl %ecx, %ecx # is object null? 1527*795d594fSAndroid Build Coastguard Worker je common_errNullObject 1528*795d594fSAndroid Build Coastguard Worker andb $$0xf, rINSTbl # rINST <- A 1529*795d594fSAndroid Build Coastguard Worker .if \wide 1530*795d594fSAndroid Build Coastguard Worker GET_WIDE_VREG rINSTq, rINSTq # rax<- fp[A]/fp[A+1] 1531*795d594fSAndroid Build Coastguard Worker .else 1532*795d594fSAndroid Build Coastguard Worker GET_VREG rINST, rINSTq # rINST <- v[A] 1533*795d594fSAndroid Build Coastguard Worker .endif 1534*795d594fSAndroid Build Coastguard Worker \store \rINST_reg, (%rcx,%rax,1) 1535*795d594fSAndroid Build Coastguard Worker.endm 1536*795d594fSAndroid Build Coastguard Worker 1537*795d594fSAndroid Build Coastguard Worker// Helper for instance field put. 1538*795d594fSAndroid Build Coastguard Worker.macro OP_IPUT rINST_reg="rINST", store="movl", wide="0": 1539*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1540*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1541*795d594fSAndroid Build Coastguard Worker1: 1542*795d594fSAndroid Build Coastguard Worker OP_IPUT_INTERNAL \rINST_reg, \store, \wide 1543*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1544*795d594fSAndroid Build Coastguard Worker2: 1545*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1546*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1547*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1548*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1549*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 1550*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset 1551*795d594fSAndroid Build Coastguard Worker testl %eax, %eax 1552*795d594fSAndroid Build Coastguard Worker jns 1b 1553*795d594fSAndroid Build Coastguard Worker negl %eax 1554*795d594fSAndroid Build Coastguard Worker OP_IPUT_INTERNAL \rINST_reg, \store, \wide 1555*795d594fSAndroid Build Coastguard Worker lock addl $$0, (%rsp) 1556*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1557*795d594fSAndroid Build Coastguard Worker.endm 1558*795d594fSAndroid Build Coastguard Worker 1559*795d594fSAndroid Build Coastguard Worker// Helper for instance field get. 1560*795d594fSAndroid Build Coastguard Worker.macro OP_IGET load="movl", wide="0" 1561*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1562*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1563*795d594fSAndroid Build Coastguard Worker1: 1564*795d594fSAndroid Build Coastguard Worker movl rINST, %ecx # rcx <- BA 1565*795d594fSAndroid Build Coastguard Worker sarl $$4, %ecx # ecx <- B 1566*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rcx # vB (object we're operating on) 1567*795d594fSAndroid Build Coastguard Worker testl %ecx, %ecx # is object null? 1568*795d594fSAndroid Build Coastguard Worker je common_errNullObject 1569*795d594fSAndroid Build Coastguard Worker andb $$0xf,rINSTbl # rINST <- A 1570*795d594fSAndroid Build Coastguard Worker .if \wide 1571*795d594fSAndroid Build Coastguard Worker movq (%rcx,%rax,1), %rax 1572*795d594fSAndroid Build Coastguard Worker SET_WIDE_VREG %rax, rINSTq # fp[A] <- value 1573*795d594fSAndroid Build Coastguard Worker .else 1574*795d594fSAndroid Build Coastguard Worker \load (%rcx,%rax,1), %eax 1575*795d594fSAndroid Build Coastguard Worker SET_VREG %eax, rINSTq # fp[A] <- value 1576*795d594fSAndroid Build Coastguard Worker .endif 1577*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1578*795d594fSAndroid Build Coastguard Worker2: 1579*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1580*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1581*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1582*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1583*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 1584*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset 1585*795d594fSAndroid Build Coastguard Worker testl %eax, %eax 1586*795d594fSAndroid Build Coastguard Worker jns 1b 1587*795d594fSAndroid Build Coastguard Worker negl %eax 1588*795d594fSAndroid Build Coastguard Worker jmp 1b 1589*795d594fSAndroid Build Coastguard Worker.endm 1590*795d594fSAndroid Build Coastguard Worker 1591*795d594fSAndroid Build Coastguard Worker.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished 1592*795d594fSAndroid Build Coastguard Worker movl REG_VAR(gpr32), (REG_VAR(regs), REG_VAR(arg_offset)) 1593*795d594fSAndroid Build Coastguard Worker movl REG_VAR(gpr32), (REG_VAR(refs), REG_VAR(arg_offset)) 1594*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(4), REG_VAR(arg_offset) 1595*795d594fSAndroid Build Coastguard Worker subl MACRO_LITERAL(1), REG_VAR(ins) 1596*795d594fSAndroid Build Coastguard Worker je \finished 1597*795d594fSAndroid Build Coastguard Worker.endm 1598*795d594fSAndroid Build Coastguard Worker 1599*795d594fSAndroid Build Coastguard Worker// Uses eax as temporary 1600*795d594fSAndroid Build Coastguard Worker.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset 1601*795d594fSAndroid Build Coastguard Worker1: 1602*795d594fSAndroid Build Coastguard Worker movl OFFSET_TO_FIRST_ARGUMENT_IN_STACK(REG_VAR(stack_ptr), REG_VAR(arg_offset)), %eax 1603*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(regs), REG_VAR(arg_offset)) 1604*795d594fSAndroid Build Coastguard Worker movl %eax, (REG_VAR(refs), REG_VAR(arg_offset)) 1605*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(4), REG_VAR(arg_offset) 1606*795d594fSAndroid Build Coastguard Worker subl MACRO_LITERAL(1), REG_VAR(ins) 1607*795d594fSAndroid Build Coastguard Worker jne 1b 1608*795d594fSAndroid Build Coastguard Worker.endm 1609*795d594fSAndroid Build Coastguard Worker 1610*795d594fSAndroid Build Coastguard Worker.macro CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot, if_not_hot 1611*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_IS_MEMORY_SHARED_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1612*795d594fSAndroid Build Coastguard Worker jz \if_hot 1613*795d594fSAndroid Build Coastguard Worker // Intrinsics are always in the boot image and considered hot. 1614*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_IS_INTRINSIC_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1615*795d594fSAndroid Build Coastguard Worker jnz \if_hot 1616*795d594fSAndroid Build Coastguard Worker movzwl rSELF:THREAD_SHARED_METHOD_HOTNESS_OFFSET, %esi 1617*795d594fSAndroid Build Coastguard Worker testl %esi, %esi 1618*795d594fSAndroid Build Coastguard Worker je \if_hot 1619*795d594fSAndroid Build Coastguard Worker addl $$-1, %esi 1620*795d594fSAndroid Build Coastguard Worker movw %si, rSELF:THREAD_SHARED_METHOD_HOTNESS_OFFSET 1621*795d594fSAndroid Build Coastguard Worker jmp \if_not_hot 1622*795d594fSAndroid Build Coastguard Worker.endm 1623*795d594fSAndroid Build Coastguard Worker 1624*795d594fSAndroid Build Coastguard Worker.macro DO_SUSPEND_CHECK continue_label 1625*795d594fSAndroid Build Coastguard Worker testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), rSELF:THREAD_FLAGS_OFFSET 1626*795d594fSAndroid Build Coastguard Worker jz \continue_label 1627*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1628*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_test_suspend) 1629*795d594fSAndroid Build Coastguard Worker.endm 1630*795d594fSAndroid Build Coastguard Worker 1631*795d594fSAndroid Build Coastguard Worker%def entry(): 1632*795d594fSAndroid Build Coastguard Worker/* 1633*795d594fSAndroid Build Coastguard Worker * ArtMethod entry point. 1634*795d594fSAndroid Build Coastguard Worker * 1635*795d594fSAndroid Build Coastguard Worker * On entry: 1636*795d594fSAndroid Build Coastguard Worker * rdi ArtMethod* callee 1637*795d594fSAndroid Build Coastguard Worker * rest method parameters 1638*795d594fSAndroid Build Coastguard Worker */ 1639*795d594fSAndroid Build Coastguard Worker 1640*795d594fSAndroid Build Coastguard WorkerOAT_ENTRY ExecuteNterpWithClinitImpl 1641*795d594fSAndroid Build Coastguard Worker .cfi_startproc 1642*795d594fSAndroid Build Coastguard Worker // For simplicity, we don't do a read barrier here, but instead rely 1643*795d594fSAndroid Build Coastguard Worker // on art_quick_resolution_trampoline to always have a suspend point before 1644*795d594fSAndroid Build Coastguard Worker // calling back here. 1645*795d594fSAndroid Build Coastguard Worker movl ART_METHOD_DECLARING_CLASS_OFFSET(%rdi), %r10d 1646*795d594fSAndroid Build Coastguard Worker cmpl $$(MIRROR_CLASS_STATUS_VISIBLY_INITIALIZED_SHIFTED), MIRROR_CLASS_STATUS_OFFSET(%r10d) 1647*795d594fSAndroid Build Coastguard Worker jae ExecuteNterpImpl 1648*795d594fSAndroid Build Coastguard Worker cmpl $$(MIRROR_CLASS_STATUS_INITIALIZING_SHIFTED), MIRROR_CLASS_STATUS_OFFSET(%r10d) 1649*795d594fSAndroid Build Coastguard Worker jb art_quick_resolution_trampoline 1650*795d594fSAndroid Build Coastguard Worker movl MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET(%r10d), %r10d 1651*795d594fSAndroid Build Coastguard Worker cmpl %r10d, rSELF:THREAD_TID_OFFSET 1652*795d594fSAndroid Build Coastguard Worker je ExecuteNterpImpl 1653*795d594fSAndroid Build Coastguard Worker jmp art_quick_resolution_trampoline 1654*795d594fSAndroid Build Coastguard Worker .cfi_endproc 1655*795d594fSAndroid Build Coastguard Worker .global SYMBOL(EndExecuteNterpWithClinitImpl) 1656*795d594fSAndroid Build Coastguard WorkerSYMBOL(EndExecuteNterpWithClinitImpl): 1657*795d594fSAndroid Build Coastguard Worker 1658*795d594fSAndroid Build Coastguard WorkerOAT_ENTRY ExecuteNterpImpl 1659*795d594fSAndroid Build Coastguard Worker .cfi_startproc 1660*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 1661*795d594fSAndroid Build Coastguard Worker testq %rax, -STACK_OVERFLOW_RESERVED_BYTES(%rsp) 1662*795d594fSAndroid Build Coastguard Worker /* Spill callee save regs */ 1663*795d594fSAndroid Build Coastguard Worker SPILL_ALL_CALLEE_SAVES 1664*795d594fSAndroid Build Coastguard Worker 1665*795d594fSAndroid Build Coastguard Worker movq ART_METHOD_DATA_OFFSET_64(%rdi), rPC 1666*795d594fSAndroid Build Coastguard Worker 1667*795d594fSAndroid Build Coastguard Worker // Setup the stack for executing the method. 1668*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FRAME rPC, rREFS, rREFS32, rFP, CFI_REFS, load_ins=1 1669*795d594fSAndroid Build Coastguard Worker 1670*795d594fSAndroid Build Coastguard Worker // Setup the parameters 1671*795d594fSAndroid Build Coastguard Worker testl %r14d, %r14d 1672*795d594fSAndroid Build Coastguard Worker je .Lxmm_setup_finished 1673*795d594fSAndroid Build Coastguard Worker 1674*795d594fSAndroid Build Coastguard Worker subq %r14, %rbx 1675*795d594fSAndroid Build Coastguard Worker salq $$2, %rbx // rbx is now the offset for inputs into the registers array. 1676*795d594fSAndroid Build Coastguard Worker 1677*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1678*795d594fSAndroid Build Coastguard Worker je .Lsetup_slow_path 1679*795d594fSAndroid Build Coastguard Worker leaq (rFP, %rbx, 1), %rdi 1680*795d594fSAndroid Build Coastguard Worker leaq (rREFS, %rbx, 1), %rbx 1681*795d594fSAndroid Build Coastguard Worker movq $$0, %r10 1682*795d594fSAndroid Build Coastguard Worker 1683*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETER_IN_GPR esi, rdi, rbx, r14d, r10, .Lxmm_setup_finished 1684*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETER_IN_GPR edx, rdi, rbx, r14d, r10, .Lxmm_setup_finished 1685*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETER_IN_GPR ecx, rdi, rbx, r14d, r10, .Lxmm_setup_finished 1686*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETER_IN_GPR r8d, rdi, rbx, r14d, r10, .Lxmm_setup_finished 1687*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETER_IN_GPR r9d, rdi, rbx, r14d, r10, .Lxmm_setup_finished 1688*795d594fSAndroid Build Coastguard Worker SETUP_REFERENCE_PARAMETERS_IN_STACK rdi, rbx, r14d, r11, r10 1689*795d594fSAndroid Build Coastguard Worker jmp .Lxmm_setup_finished 1690*795d594fSAndroid Build Coastguard Worker 1691*795d594fSAndroid Build Coastguard Worker.Lsetup_slow_path: 1692*795d594fSAndroid Build Coastguard Worker // If the method is not static and there is one argument ('this'), we don't need to fetch the 1693*795d594fSAndroid Build Coastguard Worker // shorty. 1694*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_IS_STATIC_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1695*795d594fSAndroid Build Coastguard Worker jne .Lsetup_with_shorty 1696*795d594fSAndroid Build Coastguard Worker 1697*795d594fSAndroid Build Coastguard Worker movl %esi, (rFP, %rbx) 1698*795d594fSAndroid Build Coastguard Worker movl %esi, (rREFS, %rbx) 1699*795d594fSAndroid Build Coastguard Worker 1700*795d594fSAndroid Build Coastguard Worker cmpl $$1, %r14d 1701*795d594fSAndroid Build Coastguard Worker je .Lxmm_setup_finished 1702*795d594fSAndroid Build Coastguard Worker 1703*795d594fSAndroid Build Coastguard Worker.Lsetup_with_shorty: 1704*795d594fSAndroid Build Coastguard Worker // TODO: Get shorty in a better way and remove below 1705*795d594fSAndroid Build Coastguard Worker push %rdi 1706*795d594fSAndroid Build Coastguard Worker push %rsi 1707*795d594fSAndroid Build Coastguard Worker push %rdx 1708*795d594fSAndroid Build Coastguard Worker push %rcx 1709*795d594fSAndroid Build Coastguard Worker push %r8 1710*795d594fSAndroid Build Coastguard Worker push %r9 1711*795d594fSAndroid Build Coastguard Worker 1712*795d594fSAndroid Build Coastguard Worker // Save xmm registers + alignment. 1713*795d594fSAndroid Build Coastguard Worker subq MACRO_LITERAL(8 * 8 + 8), %rsp 1714*795d594fSAndroid Build Coastguard Worker movq %xmm0, 0(%rsp) 1715*795d594fSAndroid Build Coastguard Worker movq %xmm1, 8(%rsp) 1716*795d594fSAndroid Build Coastguard Worker movq %xmm2, 16(%rsp) 1717*795d594fSAndroid Build Coastguard Worker movq %xmm3, 24(%rsp) 1718*795d594fSAndroid Build Coastguard Worker movq %xmm4, 32(%rsp) 1719*795d594fSAndroid Build Coastguard Worker movq %xmm5, 40(%rsp) 1720*795d594fSAndroid Build Coastguard Worker movq %xmm6, 48(%rsp) 1721*795d594fSAndroid Build Coastguard Worker movq %xmm7, 56(%rsp) 1722*795d594fSAndroid Build Coastguard Worker 1723*795d594fSAndroid Build Coastguard Worker call SYMBOL(NterpGetShorty) 1724*795d594fSAndroid Build Coastguard Worker // Save shorty in callee-save rbp. 1725*795d594fSAndroid Build Coastguard Worker movq %rax, %rbp 1726*795d594fSAndroid Build Coastguard Worker 1727*795d594fSAndroid Build Coastguard Worker // Restore xmm registers + alignment. 1728*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %xmm0 1729*795d594fSAndroid Build Coastguard Worker movq 8(%rsp), %xmm1 1730*795d594fSAndroid Build Coastguard Worker movq 16(%rsp), %xmm2 1731*795d594fSAndroid Build Coastguard Worker movq 24(%rsp), %xmm3 1732*795d594fSAndroid Build Coastguard Worker movq 32(%rsp), %xmm4 1733*795d594fSAndroid Build Coastguard Worker movq 40(%rsp), %xmm5 1734*795d594fSAndroid Build Coastguard Worker movq 48(%rsp), %xmm6 1735*795d594fSAndroid Build Coastguard Worker movq 56(%rsp), %xmm7 1736*795d594fSAndroid Build Coastguard Worker addq MACRO_LITERAL(8 * 8 + 8), %rsp 1737*795d594fSAndroid Build Coastguard Worker 1738*795d594fSAndroid Build Coastguard Worker pop %r9 1739*795d594fSAndroid Build Coastguard Worker pop %r8 1740*795d594fSAndroid Build Coastguard Worker pop %rcx 1741*795d594fSAndroid Build Coastguard Worker pop %rdx 1742*795d594fSAndroid Build Coastguard Worker pop %rsi 1743*795d594fSAndroid Build Coastguard Worker pop %rdi 1744*795d594fSAndroid Build Coastguard Worker // Reload the old stack pointer, which used to be stored in %r11, which is not callee-saved. 1745*795d594fSAndroid Build Coastguard Worker movq -8(rREFS), %r11 1746*795d594fSAndroid Build Coastguard Worker // TODO: Get shorty in a better way and remove above 1747*795d594fSAndroid Build Coastguard Worker 1748*795d594fSAndroid Build Coastguard Worker movq $$0, %r14 1749*795d594fSAndroid Build Coastguard Worker testl $$ART_METHOD_IS_STATIC_FLAG, ART_METHOD_ACCESS_FLAGS_OFFSET(%rdi) 1750*795d594fSAndroid Build Coastguard Worker 1751*795d594fSAndroid Build Coastguard Worker // Available: rdi, r10 1752*795d594fSAndroid Build Coastguard Worker // Note the leaq below don't change the flags. 1753*795d594fSAndroid Build Coastguard Worker leaq 1(%rbp), %r10 // shorty + 1 ; ie skip return arg character 1754*795d594fSAndroid Build Coastguard Worker leaq (rFP, %rbx, 1), %rdi 1755*795d594fSAndroid Build Coastguard Worker leaq (rREFS, %rbx, 1), %rbx 1756*795d594fSAndroid Build Coastguard Worker jne .Lhandle_static_method 1757*795d594fSAndroid Build Coastguard Worker addq $$4, %rdi 1758*795d594fSAndroid Build Coastguard Worker addq $$4, %rbx 1759*795d594fSAndroid Build Coastguard Worker addq $$4, %r11 1760*795d594fSAndroid Build Coastguard Worker jmp .Lcontinue_setup_gprs 1761*795d594fSAndroid Build Coastguard Worker.Lhandle_static_method: 1762*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_GPRS rsi, esi, r10, r14, rdi, rbx, .Lgpr_setup_finished 1763*795d594fSAndroid Build Coastguard Worker.Lcontinue_setup_gprs: 1764*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_GPRS rdx, edx, r10, r14, rdi, rbx, .Lgpr_setup_finished 1765*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_GPRS rcx, ecx, r10, r14, rdi, rbx, .Lgpr_setup_finished 1766*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_GPRS r8, r8d, r10, r14, rdi, rbx, .Lgpr_setup_finished 1767*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_GPRS r9, r9d, r10, r14, rdi, rbx, .Lgpr_setup_finished 1768*795d594fSAndroid Build Coastguard Worker LOOP_OVER_INTs r10, r14, rdi, rbx, r11, .Lgpr_setup_finished 1769*795d594fSAndroid Build Coastguard Worker.Lgpr_setup_finished: 1770*795d594fSAndroid Build Coastguard Worker leaq 1(%rbp), %r10 // shorty + 1 ; ie skip return arg character 1771*795d594fSAndroid Build Coastguard Worker movq $$0, %r14 // reset counter 1772*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm0, r10, r14, rdi, .Lxmm_setup_finished 1773*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm1, r10, r14, rdi, .Lxmm_setup_finished 1774*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm2, r10, r14, rdi, .Lxmm_setup_finished 1775*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm3, r10, r14, rdi, .Lxmm_setup_finished 1776*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm4, r10, r14, rdi, .Lxmm_setup_finished 1777*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm5, r10, r14, rdi, .Lxmm_setup_finished 1778*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm6, r10, r14, rdi, .Lxmm_setup_finished 1779*795d594fSAndroid Build Coastguard Worker LOOP_OVER_SHORTY_STORING_XMMS xmm7, r10, r14, rdi, .Lxmm_setup_finished 1780*795d594fSAndroid Build Coastguard Worker LOOP_OVER_FPs r10, r14, rdi, r11, .Lxmm_setup_finished 1781*795d594fSAndroid Build Coastguard Worker.Lxmm_setup_finished: 1782*795d594fSAndroid Build Coastguard Worker CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) 1783*795d594fSAndroid Build Coastguard Worker 1784*795d594fSAndroid Build Coastguard Worker // Set rIBASE 1785*795d594fSAndroid Build Coastguard Worker leaq artNterpAsmInstructionStart(%rip), rIBASE 1786*795d594fSAndroid Build Coastguard Worker /* start executing the instruction at rPC */ 1787*795d594fSAndroid Build Coastguard Worker START_EXECUTING_INSTRUCTIONS 1788*795d594fSAndroid Build Coastguard Worker /* NOTE: no fallthrough */ 1789*795d594fSAndroid Build Coastguard Worker // cfi info continues, and covers the whole nterp implementation. 1790*795d594fSAndroid Build Coastguard Worker END ExecuteNterpImpl 1791*795d594fSAndroid Build Coastguard Worker 1792*795d594fSAndroid Build Coastguard Worker%def opcode_pre(): 1793*795d594fSAndroid Build Coastguard Worker 1794*795d594fSAndroid Build Coastguard Worker%def fetch_from_thread_cache(dest_reg, miss_label): 1795*795d594fSAndroid Build Coastguard Worker // Fetch some information from the thread cache. 1796*795d594fSAndroid Build Coastguard Worker // Uses rax, rdx, rcx as temporaries. 1797*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rax 1798*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1799*795d594fSAndroid Build Coastguard Worker salq MACRO_LITERAL(THREAD_INTERPRETER_CACHE_SIZE_SHIFT), %rdx 1800*795d594fSAndroid Build Coastguard Worker andq MACRO_LITERAL(THREAD_INTERPRETER_CACHE_SIZE_MASK), %rdx 1801*795d594fSAndroid Build Coastguard Worker cmpq THREAD_INTERPRETER_CACHE_OFFSET(%rax, %rdx, 1), rPC 1802*795d594fSAndroid Build Coastguard Worker jne ${miss_label} 1803*795d594fSAndroid Build Coastguard Worker movq __SIZEOF_POINTER__+THREAD_INTERPRETER_CACHE_OFFSET(%rax, %rdx, 1), ${dest_reg} 1804*795d594fSAndroid Build Coastguard Worker 1805*795d594fSAndroid Build Coastguard Worker%def footer(): 1806*795d594fSAndroid Build Coastguard Worker/* 1807*795d594fSAndroid Build Coastguard Worker * =========================================================================== 1808*795d594fSAndroid Build Coastguard Worker * Common subroutines and data 1809*795d594fSAndroid Build Coastguard Worker * =========================================================================== 1810*795d594fSAndroid Build Coastguard Worker */ 1811*795d594fSAndroid Build Coastguard Worker 1812*795d594fSAndroid Build Coastguard Worker .text 1813*795d594fSAndroid Build Coastguard Worker .align 2 1814*795d594fSAndroid Build Coastguard Worker 1815*795d594fSAndroid Build Coastguard Worker// Enclose all code below in a symbol (which gets printed in backtraces). 1816*795d594fSAndroid Build Coastguard WorkerENTRY nterp_helper 1817*795d594fSAndroid Build Coastguard Worker 1818*795d594fSAndroid Build Coastguard Worker// Note: mterp also uses the common_* names below for helpers, but that's OK 1819*795d594fSAndroid Build Coastguard Worker// as the C compiler compiled each interpreter separately. 1820*795d594fSAndroid Build Coastguard Workercommon_errDivideByZero: 1821*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1822*795d594fSAndroid Build Coastguard Worker call art_quick_throw_div_zero 1823*795d594fSAndroid Build Coastguard Worker 1824*795d594fSAndroid Build Coastguard Worker// Expect array in edi, index in esi. 1825*795d594fSAndroid Build Coastguard Workercommon_errArrayIndex: 1826*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1827*795d594fSAndroid Build Coastguard Worker movl MIRROR_ARRAY_LENGTH_OFFSET(%edi), %eax 1828*795d594fSAndroid Build Coastguard Worker movl %esi, %edi 1829*795d594fSAndroid Build Coastguard Worker movl %eax, %esi 1830*795d594fSAndroid Build Coastguard Worker call art_quick_throw_array_bounds 1831*795d594fSAndroid Build Coastguard Worker 1832*795d594fSAndroid Build Coastguard Workercommon_errNullObject: 1833*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1834*795d594fSAndroid Build Coastguard Worker call art_quick_throw_null_pointer_exception 1835*795d594fSAndroid Build Coastguard Worker 1836*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeStatic: 1837*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=1, is_interface=0, suffix="invokeStatic" 1838*795d594fSAndroid Build Coastguard Worker 1839*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeStaticRange: 1840*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=1, is_interface=0, suffix="invokeStatic" 1841*795d594fSAndroid Build Coastguard Worker 1842*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeInstance: 1843*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="invokeInstance" 1844*795d594fSAndroid Build Coastguard Worker 1845*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeInstanceRange: 1846*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="invokeInstance" 1847*795d594fSAndroid Build Coastguard Worker 1848*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeInterface: 1849*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=0, is_interface=1, suffix="invokeInterface" 1850*795d594fSAndroid Build Coastguard Worker 1851*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeInterfaceRange: 1852*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=0, is_interface=1, suffix="invokeInterface" 1853*795d594fSAndroid Build Coastguard Worker 1854*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokePolymorphic: 1855*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, is_string_init=0, is_polymorphic=1, suffix="invokePolymorphic" 1856*795d594fSAndroid Build Coastguard Worker 1857*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokePolymorphicRange: 1858*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=0, is_interface=0, is_polymorphic=1, suffix="invokePolymorphic" 1859*795d594fSAndroid Build Coastguard Worker 1860*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeCustom: 1861*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=1, is_interface=0, is_string_init=0, is_polymorphic=0, is_custom=1, suffix="invokeCustom" 1862*795d594fSAndroid Build Coastguard Worker 1863*795d594fSAndroid Build Coastguard WorkerNterpCommonInvokeCustomRange: 1864*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=1, is_interface=0, is_polymorphic=0, is_custom=1, suffix="invokeCustom" 1865*795d594fSAndroid Build Coastguard Worker 1866*795d594fSAndroid Build Coastguard WorkerNterpHandleStringInit: 1867*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, is_string_init=1, suffix="stringInit" 1868*795d594fSAndroid Build Coastguard Worker 1869*795d594fSAndroid Build Coastguard WorkerNterpHandleStringInitRange: 1870*795d594fSAndroid Build Coastguard Worker COMMON_INVOKE_RANGE is_static=0, is_interface=0, is_string_init=1, suffix="stringInit" 1871*795d594fSAndroid Build Coastguard Worker 1872*795d594fSAndroid Build Coastguard WorkerNterpNewInstance: 1873*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1874*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the class from thread-local cache. 1875*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rdi", miss_label="2f") 1876*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 1877*795d594fSAndroid Build Coastguard Worker jne 3f 1878*795d594fSAndroid Build Coastguard Worker4: 1879*795d594fSAndroid Build Coastguard Worker callq *rSELF:THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET 1880*795d594fSAndroid Build Coastguard Worker1: 1881*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value 1882*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1883*795d594fSAndroid Build Coastguard Worker2: 1884*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1885*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1886*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1887*795d594fSAndroid Build Coastguard Worker call nterp_allocate_object 1888*795d594fSAndroid Build Coastguard Worker jmp 1b 1889*795d594fSAndroid Build Coastguard Worker3: 1890*795d594fSAndroid Build Coastguard Worker // 07 is %rdi 1891*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg07 1892*795d594fSAndroid Build Coastguard Worker jmp 4b 1893*795d594fSAndroid Build Coastguard Worker 1894*795d594fSAndroid Build Coastguard WorkerNterpNewArray: 1895*795d594fSAndroid Build Coastguard Worker /* new-array vA, vB, class@CCCC */ 1896*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1897*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the class from thread-local cache. 1898*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rdi", miss_label="2f") 1899*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 1900*795d594fSAndroid Build Coastguard Worker jne 3f 1901*795d594fSAndroid Build Coastguard Worker1: 1902*795d594fSAndroid Build Coastguard Worker movzbl rINSTbl,%esi 1903*795d594fSAndroid Build Coastguard Worker sarl $$4,%esi # esi<- B 1904*795d594fSAndroid Build Coastguard Worker GET_VREG %esi %rsi # esi<- vB (array length) 1905*795d594fSAndroid Build Coastguard Worker andb $$0xf,rINSTbl # rINST<- A 1906*795d594fSAndroid Build Coastguard Worker callq *rSELF:THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET 1907*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value 1908*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1909*795d594fSAndroid Build Coastguard Worker2: 1910*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1911*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1912*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1913*795d594fSAndroid Build Coastguard Worker call nterp_get_class 1914*795d594fSAndroid Build Coastguard Worker movq %rax, %rdi 1915*795d594fSAndroid Build Coastguard Worker jmp 1b 1916*795d594fSAndroid Build Coastguard Worker3: 1917*795d594fSAndroid Build Coastguard Worker // 07 is %rdi 1918*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg07 1919*795d594fSAndroid Build Coastguard Worker jmp 1b 1920*795d594fSAndroid Build Coastguard Worker 1921*795d594fSAndroid Build Coastguard WorkerNterpPutObjectInstanceField: 1922*795d594fSAndroid Build Coastguard Worker movl rINST, %ebp # rbp <- BA 1923*795d594fSAndroid Build Coastguard Worker andl $$0xf, %ebp # rbp <- A 1924*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rbp # ecx <- v[A] 1925*795d594fSAndroid Build Coastguard Worker sarl $$4, rINST 1926*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1927*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1928*795d594fSAndroid Build Coastguard Worker1: 1929*795d594fSAndroid Build Coastguard Worker GET_VREG rINST, rINSTq # vB (object we're operating on) 1930*795d594fSAndroid Build Coastguard Worker testl rINST, rINST # is object null? 1931*795d594fSAndroid Build Coastguard Worker je common_errNullObject 1932*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF ecx 1933*795d594fSAndroid Build Coastguard Worker movl %ecx, (rINSTq,%rax,1) 1934*795d594fSAndroid Build Coastguard Worker testl %ecx, %ecx 1935*795d594fSAndroid Build Coastguard Worker je 4f 1936*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_CARD_TABLE_OFFSET, %rax 1937*795d594fSAndroid Build Coastguard Worker shrq $$CARD_TABLE_CARD_SHIFT, rINSTq 1938*795d594fSAndroid Build Coastguard Worker movb %al, (%rax, rINSTq, 1) 1939*795d594fSAndroid Build Coastguard Worker4: 1940*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1941*795d594fSAndroid Build Coastguard Worker2: 1942*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1943*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1944*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1945*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1946*795d594fSAndroid Build Coastguard Worker // %rcx is already set. 1947*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset 1948*795d594fSAndroid Build Coastguard Worker // Reload the value as it may have moved. 1949*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rbp # ecx <- v[A] 1950*795d594fSAndroid Build Coastguard Worker testl %eax, %eax 1951*795d594fSAndroid Build Coastguard Worker jns 1b 1952*795d594fSAndroid Build Coastguard Worker GET_VREG rINST, rINSTq # vB (object we're operating on) 1953*795d594fSAndroid Build Coastguard Worker testl rINST, rINST # is object null? 1954*795d594fSAndroid Build Coastguard Worker je common_errNullObject 1955*795d594fSAndroid Build Coastguard Worker negl %eax 1956*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF ecx 1957*795d594fSAndroid Build Coastguard Worker movl %ecx, (rINSTq,%rax,1) 1958*795d594fSAndroid Build Coastguard Worker testl %ecx, %ecx 1959*795d594fSAndroid Build Coastguard Worker je 5f 1960*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_CARD_TABLE_OFFSET, %rax 1961*795d594fSAndroid Build Coastguard Worker shrq $$CARD_TABLE_CARD_SHIFT, rINSTq 1962*795d594fSAndroid Build Coastguard Worker movb %al, (%rax, rINSTq, 1) 1963*795d594fSAndroid Build Coastguard Worker5: 1964*795d594fSAndroid Build Coastguard Worker lock addl $$0, (%rsp) 1965*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1966*795d594fSAndroid Build Coastguard Worker 1967*795d594fSAndroid Build Coastguard WorkerNterpGetObjectInstanceField: 1968*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 1969*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 1970*795d594fSAndroid Build Coastguard Worker1: 1971*795d594fSAndroid Build Coastguard Worker movl rINST, %ecx # rcx <- BA 1972*795d594fSAndroid Build Coastguard Worker sarl $$4, %ecx # ecx <- B 1973*795d594fSAndroid Build Coastguard Worker GET_VREG %ecx, %rcx # vB (object we're operating on) 1974*795d594fSAndroid Build Coastguard Worker testl %ecx, %ecx # is object null? 1975*795d594fSAndroid Build Coastguard Worker je common_errNullObject 1976*795d594fSAndroid Build Coastguard Worker testb $$READ_BARRIER_TEST_VALUE, GRAY_BYTE_OFFSET(%ecx) 1977*795d594fSAndroid Build Coastguard Worker movl (%rcx,%rax,1), %eax 1978*795d594fSAndroid Build Coastguard Worker jnz 3f 1979*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF eax // Affects flags, so we cannot unpoison before the jnz. 1980*795d594fSAndroid Build Coastguard Worker4: 1981*795d594fSAndroid Build Coastguard Worker andb $$0xf,rINSTbl # rINST <- A 1982*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value 1983*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1984*795d594fSAndroid Build Coastguard Worker2: 1985*795d594fSAndroid Build Coastguard Worker EXPORT_PC 1986*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 1987*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 1988*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 1989*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 1990*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset 1991*795d594fSAndroid Build Coastguard Worker testl %eax, %eax 1992*795d594fSAndroid Build Coastguard Worker jns 1b 1993*795d594fSAndroid Build Coastguard Worker // For volatile fields, we return a negative offset. Remove the sign 1994*795d594fSAndroid Build Coastguard Worker // and no need for any barrier thanks to the memory model. 1995*795d594fSAndroid Build Coastguard Worker negl %eax 1996*795d594fSAndroid Build Coastguard Worker jmp 1b 1997*795d594fSAndroid Build Coastguard Worker3: 1998*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF eax 1999*795d594fSAndroid Build Coastguard Worker // reg00 is eax 2000*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 2001*795d594fSAndroid Build Coastguard Worker jmp 4b 2002*795d594fSAndroid Build Coastguard Worker 2003*795d594fSAndroid Build Coastguard WorkerNterpPutObjectStaticField: 2004*795d594fSAndroid Build Coastguard Worker GET_VREG %ebp, rINSTq 2005*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 2006*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 2007*795d594fSAndroid Build Coastguard Worker1: 2008*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 2009*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 2010*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 2011*795d594fSAndroid Build Coastguard Worker jne 3f 2012*795d594fSAndroid Build Coastguard Worker5: 2013*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF ebp 2014*795d594fSAndroid Build Coastguard Worker movl %ebp, (%eax, %edx, 1) 2015*795d594fSAndroid Build Coastguard Worker testl %ebp, %ebp 2016*795d594fSAndroid Build Coastguard Worker je 4f 2017*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_CARD_TABLE_OFFSET, %rcx 2018*795d594fSAndroid Build Coastguard Worker shrq $$CARD_TABLE_CARD_SHIFT, %rax 2019*795d594fSAndroid Build Coastguard Worker movb %cl, (%rax, %rcx, 1) 2020*795d594fSAndroid Build Coastguard Worker4: 2021*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 2022*795d594fSAndroid Build Coastguard Worker2: 2023*795d594fSAndroid Build Coastguard Worker EXPORT_PC 2024*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 2025*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 2026*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 2027*795d594fSAndroid Build Coastguard Worker movq %rbp, %rcx 2028*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field 2029*795d594fSAndroid Build Coastguard Worker // Reload the value as it may have moved. 2030*795d594fSAndroid Build Coastguard Worker GET_VREG %ebp, rINSTq 2031*795d594fSAndroid Build Coastguard Worker testq MACRO_LITERAL(1), %rax 2032*795d594fSAndroid Build Coastguard Worker je 1b 2033*795d594fSAndroid Build Coastguard Worker CLEAR_VOLATILE_MARKER %rax 2034*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 2035*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 2036*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 2037*795d594fSAndroid Build Coastguard Worker jne 7f 2038*795d594fSAndroid Build Coastguard Worker6: 2039*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF ebp 2040*795d594fSAndroid Build Coastguard Worker movl %ebp, (%eax, %edx, 1) 2041*795d594fSAndroid Build Coastguard Worker testl %ebp, %ebp 2042*795d594fSAndroid Build Coastguard Worker je 8f 2043*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_CARD_TABLE_OFFSET, %rcx 2044*795d594fSAndroid Build Coastguard Worker shrq $$CARD_TABLE_CARD_SHIFT, %rax 2045*795d594fSAndroid Build Coastguard Worker movb %cl, (%rax, %rcx, 1) 2046*795d594fSAndroid Build Coastguard Worker8: 2047*795d594fSAndroid Build Coastguard Worker lock addl $$0, (%rsp) 2048*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 2049*795d594fSAndroid Build Coastguard Worker3: 2050*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 2051*795d594fSAndroid Build Coastguard Worker jmp 5b 2052*795d594fSAndroid Build Coastguard Worker7: 2053*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 2054*795d594fSAndroid Build Coastguard Worker jmp 6b 2055*795d594fSAndroid Build Coastguard Worker 2056*795d594fSAndroid Build Coastguard WorkerNterpGetObjectStaticField: 2057*795d594fSAndroid Build Coastguard Worker // Fast-path which gets the field from thread-local cache. 2058*795d594fSAndroid Build Coastguard Worker% fetch_from_thread_cache("%rax", miss_label="2f") 2059*795d594fSAndroid Build Coastguard Worker1: 2060*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_OFFSET_OFFSET(%rax), %edx 2061*795d594fSAndroid Build Coastguard Worker movl ART_FIELD_DECLARING_CLASS_OFFSET(%rax), %eax 2062*795d594fSAndroid Build Coastguard Worker cmpq $$0, rSELF:THREAD_READ_BARRIER_MARK_REG00_OFFSET 2063*795d594fSAndroid Build Coastguard Worker jne 5f 2064*795d594fSAndroid Build Coastguard Worker6: 2065*795d594fSAndroid Build Coastguard Worker testb $$READ_BARRIER_TEST_VALUE, GRAY_BYTE_OFFSET(%eax) 2066*795d594fSAndroid Build Coastguard Worker movl (%eax, %edx, 1), %eax 2067*795d594fSAndroid Build Coastguard Worker jnz 3f 2068*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF eax // Affects flags, so we cannot unpoison before the jnz. 2069*795d594fSAndroid Build Coastguard Worker4: 2070*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value 2071*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 2072*795d594fSAndroid Build Coastguard Worker2: 2073*795d594fSAndroid Build Coastguard Worker EXPORT_PC 2074*795d594fSAndroid Build Coastguard Worker movq rSELF:THREAD_SELF_OFFSET, %rdi 2075*795d594fSAndroid Build Coastguard Worker movq 0(%rsp), %rsi 2076*795d594fSAndroid Build Coastguard Worker movq rPC, %rdx 2077*795d594fSAndroid Build Coastguard Worker movq $$0, %rcx 2078*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field 2079*795d594fSAndroid Build Coastguard Worker andq $$-2, %rax 2080*795d594fSAndroid Build Coastguard Worker jmp 1b 2081*795d594fSAndroid Build Coastguard Worker3: 2082*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF eax 2083*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 2084*795d594fSAndroid Build Coastguard Worker jmp 4b 2085*795d594fSAndroid Build Coastguard Worker5: 2086*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg00 2087*795d594fSAndroid Build Coastguard Worker jmp 6b 2088*795d594fSAndroid Build Coastguard Worker 2089*795d594fSAndroid Build Coastguard WorkerNterpGetBooleanStaticField: 2090*795d594fSAndroid Build Coastguard Worker OP_SGET load="movsbl", wide=0 2091*795d594fSAndroid Build Coastguard Worker 2092*795d594fSAndroid Build Coastguard WorkerNterpGetByteStaticField: 2093*795d594fSAndroid Build Coastguard Worker OP_SGET load="movsbl", wide=0 2094*795d594fSAndroid Build Coastguard Worker 2095*795d594fSAndroid Build Coastguard WorkerNterpGetCharStaticField: 2096*795d594fSAndroid Build Coastguard Worker OP_SGET load="movzwl", wide=0 2097*795d594fSAndroid Build Coastguard Worker 2098*795d594fSAndroid Build Coastguard WorkerNterpGetShortStaticField: 2099*795d594fSAndroid Build Coastguard Worker OP_SGET load="movswl", wide=0 2100*795d594fSAndroid Build Coastguard Worker 2101*795d594fSAndroid Build Coastguard WorkerNterpGetWideStaticField: 2102*795d594fSAndroid Build Coastguard Worker OP_SGET load="movq", wide=1 2103*795d594fSAndroid Build Coastguard Worker 2104*795d594fSAndroid Build Coastguard WorkerNterpGetIntStaticField: 2105*795d594fSAndroid Build Coastguard Worker OP_SGET load="movl", wide=0 2106*795d594fSAndroid Build Coastguard Worker 2107*795d594fSAndroid Build Coastguard WorkerNterpPutStaticField: 2108*795d594fSAndroid Build Coastguard Worker OP_SPUT rINST_reg=rINST, store="movl", wide=0 2109*795d594fSAndroid Build Coastguard Worker 2110*795d594fSAndroid Build Coastguard WorkerNterpPutBooleanStaticField: 2111*795d594fSAndroid Build Coastguard WorkerNterpPutByteStaticField: 2112*795d594fSAndroid Build Coastguard Worker OP_SPUT rINST_reg=rINSTbl, store="movb", wide=0 2113*795d594fSAndroid Build Coastguard Worker 2114*795d594fSAndroid Build Coastguard WorkerNterpPutCharStaticField: 2115*795d594fSAndroid Build Coastguard WorkerNterpPutShortStaticField: 2116*795d594fSAndroid Build Coastguard Worker OP_SPUT rINST_reg=rINSTw, store="movw", wide=0 2117*795d594fSAndroid Build Coastguard Worker 2118*795d594fSAndroid Build Coastguard WorkerNterpPutWideStaticField: 2119*795d594fSAndroid Build Coastguard Worker OP_SPUT rINST_reg=rINSTq, store="movq", wide=1 2120*795d594fSAndroid Build Coastguard Worker 2121*795d594fSAndroid Build Coastguard WorkerNterpPutInstanceField: 2122*795d594fSAndroid Build Coastguard Worker OP_IPUT rINST_reg=rINST, store="movl", wide=0 2123*795d594fSAndroid Build Coastguard Worker 2124*795d594fSAndroid Build Coastguard WorkerNterpPutBooleanInstanceField: 2125*795d594fSAndroid Build Coastguard WorkerNterpPutByteInstanceField: 2126*795d594fSAndroid Build Coastguard Worker OP_IPUT rINST_reg=rINSTbl, store="movb", wide=0 2127*795d594fSAndroid Build Coastguard Worker 2128*795d594fSAndroid Build Coastguard WorkerNterpPutCharInstanceField: 2129*795d594fSAndroid Build Coastguard WorkerNterpPutShortInstanceField: 2130*795d594fSAndroid Build Coastguard Worker OP_IPUT rINST_reg=rINSTw, store="movw", wide=0 2131*795d594fSAndroid Build Coastguard Worker 2132*795d594fSAndroid Build Coastguard WorkerNterpPutWideInstanceField: 2133*795d594fSAndroid Build Coastguard Worker OP_IPUT rINST_reg=rINSTq, store="movq", wide=1 2134*795d594fSAndroid Build Coastguard Worker 2135*795d594fSAndroid Build Coastguard WorkerNterpGetBooleanInstanceField: 2136*795d594fSAndroid Build Coastguard Worker OP_IGET load="movzbl", wide=0 2137*795d594fSAndroid Build Coastguard Worker 2138*795d594fSAndroid Build Coastguard WorkerNterpGetByteInstanceField: 2139*795d594fSAndroid Build Coastguard Worker OP_IGET load="movsbl", wide=0 2140*795d594fSAndroid Build Coastguard Worker 2141*795d594fSAndroid Build Coastguard WorkerNterpGetCharInstanceField: 2142*795d594fSAndroid Build Coastguard Worker OP_IGET load="movzwl", wide=0 2143*795d594fSAndroid Build Coastguard Worker 2144*795d594fSAndroid Build Coastguard WorkerNterpGetShortInstanceField: 2145*795d594fSAndroid Build Coastguard Worker OP_IGET load="movswl", wide=0 2146*795d594fSAndroid Build Coastguard Worker 2147*795d594fSAndroid Build Coastguard WorkerNterpGetWideInstanceField: 2148*795d594fSAndroid Build Coastguard Worker OP_IGET load="movq", wide=1 2149*795d594fSAndroid Build Coastguard Worker 2150*795d594fSAndroid Build Coastguard WorkerNterpGetInstanceField: 2151*795d594fSAndroid Build Coastguard Worker OP_IGET load="movl", wide=0 2152*795d594fSAndroid Build Coastguard Worker 2153*795d594fSAndroid Build Coastguard WorkerNterpHandleHotnessOverflow: 2154*795d594fSAndroid Build Coastguard Worker CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=1f, if_not_hot=4f 2155*795d594fSAndroid Build Coastguard Worker1: 2156*795d594fSAndroid Build Coastguard Worker movq rPC, %rsi 2157*795d594fSAndroid Build Coastguard Worker movq rFP, %rdx 2158*795d594fSAndroid Build Coastguard Worker call nterp_hot_method 2159*795d594fSAndroid Build Coastguard Worker testq %rax, %rax 2160*795d594fSAndroid Build Coastguard Worker jne 3f 2161*795d594fSAndroid Build Coastguard Worker2: 2162*795d594fSAndroid Build Coastguard Worker FETCH_INST 2163*795d594fSAndroid Build Coastguard Worker GOTO_NEXT 2164*795d594fSAndroid Build Coastguard Worker3: 2165*795d594fSAndroid Build Coastguard Worker // Drop the current frame. 2166*795d594fSAndroid Build Coastguard Worker movq -8(rREFS), %rsp 2167*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA(rsp, CALLEE_SAVES_SIZE) 2168*795d594fSAndroid Build Coastguard Worker 2169*795d594fSAndroid Build Coastguard Worker // Setup the new frame 2170*795d594fSAndroid Build Coastguard Worker movq OSR_DATA_FRAME_SIZE(%rax), %rcx 2171*795d594fSAndroid Build Coastguard Worker // Given stack size contains all callee saved registers, remove them. 2172*795d594fSAndroid Build Coastguard Worker subq $$CALLEE_SAVES_SIZE, %rcx 2173*795d594fSAndroid Build Coastguard Worker 2174*795d594fSAndroid Build Coastguard Worker // Remember CFA. 2175*795d594fSAndroid Build Coastguard Worker movq %rsp, %rbp 2176*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_REGISTER(rbp) 2177*795d594fSAndroid Build Coastguard Worker 2178*795d594fSAndroid Build Coastguard Worker subq %rcx, %rsp 2179*795d594fSAndroid Build Coastguard Worker movq %rsp, %rdi // rdi := beginning of stack 2180*795d594fSAndroid Build Coastguard Worker leaq OSR_DATA_MEMORY(%rax), %rsi // rsi := memory to copy 2181*795d594fSAndroid Build Coastguard Worker rep movsb // while (rcx--) { *rdi++ = *rsi++ } 2182*795d594fSAndroid Build Coastguard Worker 2183*795d594fSAndroid Build Coastguard Worker // Fetch the native PC to jump to and save it in a callee-save register. 2184*795d594fSAndroid Build Coastguard Worker movq OSR_DATA_NATIVE_PC(%rax), %rbx 2185*795d594fSAndroid Build Coastguard Worker 2186*795d594fSAndroid Build Coastguard Worker // Free the memory holding OSR Data. 2187*795d594fSAndroid Build Coastguard Worker movq %rax, %rdi 2188*795d594fSAndroid Build Coastguard Worker call free 2189*795d594fSAndroid Build Coastguard Worker 2190*795d594fSAndroid Build Coastguard Worker // Jump to the compiled code. 2191*795d594fSAndroid Build Coastguard Worker jmp *%rbx 2192*795d594fSAndroid Build Coastguard Worker4: 2193*795d594fSAndroid Build Coastguard Worker DO_SUSPEND_CHECK continue_label=2b 2194*795d594fSAndroid Build Coastguard Worker jmp 2b 2195*795d594fSAndroid Build Coastguard Worker 2196*795d594fSAndroid Build Coastguard WorkerNterpHandleInvokeInterfaceOnObjectMethodRange: 2197*795d594fSAndroid Build Coastguard Worker shrl $$16, %eax 2198*795d594fSAndroid Build Coastguard Worker movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi 2199*795d594fSAndroid Build Coastguard Worker jmp NterpCommonInvokeInstanceRange 2200*795d594fSAndroid Build Coastguard Worker 2201*795d594fSAndroid Build Coastguard WorkerNterpHandleInvokeInterfaceOnObjectMethod: 2202*795d594fSAndroid Build Coastguard Worker shrl $$16, %eax 2203*795d594fSAndroid Build Coastguard Worker movq MIRROR_CLASS_VTABLE_OFFSET_64(%edx, %eax, 8), %rdi 2204*795d594fSAndroid Build Coastguard Worker jmp NterpCommonInvokeInstance 2205*795d594fSAndroid Build Coastguard Worker 2206*795d594fSAndroid Build Coastguard Worker// This is the logical end of ExecuteNterpImpl, where the frame info applies. 2207*795d594fSAndroid Build Coastguard Worker// EndExecuteNterpImpl includes the methods below as we want the runtime to 2208*795d594fSAndroid Build Coastguard Worker// see them as part of the Nterp PCs. 2209*795d594fSAndroid Build Coastguard Worker.cfi_endproc 2210*795d594fSAndroid Build Coastguard Worker 2211*795d594fSAndroid Build Coastguard Workernterp_to_nterp_static_non_range: 2212*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2213*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2214*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2215*795d594fSAndroid Build Coastguard Worker SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0 2216*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2217*795d594fSAndroid Build Coastguard Worker 2218*795d594fSAndroid Build Coastguard Workernterp_to_nterp_string_init_non_range: 2219*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2220*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2221*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2222*795d594fSAndroid Build Coastguard Worker SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1 2223*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2224*795d594fSAndroid Build Coastguard Worker 2225*795d594fSAndroid Build Coastguard Workernterp_to_nterp_instance_non_range: 2226*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2227*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2228*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2229*795d594fSAndroid Build Coastguard Worker SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 2230*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2231*795d594fSAndroid Build Coastguard Worker 2232*795d594fSAndroid Build Coastguard Workernterp_to_nterp_static_range: 2233*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2234*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2235*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2236*795d594fSAndroid Build Coastguard Worker SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1 2237*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2238*795d594fSAndroid Build Coastguard Worker 2239*795d594fSAndroid Build Coastguard Workernterp_to_nterp_instance_range: 2240*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2241*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2242*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2243*795d594fSAndroid Build Coastguard Worker SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0 2244*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2245*795d594fSAndroid Build Coastguard Worker 2246*795d594fSAndroid Build Coastguard Workernterp_to_nterp_string_init_range: 2247*795d594fSAndroid Build Coastguard Worker .cfi_startproc 2248*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa rsp, 8 2249*795d594fSAndroid Build Coastguard Worker SETUP_STACK_FOR_INVOKE 2250*795d594fSAndroid Build Coastguard Worker SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1 2251*795d594fSAndroid Build Coastguard Worker .cfi_endproc 2252*795d594fSAndroid Build Coastguard Worker 2253*795d594fSAndroid Build Coastguard WorkerEND nterp_helper 2254*795d594fSAndroid Build Coastguard Worker 2255*795d594fSAndroid Build Coastguard Worker// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter 2256*795d594fSAndroid Build Coastguard Worker// entry point. 2257*795d594fSAndroid Build Coastguard Worker FUNCTION_TYPE(EndExecuteNterpImpl) 2258*795d594fSAndroid Build Coastguard Worker ASM_HIDDEN SYMBOL(EndExecuteNterpImpl) 2259*795d594fSAndroid Build Coastguard Worker .global SYMBOL(EndExecuteNterpImpl) 2260*795d594fSAndroid Build Coastguard WorkerSYMBOL(EndExecuteNterpImpl): 2261*795d594fSAndroid Build Coastguard Worker 2262*795d594fSAndroid Build Coastguard Worker// Entrypoints into runtime. 2263*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField 2264*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset 2265*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray 2266*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange 2267*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_class, NterpGetClass 2268*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_allocate_object, NterpAllocateObject 2269*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_get_method, NterpGetMethod 2270*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod 2271*795d594fSAndroid Build Coastguard WorkerNTERP_TRAMPOLINE nterp_load_object, NterpLoadObject 2272*795d594fSAndroid Build Coastguard Worker 2273*795d594fSAndroid Build Coastguard WorkerDEFINE_FUNCTION nterp_deliver_pending_exception 2274*795d594fSAndroid Build Coastguard Worker DELIVER_PENDING_EXCEPTION 2275*795d594fSAndroid Build Coastguard WorkerEND_FUNCTION nterp_deliver_pending_exception 2276*795d594fSAndroid Build Coastguard Worker 2277*795d594fSAndroid Build Coastguard Worker// gen_mterp.py will inline the following definitions 2278*795d594fSAndroid Build Coastguard Worker// within [ExecuteNterpImpl, EndExecuteNterpImpl). 2279*795d594fSAndroid Build Coastguard Worker%def instruction_end(): 2280*795d594fSAndroid Build Coastguard Worker 2281*795d594fSAndroid Build Coastguard Worker FUNCTION_TYPE(artNterpAsmInstructionEnd) 2282*795d594fSAndroid Build Coastguard Worker ASM_HIDDEN SYMBOL(artNterpAsmInstructionEnd) 2283*795d594fSAndroid Build Coastguard Worker .global SYMBOL(artNterpAsmInstructionEnd) 2284*795d594fSAndroid Build Coastguard WorkerSYMBOL(artNterpAsmInstructionEnd): 2285*795d594fSAndroid Build Coastguard Worker // artNterpAsmInstructionEnd is used as landing pad for exception handling. 2286*795d594fSAndroid Build Coastguard Worker FETCH_INST 2287*795d594fSAndroid Build Coastguard Worker GOTO_NEXT 2288*795d594fSAndroid Build Coastguard Worker 2289*795d594fSAndroid Build Coastguard Worker%def instruction_start(): 2290*795d594fSAndroid Build Coastguard Worker 2291*795d594fSAndroid Build Coastguard Worker FUNCTION_TYPE(artNterpAsmInstructionStart) 2292*795d594fSAndroid Build Coastguard Worker ASM_HIDDEN SYMBOL(artNterpAsmInstructionStart) 2293*795d594fSAndroid Build Coastguard Worker .global SYMBOL(artNterpAsmInstructionStart) 2294*795d594fSAndroid Build Coastguard WorkerSYMBOL(artNterpAsmInstructionStart) = .L_op_nop 2295*795d594fSAndroid Build Coastguard Worker .text 2296*795d594fSAndroid Build Coastguard Worker 2297*795d594fSAndroid Build Coastguard Worker%def opcode_name_prefix(): 2298*795d594fSAndroid Build Coastguard Worker% return "nterp_" 2299*795d594fSAndroid Build Coastguard Worker%def opcode_start(): 2300*795d594fSAndroid Build Coastguard Worker ENTRY nterp_${opcode} 2301*795d594fSAndroid Build Coastguard Worker%def opcode_end(): 2302*795d594fSAndroid Build Coastguard Worker END nterp_${opcode} 2303*795d594fSAndroid Build Coastguard Worker // Advance to the end of this handler. Causes error if we are past that point. 2304*795d594fSAndroid Build Coastguard Worker .org nterp_${opcode} + NTERP_HANDLER_SIZE // ${opcode} handler is too big! 2305*795d594fSAndroid Build Coastguard Worker%def opcode_slow_path_start(name): 2306*795d594fSAndroid Build Coastguard Worker ENTRY ${name} 2307*795d594fSAndroid Build Coastguard Worker%def opcode_slow_path_end(name): 2308*795d594fSAndroid Build Coastguard Worker END ${name} 2309