xref: /aosp_15_r20/art/runtime/interpreter/mterp/x86ng/main.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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