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