1/* DO NOT EDIT: This file was generated by gen-mterp.py. */
2/*
3 * Copyright (C) 2020 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * This is a #include, not a %include, because we want the C pre-processor
20 * to expand the macros into assembler assignment statements.
21 */
22#include "asm_support.h"
23#include "arch/arm64/asm_support_arm64.S"
24
25/**
26 * ARM64 Runtime register usage conventions.
27 *
28 *   r0     : w0 is 32-bit return register and x0 is 64-bit.
29 *   r0-r7  : Argument registers.
30 *   r8-r15 : Caller save registers (used as temporary registers).
31 *   r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by
32 *            the linker, by the trampolines and other stubs (the compiler uses
33 *            these as temporary registers).
34 *   r18    : Reserved for platform (SCS, shadow call stack)
35 *   r19    : Pointer to thread-local storage.
36 *   r20-r29: Callee save registers.
37 *   r30    : (lr) is reserved (the link register).
38 *   rsp    : (sp) is reserved (the stack pointer).
39 *   rzr    : (zr) is reserved (the zero register).
40 *
41 *   Floating-point registers
42 *   v0-v31
43 *
44 *   v0     : s0 is return register for singles (32-bit) and d0 for doubles (64-bit).
45 *            This is analogous to the C/C++ (hard-float) calling convention.
46 *   v0-v7  : Floating-point argument registers in both Dalvik and C/C++ conventions.
47 *            Also used as temporary and codegen scratch registers.
48 *
49 *   v0-v7 and v16-v31 : Caller save registers (used as temporary registers).
50 *   v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved).
51 *
52 *   v16-v31: Used as codegen temp/scratch.
53 *   v8-v15 : Can be used for promotion.
54 *
55 *   Must maintain 16-byte stack alignment.
56 *
57 * Nterp notes:
58 *
59 * The following registers have fixed assignments:
60 *
61 *   reg nick      purpose
62 *   x19  xSELF     self (Thread) pointer
63 *   x20  wMR       marking register
64 *   x21  xSUSPEND  suspend check register
65 *   x29  xFP       interpreted frame pointer, used for accessing locals and args
66 *   x22  xPC       interpreted program counter, used for fetching instructions
67 *   x23  xINST     first 16-bit code unit of current instruction
68 *   x24  xIBASE    interpreted instruction base pointer, used for computed goto
69 *   x25  xREFS     base of object references of dex registers.
70 *   x16  ip        scratch reg
71 *   x17  ip2       scratch reg (used by macros)
72 *
73 * Macros are provided for common operations.  They MUST NOT alter unspecified registers or
74 * condition codes.
75*/
76
77/* single-purpose registers, given names for clarity */
78#define CFI_DEX  22 // DWARF register number of the register holding dex-pc (xPC).
79#define CFI_TMP  0  // DWARF register number of the first argument register (r0).
80#define xPC      x22
81#define xINST    x23
82#define wINST    w23
83#define xIBASE   x24
84#define xREFS    x25
85#define CFI_REFS 25
86#define ip       x16
87#define ip2      x17
88#define wip      w16
89#define wip2     w17
90
91// To avoid putting ifdefs arond the use of wMR, make sure it's defined.
92// IsNterpSupported returns false for configurations that don't have wMR (typically CMS).
93#ifndef wMR
94#define wMR w20
95#endif
96
97// Temporary registers while setting up a frame.
98#define xNEW_FP   x26
99#define xNEW_REFS x27
100#define CFI_NEW_REFS 27
101
102// +8 for the ArtMethod of the caller.
103#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 8)
104
105/*
106 * Fetch the next instruction from xPC into wINST.  Does not advance xPC.
107 */
108.macro FETCH_INST
109    ldrh    wINST, [xPC]
110.endm
111
112/*
113 * Fetch the next instruction from the specified offset.  Advances xPC
114 * to point to the next instruction.  "count" is in 16-bit code units.
115 *
116 * Because of the limited size of immediate constants on ARM, this is only
117 * suitable for small forward movements (i.e. don't try to implement "goto"
118 * with this).
119 *
120 * This must come AFTER anything that can throw an exception, or the
121 * exception catch may miss.  (This also implies that it must come after
122 * EXPORT_PC.)
123 */
124.macro FETCH_ADVANCE_INST count
125    ldrh    wINST, [xPC, #((\count)*2)]!
126.endm
127
128/*
129 * Similar to FETCH_ADVANCE_INST, but does not update xPC.  Used to load
130 * xINST ahead of possible exception point.  Be sure to manually advance xPC
131 * later.
132 */
133.macro PREFETCH_INST count
134    ldrh    wINST, [xPC, #((\count)*2)]
135.endm
136
137/* Advance xPC by some number of code units. */
138.macro ADVANCE count
139  add  xPC, xPC, #((\count)*2)
140.endm
141
142/*
143 * Fetch a half-word code unit from an offset past the current PC.  The
144 * "count" value is in 16-bit code units.  Does not advance xPC.
145 *
146 * The "_S" variant works the same but treats the value as signed.
147 */
148.macro FETCH reg, count
149    ldrh    \reg, [xPC, #((\count)*2)]
150.endm
151
152.macro FETCH_S reg, count
153    ldrsh   \reg, [xPC, #((\count)*2)]
154.endm
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161.macro FETCH_B reg, count, byte
162    ldrb     \reg, [xPC, #((\count)*2+(\byte))]
163.endm
164
165/*
166 * Put the instruction's opcode field into the specified register.
167 */
168.macro GET_INST_OPCODE reg
169    and     \reg, xINST, #255
170.endm
171
172/*
173 * Begin executing the opcode in _reg.  Clobbers reg
174 */
175
176.macro GOTO_OPCODE reg
177    add     \reg, xIBASE, \reg, lsl #NTERP_HANDLER_SIZE_LOG2
178    br      \reg
179.endm
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184.macro GET_VREG reg, vreg
185    ldr     \reg, [xFP, \vreg, uxtw #2]
186.endm
187.macro GET_VREG_OBJECT reg, vreg
188    ldr     \reg, [xREFS, \vreg, uxtw #2]
189.endm
190.macro SET_VREG reg, vreg
191    str     \reg, [xFP, \vreg, uxtw #2]
192    str     wzr, [xREFS, \vreg, uxtw #2]
193.endm
194.macro SET_VREG_OBJECT reg, vreg
195    str     \reg, [xFP, \vreg, uxtw #2]
196    str     \reg, [xREFS, \vreg, uxtw #2]
197.endm
198.macro SET_VREG_FLOAT reg, vreg
199    str     \reg, [xFP, \vreg, uxtw #2]
200    str     wzr, [xREFS, \vreg, uxtw #2]
201.endm
202
203/*
204 * Get/set the 64-bit value from a Dalvik register.
205 */
206.macro LOAD_SCALED_VREG_MASK scaled_mask_reg, unscaled_mask
207    mov     \scaled_mask_reg, \unscaled_mask << 2
208.endm
209.macro EXTRACT_SCALED_VREG scaled_vreg, scaled_mask_reg, src_reg, lsb
210    .if \lsb < 2
211    and     \scaled_vreg, \scaled_mask_reg, \src_reg, lsl #(2 - \lsb)
212    .else
213    and     \scaled_vreg, \scaled_mask_reg, \src_reg, lsr #(\lsb - 2)
214    .endif
215.endm
216.macro GET_VREG_WIDE_PRESCALED reg, scaled_vreg
217    ldr     \reg, [xFP, \scaled_vreg, uxtw]
218.endm
219.macro GET_VREG_WIDE reg, vreg
220    lsl     wip2, \vreg, #2
221    GET_VREG_WIDE_PRESCALED \reg, wip2
222.endm
223.macro SET_VREG_WIDE_PRESCALED reg, scaled_vreg
224    str     \reg, [xFP, \scaled_vreg, uxtw]
225    str     xzr, [xREFS, \scaled_vreg, uxtw]
226.endm
227.macro SET_VREG_WIDE reg, vreg
228    lsl     wip2, \vreg, #2
229    SET_VREG_WIDE_PRESCALED \reg, wip2
230.endm
231.macro GET_VREG_DOUBLE_PRESCALED reg, scaled_vreg
232    GET_VREG_WIDE_PRESCALED \reg, \scaled_vreg
233.endm
234.macro GET_VREG_DOUBLE reg, vreg
235    GET_VREG_WIDE \reg, \vreg
236.endm
237.macro SET_VREG_DOUBLE reg, vreg
238    SET_VREG_WIDE \reg, \vreg
239.endm
240
241/*
242 * Get the 32-bit value from a Dalvik register and sign-extend to 64-bit.
243 * Used to avoid an extra instruction in int-to-long.
244 */
245.macro GET_VREG_S reg, vreg
246    ldrsw   \reg, [xFP, \vreg, uxtw #2]
247.endm
248
249// An assembly entry for nterp.
250.macro OAT_ENTRY name
251    .type \name, #function
252    .hidden \name
253    .global \name
254    .balign 16
255\name:
256.endm
257
258.macro SIZE name
259    .size \name, .-\name
260.endm
261
262.macro NAME_START name
263    .type \name, #function
264    .hidden \name  // Hide this as a global symbol, so we do not incur plt calls.
265    .global \name
266    /* Cache alignment for function entry */
267    .balign 16
268\name:
269.endm
270
271.macro NAME_END name
272  SIZE \name
273.endm
274
275// Macro for defining entrypoints into runtime. We don't need to save registers
276// (we're not holding references there), but there is no
277// kDontSave runtime method. So just use the kSaveRefsOnly runtime method.
278.macro NTERP_TRAMPOLINE name, helper
279ENTRY \name
280  SETUP_SAVE_REFS_ONLY_FRAME
281  bl \helper
282  RESTORE_SAVE_REFS_ONLY_FRAME
283  REFRESH_MARKING_REGISTER
284  ldr xIP0, [xSELF, # THREAD_EXCEPTION_OFFSET]   // Get exception field.
285  cbnz xIP0, nterp_deliver_pending_exception
286  ret
287END \name
288.endm
289
290.macro CLEAR_STATIC_VOLATILE_MARKER reg
291  and \reg, \reg, #-2
292.endm
293
294.macro CLEAR_INSTANCE_VOLATILE_MARKER reg
295  neg \reg, \reg
296.endm
297
298.macro EXPORT_PC
299    str    xPC, [xREFS, #-16]
300.endm
301
302.macro BRANCH
303    add     xPC, xPC, wINST, sxtw #1    // update xPC
304    // Update method counter and do a suspend check if the branch is negative or zero.
305    cmp wINST, #0
306    b.le 2f
3071:
308    FETCH wINST, 0                      // load wINST
309    GET_INST_OPCODE ip                  // extract opcode from wINST
310    GOTO_OPCODE ip                      // jump to next instruction
3112:
312    ldr x0, [sp]
313    ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
314#if (NTERP_HOTNESS_VALUE != 0)
315#error Expected 0 for hotness value
316#endif
317    // If the counter is at zero, handle this in the runtime.
318    cbz w2, NterpHandleHotnessOverflow
319    add x2, x2, #-1
320    strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
321    DO_SUSPEND_CHECK continue_label=1b
322    b 1b
323.endm
324
325// Uses x12, x13, and x14 as temporaries.
326.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins
327    // Fetch dex register size.
328    ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET]
329    // Fetch outs size.
330    ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET]
331    .if \load_ins
332    ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET]
333    .endif
334    add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET
335.endm
336
337.macro TEST_IF_MARKING label
338    cbnz wMR, \label
339.endm
340
341// Setup the stack to start executing the method. Expects:
342// - x0 to contain the ArtMethod
343//
344// Outputs
345// - ip contains the dex registers size
346// - x28 contains the old stack pointer.
347// - \code_item is replaced with a pointer to the instructions
348// - if load_ins is 1, w15 contains the ins
349//
350// Uses ip, ip2, x12, x13, x14 as temporaries.
351.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins
352    FETCH_CODE_ITEM_INFO \code_item, wip, wip2, w15, \load_ins
353
354    // Compute required frame size: ((2 * ip) + ip2) * 4 + 24
355    // 24 is for saving the previous frame, pc, and method being executed.
356    add x14, ip, ip
357    add x14, x14, ip2
358    lsl x14, x14, #2
359    add x14, x14, #24
360
361    // Compute new stack pointer in x14
362    sub x14, sp, x14
363    // Alignment
364    and x14, x14, #-16
365
366    // Set reference and dex registers, align to pointer size for previous frame and dex pc.
367    add \refs, x14, ip2, lsl #2
368    add \refs, \refs, 28
369    and \refs, \refs, #(-__SIZEOF_POINTER__)
370    add \fp, \refs, ip, lsl #2
371
372    // Now setup the stack pointer.
373    mov x28, sp
374    .cfi_def_cfa_register x28
375    mov sp, x14
376    str x28, [\refs, #-8]
377    CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -8, CALLEE_SAVES_SIZE
378
379    // Put nulls in reference frame.
380    cbz ip, 2f
381    mov ip2, \refs
3821:
383    str xzr, [ip2], #8  // May clear vreg[0].
384    cmp ip2, \fp
385    b.lo 1b
3862:
387    // Save the ArtMethod.
388    str x0, [sp]
389.endm
390
391// Increase method hotness and do suspend check before starting executing the method.
392.macro START_EXECUTING_INSTRUCTIONS
393    ldr x0, [sp]
394    ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
395#if (NTERP_HOTNESS_VALUE != 0)
396#error Expected 0 for hotness value
397#endif
398    // If the counter is at zero, handle this in the runtime.
399    cbz w2, 3f
400    add x2, x2, #-1
401    strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
4021:
403    DO_SUSPEND_CHECK continue_label=2f
4042:
405    FETCH_INST
406    GET_INST_OPCODE ip
407    GOTO_OPCODE ip
4083:
409    CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=4f, if_not_hot=1b
4104:
411    mov x1, xzr
412    mov x2, xFP
413    bl nterp_hot_method
414    b 2b
415.endm
416
417.macro SPILL_ALL_CALLEE_SAVES
418    INCREASE_FRAME CALLEE_SAVES_SIZE
419    // Note: we technically don't need to save x19 and x20,
420    // but the runtime will expect those values to be there when unwinding
421    // (see Arm64Context::DoLongJump checking for the thread register).
422    SAVE_ALL_CALLEE_SAVES 0
423.endm
424
425.macro RESTORE_ALL_CALLEE_SAVES
426    // FP callee-saves
427    ldp d8, d9, [sp, #0]
428    ldp d10, d11, [sp, #16]
429    ldp d12, d13, [sp, #32]
430    ldp d14, d15, [sp, #48]
431
432    // GP callee-saves.
433    // No need to restore x19 (it's always the thread), and
434    // don't restore x20 (the marking register) as it may have been updated,
435    // don't restore x21 (the suspend check register) as it may have been updated.
436    RESTORE_REG      x22, 88
437    RESTORE_TWO_REGS x23, x24, 96
438    RESTORE_TWO_REGS x25, x26, 112
439    RESTORE_TWO_REGS x27, x28, 128
440    RESTORE_TWO_REGS x29, lr, 144
441
442    DECREASE_FRAME CALLEE_SAVES_SIZE
443.endm
444
445.macro SPILL_ALL_ARGUMENTS
446    stp x0, x1, [sp, #-128]!
447    stp x2, x3, [sp, #16]
448    stp x4, x5, [sp, #32]
449    stp x6, x7, [sp, #48]
450    stp d0, d1, [sp, #64]
451    stp d2, d3, [sp, #80]
452    stp d4, d5, [sp, #96]
453    stp d6, d7, [sp, #112]
454.endm
455
456.macro RESTORE_ALL_ARGUMENTS
457    ldp x2, x3, [sp, #16]
458    ldp x4, x5, [sp, #32]
459    ldp x6, x7, [sp, #48]
460    ldp d0, d1, [sp, #64]
461    ldp d2, d3, [sp, #80]
462    ldp d4, d5, [sp, #96]
463    ldp d6, d7, [sp, #112]
464    ldp x0, x1, [sp], #128
465.endm
466
467// Helper to setup the stack after doing a nterp to nterp call. This will setup:
468// - xNEW_FP: the new pointer to dex registers
469// - xNEW_REFS: the new pointer to references
470// - xPC: the new PC pointer to execute
471// - x2: value in instruction to decode the number of arguments.
472// - x3: first dex register
473// - x4: top of dex register array
474//
475// The method expects:
476// - x0 to contain the ArtMethod
477// - x8 to contain the code item
478.macro SETUP_STACK_FOR_INVOKE
479   // We do the same stack overflow check as the compiler. See CanMethodUseNterp
480   // in how we limit the maximum nterp frame size.
481   sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES
482   ldr wzr, [x16]
483
484   // Spill all callee saves to have a consistent stack frame whether we
485   // are called by compiled code or nterp.
486   SPILL_ALL_CALLEE_SAVES
487
488   // Setup the frame.
489   SETUP_STACK_FRAME x8, xNEW_REFS, xNEW_FP, CFI_NEW_REFS, load_ins=0
490   // Make x4 point to the top of the dex register array.
491   add x4, xNEW_FP, ip, uxtx #2
492
493   // Fetch instruction information before replacing xPC.
494   // TODO: move this down to the method that uses it, fetching it directly from wINST.
495   FETCH_B w2, 0, 1
496   // TODO: we could avoid this as instance invokes already fetch it.
497   FETCH w3, 2
498
499   // Set the dex pc pointer.
500   mov xPC, x8
501   CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
502.endm
503
504// Setup arguments based on a non-range nterp to nterp call, and start executing
505// the method. We expect:
506// - xNEW_FP: the new pointer to dex registers
507// - xNEW_REFS: the new pointer to references
508// - xPC: the new PC pointer to execute
509// - x2: number of arguments (bits 4-7), 5th argument if any (bits 0-3)
510// - x3: first dex register
511// - x4: top of dex register array
512// - x1: receiver if non-static.
513.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
514   // /* op vA, vB, {vC...vG} */
515   asr ip2, x2, #4
516   cbz ip2, 6f
517   mov ip, #-4
518   cmp ip2, #2
519   b.lt 1f
520   b.eq 2f
521   cmp ip2, #4
522   b.lt 3f
523   b.eq 4f
524
525  // We use a decrementing ip to store references relative
526  // to xNEW_FP and dex registers relative to x4
527  //
528  // TODO: We could set up ip as the number of registers (this can be an additional output from
529  // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg.
530  // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS.
5315:
532   and         x2, x2, #15
533   GET_VREG_OBJECT w5, w2
534   str         w5, [xNEW_FP, ip]
535   GET_VREG    w5, w2
536   str         w5, [x4, ip]
537   sub         ip, ip, #4
5384:
539   asr         x2, x3, #12
540   GET_VREG_OBJECT w5, w2
541   str         w5, [xNEW_FP, ip]
542   GET_VREG    w5, w2
543   str         w5, [x4, ip]
544   sub         ip, ip, #4
5453:
546   ubfx        x2, x3, #8, #4
547   GET_VREG_OBJECT w5, w2
548   str         w5, [xNEW_FP, ip]
549   GET_VREG    w5, w2
550   str         w5, [x4, ip]
551   sub         ip, ip, #4
5522:
553   ubfx        x2, x3, #4, #4
554   GET_VREG_OBJECT w5, w2
555   str         w5, [xNEW_FP, ip]
556   GET_VREG    w5, w2
557   str         w5, [x4, ip]
558   .if !\is_string_init
559   sub         ip, ip, #4
560   .endif
5611:
562   .if \is_string_init
563   // Ignore the first argument
564   .elseif \is_static
565   and         x2, x3, #0xf
566   GET_VREG_OBJECT w5, w2
567   str         w5, [xNEW_FP, ip]
568   GET_VREG    w5, w2
569   str         w5, [x4, ip]
570   .else
571   str         w1, [xNEW_FP, ip]
572   str         w1, [x4, ip]
573   .endif
574
5756:
576   // Start executing the method.
577   mov xFP, xNEW_FP
578   mov xREFS, xNEW_REFS
579   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
580   START_EXECUTING_INSTRUCTIONS
581.endm
582
583// Setup arguments based on a range nterp to nterp call, and start executing
584// the method.
585// - xNEW_FP: the new pointer to dex registers
586// - xNEW_REFS: the new pointer to references
587// - xPC: the new PC pointer to execute
588// - x2: number of arguments
589// - x3: first dex register
590// - x4: top of dex register array
591// - x1: receiver if non-static.
592//
593// Uses ip, ip2, x5, x6 as temporaries.
594.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
595   mov ip, #-4
596   .if \is_string_init
597   // Ignore the first argument
598   sub x2, x2, #1
599   add x3, x3, #1
600   .elseif !\is_static
601   sub x2, x2, #1
602   add x3, x3, #1
603   .endif
604
605   cbz x2, 2f
606   add ip2, xREFS, x3, lsl #2  // pointer to first argument in reference array
607   add ip2, ip2, x2, lsl #2    // pointer to last argument in reference array
608   add x5, xFP, x3, lsl #2     // pointer to first argument in register array
609   add x6, x5, x2, lsl #2      // pointer to last argument in register array
6101:
611   ldr  w7, [ip2, #-4]!
612   str  w7, [xNEW_FP, ip]
613   sub  x2, x2, 1
614   ldr  w7, [x6, #-4]!
615   str  w7, [x4, ip]
616   sub ip, ip, 4
617   cbnz x2, 1b
6182:
619   .if \is_string_init
620   // Ignore first argument
621   .elseif !\is_static
622   str w1, [xNEW_FP, ip]
623   str w1, [x4, ip]
624   .endif
625   mov xFP, xNEW_FP
626   mov xREFS, xNEW_REFS
627   CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
628   START_EXECUTING_INSTRUCTIONS
629.endm
630
631.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom
632   stp x0, x1, [sp, #-16]!
633   .if \is_polymorphic
634   ldr x0, [sp, #16]
635   mov x1, xPC
636   bl NterpGetShortyFromInvokePolymorphic
637   .elseif \is_custom
638   ldr x0, [sp, #16]
639   mov x1, xPC
640   bl NterpGetShortyFromInvokeCustom
641   .elseif \is_interface
642   ldr x0, [sp, #16]
643   FETCH w1, 1
644   bl NterpGetShortyFromMethodId
645   .else
646   bl NterpGetShorty
647   .endif
648   mov \dest, x0
649   ldp x0, x1, [sp], #16
650.endm
651
652.macro GET_SHORTY_SLOW_PATH dest, is_interface
653   // Save all registers that can hold arguments in the fast path.
654   stp x0, x1, [sp, #-32]!
655   str w2, [sp, #16]
656   str s0, [sp, #20]
657   .if \is_interface
658   ldr x0, [sp, #32]
659   FETCH w1, 1
660   bl NterpGetShortyFromMethodId
661   .else
662   bl NterpGetShorty
663   .endif
664   mov \dest, x0
665   ldr w2, [sp, #16]
666   ldr s0, [sp, #20]
667   ldp x0, x1, [sp], #32
668.endm
669
670// Input:  x0 contains the ArtMethod
671// Output: x8 contains the code item
672.macro GET_CODE_ITEM
673   ldr x8, [x0, #ART_METHOD_DATA_OFFSET_64]
674.endm
675
676.macro DO_ENTRY_POINT_CHECK call_compiled_code
677   // On entry, the method is x0, the instance is x1
678   adr x2, ExecuteNterpImpl
679   ldr x3, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
680   cmp x2, x3
681   b.ne  \call_compiled_code
682.endm
683
684.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value
685   mov wip, wzr
6861:
687   GET_VREG_OBJECT wip2, wip
688   cmp wip2, \old_value
689   b.ne 2f
690   SET_VREG_OBJECT \new_value, wip
6912:
692   add wip, wip, #1
693   add ip2, xREFS, wip, uxtw #2
694   cmp ip2, xFP
695   b.ne 1b
696.endm
697
698// Puts the next floating point argument into the expected register,
699// fetching values based on a non-range invoke.
700// Uses ip and ip2.
701.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished
7021: // LOOP
703    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
704    cbz wip, \finished              // if (wip == '\0') goto finished
705    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
706    b.eq 2f
707    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
708    b.eq 3f
709    lsr \inst, \inst, #4
710    add \arg_index, \arg_index, #1
711    //  Handle extra argument in arg array taken by a long.
712    cmp wip, #74                   // if (wip != 'J') goto LOOP
713    b.ne 1b
714    lsr \inst, \inst, #4
715    add \arg_index, \arg_index, #1
716    b 1b                        // goto LOOP
7172:  // FOUND_DOUBLE
718    and ip, \inst, #0xf
719    GET_VREG wip, wip
720    lsr \inst, \inst, #4
721    add \arg_index, \arg_index, #1
722    cmp \arg_index, #4
723    b.eq 5f
724    and ip2, \inst, #0xf
725    lsr \inst, \inst, #4
726    add \arg_index, \arg_index, #1
727    b 6f
7285:
729    // TODO: Extract from wINST here and below? (Requires using a different register
730    // in the COMMON_INVOKE_NON_RANGE.)
731    FETCH_B wip2, 0, 1
732    and wip2, wip2, #0xf
7336:
734    GET_VREG wip2, wip2
735    add ip, ip, ip2, lsl #32
736    fmov \dreg, ip
737    b 4f
7383:  // FOUND_FLOAT
739    cmp \arg_index, #4
740    b.eq 7f
741    and ip, \inst, #0xf
742    lsr \inst, \inst, #4
743    add \arg_index, \arg_index, #1
744    b 8f
7457:
746    FETCH_B wip, 0, 1
747    and wip, wip, #0xf
7488:
749    GET_VREG \sreg, wip
7504:
751.endm
752
753// Puts the next int/long/object argument in the expected register,
754// fetching values based on a non-range invoke.
755// Uses ip and ip2.
756.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished
7571: // LOOP
758    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
759    cbz wip, \finished              // if (wip == '\0') goto finished
760    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
761    b.eq 2f
762    cmp wip, #70                    // if (wip == 'F') goto SKIP_FLOAT
763    b.eq 3f
764    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
765    b.eq 4f
766    cmp \arg_index, #4
767    b.eq 7f
768    and ip, \inst, #0xf
769    lsr \inst, \inst, #4
770    add \arg_index, \arg_index, #1
771    b 8f
7727:
773    FETCH_B wip, 0, 1
774    and wip, wip, #0xf
7758:
776    GET_VREG \gpr_reg32, wip
777    b 5f
7782:  // FOUND_LONG
779    and ip, \inst, #0xf
780    GET_VREG wip, wip
781    lsr \inst, \inst, #4
782    add \arg_index, \arg_index, #1
783    cmp \arg_index, #4
784    b.eq 9f
785    and ip2, \inst, #0xf
786    lsr \inst, \inst, #4
787    add \arg_index, \arg_index, #1
788    b 10f
7899:
790    FETCH_B wip2, 0, 1
791    and wip2, wip2, #0xf
79210:
793    GET_VREG wip2, wip2
794    add \gpr_reg64, ip, ip2, lsl #32
795    b 5f
7963:  // SKIP_FLOAT
797    lsr \inst, \inst, #4
798    add \arg_index, \arg_index, #1
799    b 1b
8004:  // SKIP_DOUBLE
801    lsr \inst, \inst, #4
802    add \arg_index, \arg_index, #1
803    cmp \arg_index, #4
804    b.eq 1b
805    lsr \inst, \inst, #4
806    add \arg_index, \arg_index, #1
807    b 1b
8085:
809.endm
810
811.macro SETUP_RETURN_VALUE shorty
812   ldrb wip, [\shorty]
813   cmp ip, #68       // Test if result type char == 'D'.
814   b.eq 1f
815   cmp ip, #70       // Test if result type char == 'F'.
816   b.ne 2f
817   fmov w0, s0
818   b 2f
8191:
820   fmov x0, d0
8212:
822.endm
823
824.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
825   .if \is_polymorphic
826   // We always go to compiled code for polymorphic calls.
827   .elseif \is_custom
828   // We always go to compiled code for custom calls.
829   .else
830     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix
831     GET_CODE_ITEM
832     .if \is_string_init
833     bl nterp_to_nterp_string_init_non_range
834     .elseif \is_static
835     bl nterp_to_nterp_static_non_range
836     .else
837     bl nterp_to_nterp_instance_non_range
838     .endif
839     b .Ldone_return_\suffix
840   .endif
841
842.Lcall_compiled_code_\suffix:
843   .if \is_polymorphic
844   // No fast path for polymorphic calls.
845   .elseif \is_custom
846   // No fast path for custom calls.
847   .elseif \is_string_init
848   // No fast path for string.init.
849   .else
850     ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
851     tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_\suffix
852     FETCH_B wip2, 0, 1
853     asr ip, ip2, #4
854     .if \is_static
855     cbz ip, .Linvoke_fast_path_\suffix
856     .else
857     cmp ip, #1
858     b.eq .Linvoke_fast_path_\suffix
859     .endif
860     FETCH w8, 2
861     cmp ip, #2
862     .if \is_static
863     b.lt .Lone_arg_fast_path_\suffix
864     .endif
865     b.eq .Ltwo_args_fast_path_\suffix
866     cmp ip, #4
867     b.lt .Lthree_args_fast_path_\suffix
868     b.eq .Lfour_args_fast_path_\suffix
869
870     and         ip, ip2, #15
871     GET_VREG    w5, wip
872.Lfour_args_fast_path_\suffix:
873     asr         ip, x8, #12
874     GET_VREG    w4, wip
875.Lthree_args_fast_path_\suffix:
876     ubfx        ip, x8, #8, #4
877     GET_VREG    w3, wip
878.Ltwo_args_fast_path_\suffix:
879     ubfx        ip, x8, #4, #4
880     GET_VREG    w2, wip
881.Lone_arg_fast_path_\suffix:
882     .if \is_static
883     and         ip, x8, #0xf
884     GET_VREG    w1, wip
885     .else
886     // First argument already in w1.
887     .endif
888.Linvoke_fast_path_\suffix:
889     .if \is_interface
890     // Setup hidden argument.
891     mov ip2, x26
892     .endif
893     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
894     blr lr
895     FETCH_ADVANCE_INST 3
896     GET_INST_OPCODE ip
897     GOTO_OPCODE ip
898
899.Lfast_path_with_few_args_\suffix:
900     // Fast path when we have zero or one argument (modulo 'this'). If there
901     // is one argument, we can put it in both floating point and core register.
902     FETCH_B w2, 0, 1
903     .if \is_static
904     cmp w2, #(2 << 4)
905     .else
906     cmp w2, #(3 << 4)
907     .endif
908     b.ge .Lget_shorty_\suffix
909     .if \is_static
910     tbz w2, #4, .Linvoke_with_few_args_\suffix
911     .else
912     tbnz w2, #4, .Linvoke_with_few_args_\suffix
913     .endif
914     FETCH w2, 2
915     .if \is_static
916     and w2, w2, #0xf  // dex register of first argument
917     GET_VREG w1, w2
918     fmov s0, w1
919     .else
920     ubfx x2, x2, #4, #4  // dex register of second argument
921     GET_VREG w2, w2
922     fmov s0, w2
923     .endif
924.Linvoke_with_few_args_\suffix:
925     // Check if the next instruction is move-result or move-result-wide.
926     // If it is, we fetch the shorty and jump to the regular invocation.
927     FETCH w27, 3
928     and ip, x27, #0xfe
929     cmp ip, #0x0a
930     b.eq .Lget_shorty_and_invoke_\suffix
931     .if \is_interface
932     // Setup hidden argument.
933     mov ip2, x26
934     .endif
935     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
936     blr lr
937     # TODO: Use some other register for shorty and prefetch the instruction directly to wINST.
938     mov xINST, x27
939     ADVANCE 3
940     GET_INST_OPCODE ip
941     GOTO_OPCODE ip
942.Lget_shorty_and_invoke_\suffix:
943     GET_SHORTY_SLOW_PATH xINST, \is_interface
944     b .Lgpr_setup_finished_\suffix
945   .endif
946
947.Lget_shorty_\suffix:
948   GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom
949   // From this point:
950   // - xINST contains shorty (in callee-save to switch over return value after call).
951   // - x0 contains method
952   // - x1 contains 'this' pointer for instance method.
953   // - for interface calls, x26 contains the interface method.
954   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
955   FETCH w11, 2 // arguments
956   .if \is_string_init
957   lsr x11, x11, #4
958   mov x10, #1       // ignore first argument
959   .elseif \is_static
960   mov x10, xzr      // arg_index
961   .else
962   lsr x11, x11, #4
963   mov x10, #1       // ignore first argument
964   .endif
965   LOOP_OVER_SHORTY_LOADING_FPS d0, s0, x11, x9, x10, .Lxmm_setup_finished_\suffix
966   LOOP_OVER_SHORTY_LOADING_FPS d1, s1, x11, x9, x10, .Lxmm_setup_finished_\suffix
967   LOOP_OVER_SHORTY_LOADING_FPS d2, s2, x11, x9, x10, .Lxmm_setup_finished_\suffix
968   LOOP_OVER_SHORTY_LOADING_FPS d3, s3, x11, x9, x10, .Lxmm_setup_finished_\suffix
969   LOOP_OVER_SHORTY_LOADING_FPS d4, s4, x11, x9, x10, .Lxmm_setup_finished_\suffix
970.Lxmm_setup_finished_\suffix:
971   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
972   FETCH w11, 2 // arguments
973   .if \is_string_init
974   lsr x11, x11, #4
975   mov x10, #1       // ignore first argument
976   LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix
977   .elseif \is_static
978   mov x10, xzr      // arg_index
979   LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix
980   .else
981   lsr x11, x11, #4
982   mov x10, #1       // ignore first argument
983   .endif
984   LOOP_OVER_SHORTY_LOADING_GPRS x2, w2, x11, x9, x10, .Lgpr_setup_finished_\suffix
985   LOOP_OVER_SHORTY_LOADING_GPRS x3, w3, x11, x9, x10, .Lgpr_setup_finished_\suffix
986   LOOP_OVER_SHORTY_LOADING_GPRS x4, w4, x11, x9, x10, .Lgpr_setup_finished_\suffix
987   LOOP_OVER_SHORTY_LOADING_GPRS x5, w5, x11, x9, x10, .Lgpr_setup_finished_\suffix
988.Lgpr_setup_finished_\suffix:
989   .if \is_polymorphic
990   bl art_quick_invoke_polymorphic
991   .elseif \is_custom
992   bl art_quick_invoke_custom
993   .else
994      .if \is_interface
995      // Setup hidden argument.
996      mov ip2, x26
997      .endif
998      ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
999      blr lr
1000   .endif
1001   SETUP_RETURN_VALUE xINST
1002.Ldone_return_\suffix:
1003   /* resume execution of caller */
1004   .if \is_string_init
1005   FETCH w11, 2 // arguments
1006   and x11, x11, #0xf
1007   GET_VREG w1, w11
1008   UPDATE_REGISTERS_FOR_STRING_INIT w1, w0
1009   .endif
1010
1011   .if \is_polymorphic
1012   FETCH_ADVANCE_INST 4
1013   .else
1014   FETCH_ADVANCE_INST 3
1015   .endif
1016   GET_INST_OPCODE ip
1017   GOTO_OPCODE ip
1018.endm
1019
1020// Puts the next floating point argument into the expected register,
1021// fetching values based on a range invoke.
1022// Uses ip as temporary.
1023.macro LOOP_RANGE_OVER_SHORTY_LOADING_FPS dreg, sreg, shorty, arg_index, stack_index, finished
10241: // LOOP
1025    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
1026    cbz wip, \finished              // if (wip == '\0') goto finished
1027    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
1028    b.eq 2f
1029    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
1030    b.eq 3f
1031    add \arg_index, \arg_index, #1
1032    add \stack_index, \stack_index, #1
1033    //  Handle extra argument in arg array taken by a long.
1034    cmp wip, #74                    // if (wip != 'J') goto LOOP
1035    b.ne 1b
1036    add \arg_index, \arg_index, #1
1037    add \stack_index, \stack_index, #1
1038    b 1b                        // goto LOOP
10392:  // FOUND_DOUBLE
1040    GET_VREG_DOUBLE \dreg, \arg_index
1041    add \arg_index, \arg_index, #2
1042    add \stack_index, \stack_index, #2
1043    b 4f
10443:  // FOUND_FLOAT
1045    GET_VREG \sreg, \arg_index
1046    add \arg_index, \arg_index, #1
1047    add \stack_index, \stack_index, #1
10484:
1049.endm
1050
1051// Puts the next floating point argument into the expected stack slot,
1052// fetching values based on a range invoke.
1053// Uses ip as temporary.
1054//
1055// TODO: We could just copy all the vregs to the stack slots in a simple loop
1056// without looking at the shorty at all. (We could also drop
1057// the "stack_index" from the macros for loading registers.) We could also do
1058// that conditionally if argument word count > 6; otherwise we know that all
1059// args fit into registers.
1060.macro LOOP_RANGE_OVER_FPs shorty, arg_index, stack_index, finished
10611: // LOOP
1062    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
1063    cbz wip, \finished              // if (wip == '\0') goto finished
1064    cmp wip, #68                    // if (wip == 'D') goto FOUND_DOUBLE
1065    b.eq 2f
1066    cmp wip, #70                    // if (wip == 'F') goto FOUND_FLOAT
1067    b.eq 3f
1068    add \arg_index, \arg_index, #1
1069    add \stack_index, \stack_index, #1
1070    //  Handle extra argument in arg array taken by a long.
1071    cmp wip, #74                    // if (wip != 'J') goto LOOP
1072    b.ne 1b
1073    add \arg_index, \arg_index, #1
1074    add \stack_index, \stack_index, #1
1075    b 1b                        // goto LOOP
10762:  // FOUND_DOUBLE
1077    GET_VREG_WIDE ip, \arg_index
1078    add ip2, sp, \stack_index, uxtw #2
1079    str ip, [ip2]
1080    add \arg_index, \arg_index, #2
1081    add \stack_index, \stack_index, #2
1082    b 1b
10833:  // FOUND_FLOAT
1084    GET_VREG wip, \arg_index
1085    str wip, [sp, \stack_index, uxtw #2]
1086    add \arg_index, \arg_index, #1
1087    add \stack_index, \stack_index, #1
1088    b 1b
1089.endm
1090
1091// Puts the next int/long/object argument in the expected register,
1092// fetching values based on a range invoke.
1093// Uses ip as temporary.
1094.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg64, reg32, shorty, arg_index, stack_index, finished
10951: // LOOP
1096    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
1097    cbz wip, \finished              // if (wip == '\0') goto finished
1098    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
1099    b.eq 2f
1100    cmp wip, #70                   // if (wip == 'F') goto SKIP_FLOAT
1101    b.eq 3f
1102    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
1103    b.eq 4f
1104    GET_VREG \reg32, \arg_index
1105    add \arg_index, \arg_index, #1
1106    add \stack_index, \stack_index, #1
1107    b 5f
11082:  // FOUND_LONG
1109    GET_VREG_WIDE \reg64, \arg_index
1110    add \arg_index, \arg_index, #2
1111    add \stack_index, \stack_index, #2
1112    b 5f
11133:  // SKIP_FLOAT
1114    add \arg_index, \arg_index, #1
1115    add \stack_index, \stack_index, #1
1116    b 1b
11174:  // SKIP_DOUBLE
1118    add \arg_index, \arg_index, #2
1119    add \stack_index, \stack_index, #2
1120    b 1b
11215:
1122.endm
1123
1124// Puts the next int/long/object argument in the expected stack slot,
1125// fetching values based on a range invoke.
1126// Uses ip as temporary.
1127.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished
11281: // LOOP
1129    ldrb wip, [\shorty], #1         // Load next character in shorty, and increment.
1130    cbz wip, \finished              // if (wip == '\0') goto finished
1131    cmp wip, #74                    // if (wip == 'J') goto FOUND_LONG
1132    b.eq 2f
1133    cmp wip, #70                    // if (wip == 'F') goto SKIP_FLOAT
1134    b.eq 3f
1135    cmp wip, #68                    // if (wip == 'D') goto SKIP_DOUBLE
1136    b.eq 4f
1137    GET_VREG wip, \arg_index
1138    str wip, [sp, \stack_index, uxtw #2]
1139    add \arg_index, \arg_index, #1
1140    add \stack_index, \stack_index, #1
1141    b 1b
11422:  // FOUND_LONG
1143    GET_VREG_WIDE ip, \arg_index
1144    add ip2, sp, \stack_index, uxtw #2
1145    str ip, [ip2]
1146    add \arg_index, \arg_index, #2
1147    add \stack_index, \stack_index, #2
1148    b 1b
11493:  // SKIP_FLOAT
1150    add \arg_index, \arg_index, #1
1151    add \stack_index, \stack_index, #1
1152    b 1b
11534:  // SKIP_DOUBLE
1154    add \arg_index, \arg_index, #2
1155    add \stack_index, \stack_index, #2
1156    b 1b
1157.endm
1158
1159.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0
1160   .if \is_polymorphic
1161   // We always go to compiled code for polymorphic calls.
1162   .elseif \is_custom
1163   // We always go to compiled code for custom calls.
1164   .else
1165     DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix
1166     GET_CODE_ITEM
1167     .if \is_string_init
1168     bl nterp_to_nterp_string_init_range
1169     .elseif \is_static
1170     bl nterp_to_nterp_static_range
1171     .else
1172     bl nterp_to_nterp_instance_range
1173     .endif
1174     b .Ldone_return_range_\suffix
1175   .endif
1176
1177.Lcall_compiled_code_range_\suffix:
1178   .if \is_polymorphic
1179   // No fast path for polymorphic calls.
1180   .elseif \is_custom
1181   // No fast path for custom calls.
1182   .elseif \is_string_init
1183   // No fast path for string.init.
1184   .else
1185     ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1186     tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_range_\suffix
1187     FETCH_B wip2, 0, 1  // Number of arguments
1188     .if \is_static
1189     cbz ip2, .Linvoke_fast_path_range_\suffix
1190     .else
1191     cmp ip2, #1
1192     b.eq .Linvoke_fast_path_range_\suffix
1193     .endif
1194     FETCH wip, 2  // dex register of first argument
1195     add x8, xFP, wip, uxtw #2  // location of first dex register value
1196     cmp ip2, #2
1197     .if \is_static
1198     b.lt .Lone_arg_fast_path_range_\suffix
1199     .endif
1200     b.eq .Ltwo_args_fast_path_range_\suffix
1201     cmp ip2, #4
1202     b.lt .Lthree_args_fast_path_range_\suffix
1203     b.eq .Lfour_args_fast_path_range_\suffix
1204     cmp ip2, #6
1205     b.lt .Lfive_args_fast_path_range_\suffix
1206     b.eq .Lsix_args_fast_path_range_\suffix
1207     cmp ip2, #7
1208     b.eq .Lseven_args_fast_path_range_\suffix
1209     // Setup x8 to point to the stack location of parameters we do not need
1210     // to put parameters in.
1211     add x9, sp, #8  // Add space for the ArtMethod
1212
1213.Lloop_over_fast_path_range_\suffix:
1214     sub ip2, ip2, #1
1215     ldr wip, [x8, ip2, lsl #2]
1216     str wip, [x9, ip2, lsl #2]
1217     cmp ip2, #7
1218     b.ne .Lloop_over_fast_path_range_\suffix
1219
1220.Lseven_args_fast_path_range_\suffix:
1221     ldr w7, [x8, #24]
1222.Lsix_args_fast_path_range_\suffix:
1223     ldr w6, [x8, #20]
1224.Lfive_args_fast_path_range_\suffix:
1225     ldr w5, [x8, #16]
1226.Lfour_args_fast_path_range_\suffix:
1227     ldr w4, [x8, #12]
1228.Lthree_args_fast_path_range_\suffix:
1229     ldr w3, [x8, #8]
1230.Ltwo_args_fast_path_range_\suffix:
1231     ldr w2, [x8, #4]
1232.Lone_arg_fast_path_range_\suffix:
1233     .if \is_static
1234     ldr w1, [x8, #0]
1235     .else
1236     // First argument already in w1.
1237     .endif
1238.Linvoke_fast_path_range_\suffix:
1239     .if \is_interface
1240     // Setup hidden argument.
1241     mov ip2, x26
1242     .endif
1243     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
1244     blr lr
1245     FETCH_ADVANCE_INST 3
1246     GET_INST_OPCODE ip
1247     GOTO_OPCODE ip
1248
1249.Lfast_path_with_few_args_range_\suffix:
1250     // Fast path when we have zero or one argument (modulo 'this'). If there
1251     // is one argument, we can put it in both floating point and core register.
1252     FETCH_B w2, 0, 1 // number of arguments
1253     .if \is_static
1254     cmp w2, #1
1255     .else
1256     cmp w2, #2
1257     .endif
1258     b.lt .Linvoke_with_few_args_range_\suffix
1259     b.ne .Lget_shorty_range_\suffix
1260     FETCH w3, 2  // dex register of first argument
1261     .if \is_static
1262     GET_VREG w1, w3
1263     fmov s0, w1
1264     .else
1265     add w3, w3, #1  // Add 1 for next argument
1266     GET_VREG w2, w3
1267     fmov s0, w2
1268     .endif
1269.Linvoke_with_few_args_range_\suffix:
1270     // Check if the next instruction is move-result or move-result-wide.
1271     // If it is, we fetch the shorty and jump to the regular invocation.
1272     FETCH w27, 3
1273     and ip, x27, #0xfe
1274     cmp ip, #0x0a
1275     b.eq .Lget_shorty_and_invoke_range_\suffix
1276     .if \is_interface
1277     // Setup hidden argument.
1278     mov ip2, x26
1279     .endif
1280     ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
1281     blr lr
1282     mov xINST, x27
1283     ADVANCE 3
1284     GET_INST_OPCODE ip
1285     GOTO_OPCODE ip
1286.Lget_shorty_and_invoke_range_\suffix:
1287     GET_SHORTY_SLOW_PATH xINST, \is_interface
1288     b .Lgpr_setup_finished_range_\suffix
1289   .endif
1290
1291.Lget_shorty_range_\suffix:
1292   GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom
1293   // From this point:
1294   // - xINST contains shorty (in callee-save to switch over return value after call).
1295   // - x0 contains method
1296   // - x1 contains 'this' pointer for instance method.
1297   // - for interface calls, x26 contains the interface method.
1298   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
1299   FETCH w10, 2 // arguments
1300   .if \is_string_init
1301   add x10, x10, #1  // arg start index
1302   mov x11, #1       // index in stack
1303   .elseif \is_static
1304   mov x11, xzr      // index in stack
1305   .else
1306   add x10, x10, #1  // arg start index
1307   mov x11, #1       // index in stack
1308   .endif
1309   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d0, s0, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1310   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d1, s1, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1311   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d2, s2, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1312   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d3, s3, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1313   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d4, s4, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1314   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d5, s5, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1315   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d6, s6, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1316   LOOP_RANGE_OVER_SHORTY_LOADING_FPS d7, s7, x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1317   // Store in the outs array (stored above the ArtMethod in the stack)
1318   add x11, x11, #2 // Add two words for the ArtMethod stored before the outs.
1319   LOOP_RANGE_OVER_FPs x9, w10, w11, .Lxmm_setup_finished_range_\suffix
1320.Lxmm_setup_finished_range_\suffix:
1321   add x9, xINST, #1  // shorty + 1  ; ie skip return arg character
1322   FETCH w10, 2 // arguments
1323   .if \is_string_init
1324   add x10, x10, #1  // arg start index
1325   mov x11, #1       // index in stack
1326   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1327   .elseif \is_static
1328   mov x11, xzr      // index in stack
1329   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11 .Lgpr_setup_finished_range_\suffix
1330   .else
1331   add x10, x10, #1  // arg start index
1332   mov x11, #1       // index in stack
1333   .endif
1334   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x2, w2, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1335   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x3, w3, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1336   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x4, w4, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1337   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x5, w5, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1338   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x6, w6, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1339   LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x7, w7, x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1340   // Store in the outs array (stored above the ArtMethod in the stack)
1341   add x11, x11, #2 // Add two words for the ArtMethod stored before the outs.
1342   LOOP_RANGE_OVER_INTs x9, w10, w11, .Lgpr_setup_finished_range_\suffix
1343.Lgpr_setup_finished_range_\suffix:
1344   .if \is_polymorphic
1345   bl art_quick_invoke_polymorphic
1346   .elseif \is_custom
1347   bl art_quick_invoke_custom
1348   .else
1349      .if \is_interface
1350      // Setup hidden argument.
1351      mov ip2, x26
1352      .endif
1353      ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
1354      blr lr
1355   .endif
1356   SETUP_RETURN_VALUE xINST
1357.Ldone_return_range_\suffix:
1358   /* resume execution of caller */
1359   .if \is_string_init
1360   FETCH w11, 2 // arguments
1361   GET_VREG w1, w11
1362   UPDATE_REGISTERS_FOR_STRING_INIT w1, w0
1363   .endif
1364
1365   .if \is_polymorphic
1366   FETCH_ADVANCE_INST 4
1367   .else
1368   FETCH_ADVANCE_INST 3
1369   .endif
1370   GET_INST_OPCODE ip
1371   GOTO_OPCODE ip
1372.endm
1373
1374.macro POISON_HEAP_REF_IF_OBJECT is_object, rRef
1375   .if \is_object
1376   POISON_HEAP_REF \rRef
1377   .endif
1378.endm
1379
1380.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label
1381   .if \is_object
1382   cbz     \value, \label
1383   ldr     ip, [xSELF, #THREAD_CARD_TABLE_OFFSET]
1384   lsr     wip2, \holder, #CARD_TABLE_CARD_SHIFT
1385   strb    wip, [ip, ip2]
1386\label:
1387   .endif
1388.endm
1389
1390// Puts the next int/long/object parameter passed in physical register
1391// in the expected dex register array entry, and in case of object in the
1392// expected reference array entry.
1393.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_64, gpr_32, shorty, arg_offset, regs, refs, finished
13941: // LOOP
1395    ldrb wip, [\shorty], #1       // Load next character in shorty, and increment.
1396    cbz wip, \finished            // if (wip == '\0') goto finished
1397    cmp wip, #74                  // if (wip == 'J') goto FOUND_LONG
1398    b.eq 2f
1399    cmp wip, #70                  // if (wip == 'F') goto SKIP_FLOAT
1400    b.eq 3f
1401    cmp wip, #68                  // if (wip == 'D') goto SKIP_DOUBLE
1402    b.eq 4f
1403    str \gpr_32, [\regs, \arg_offset]
1404    cmp wip, #76                  // if (wip != 'L') goto NOT_REFERENCE
1405    b.ne 6f
1406    str \gpr_32, [\refs, \arg_offset]
14076:  // NOT_REFERENCE
1408    add \arg_offset, \arg_offset, #4
1409    b 5f
14102:  // FOUND_LONG
1411    str \gpr_64, [\regs, \arg_offset]
1412    add \arg_offset, \arg_offset, #8
1413    b 5f
14143:  // SKIP_FLOAT
1415    add \arg_offset, \arg_offset, #4
1416    b 1b
14174:  // SKIP_DOUBLE
1418    add \arg_offset, \arg_offset, #8
1419    b 1b
14205:
1421.endm
1422
1423// Puts the next floating point parameter passed in physical register
1424// in the expected dex register array entry.
1425// Uses ip as temporary.
1426.macro LOOP_OVER_SHORTY_STORING_FPS dreg, sreg, shorty, arg_offset, fp, finished
14271: // LOOP
1428    ldrb wip, [\shorty], #1                 // Load next character in shorty, and increment.
1429    cbz wip, \finished                      // if (wip == '\0') goto finished
1430    cmp wip, #68                            // if (wip == 'D') goto FOUND_DOUBLE
1431    b.eq 2f
1432    cmp wip, #70                            // if (wip == 'F') goto FOUND_FLOAT
1433    b.eq 3f
1434    add \arg_offset, \arg_offset, #4
1435    //  Handle extra argument in arg array taken by a long.
1436    cmp wip, #74                            // if (wip != 'J') goto LOOP
1437    b.ne 1b
1438    add \arg_offset, \arg_offset, #4
1439    b 1b                        // goto LOOP
14402:  // FOUND_DOUBLE
1441    str \dreg, [\fp, \arg_offset]
1442    add \arg_offset, \arg_offset, #8
1443    b 4f
14443:  // FOUND_FLOAT
1445    str \sreg, [\fp, \arg_offset]
1446    add \arg_offset, \arg_offset, #4
14474:
1448.endm
1449
1450// Puts the next floating point parameter passed in stack
1451// in the expected dex register array entry.
1452// Uses ip as temporary.
1453//
1454// TODO: Or we could just spill regs to the reserved slots in the caller's
1455// frame and copy all regs in a simple loop. This time, however, we would
1456// need to look at the shorty anyway to look for the references.
1457// (The trade-off is different for passing arguments and receiving them.)
1458.macro LOOP_OVER_FPs shorty, arg_offset, regs, stack_ptr, finished
14591: // LOOP
1460    ldrb wip, [\shorty], #1                 // Load next character in shorty, and increment.
1461    cbz wip, \finished                      // if (wip == '\0') goto finished
1462    cmp wip, #68                            // if (wip == 'D') goto FOUND_DOUBLE
1463    b.eq 2f
1464    cmp wip, #70                            // if (wip == 'F') goto FOUND_FLOAT
1465    b.eq 3f
1466    add \arg_offset, \arg_offset, #4
1467    //  Handle extra argument in arg array taken by a long.
1468    cmp wip, #74                            // if (wip != 'J') goto LOOP
1469    b.ne 1b
1470    add \arg_offset, \arg_offset, #4
1471    b 1b                        // goto LOOP
14722:  // FOUND_DOUBLE
1473    add ip, \stack_ptr, \arg_offset
1474    ldr ip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1475    str ip, [\regs, \arg_offset]
1476    add \arg_offset, \arg_offset, #8
1477    b 1b
14783:  // FOUND_FLOAT
1479    add ip, \stack_ptr, \arg_offset
1480    ldr wip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1481    str wip, [\regs, \arg_offset]
1482    add \arg_offset, \arg_offset, #4
1483    b 1b
1484.endm
1485
1486// Puts the next int/long/object parameter passed in stack
1487// in the expected dex register array entry, and in case of object in the
1488// expected reference array entry.
1489// Uses ip and ip2 as temporary.
1490.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, finished
14911: // LOOP
1492    ldrb wip, [\shorty], #1       // Load next character in shorty, and increment.
1493    cbz wip, \finished            // if (wip == '\0') goto finished
1494    cmp wip, #74                  // if (wip == 'J') goto FOUND_LONG
1495    b.eq 2f
1496    cmp wip, #70                  // if (wip == 'F') goto SKIP_FLOAT
1497    b.eq 3f
1498    cmp wip, #68                  // if (wip == 'D') goto SKIP_DOUBLE
1499    b.eq 4f
1500    add ip2, \stack_ptr, \arg_offset
1501    ldr wip2, [ip2,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1502    str wip2, [\regs, \arg_offset]
1503    cmp wip, #76                  // if (wip != 'L') goto loop
1504    b.ne 3f
1505    str wip2, [\refs, \arg_offset]
1506    add \arg_offset, \arg_offset, #4
1507    b 1b
15082:  // FOUND_LONG
1509    add ip, \stack_ptr, \arg_offset
1510    ldr ip, [ip,  #OFFSET_TO_FIRST_ARGUMENT_IN_STACK]
1511    str ip, [\regs, \arg_offset]
1512    add \arg_offset, \arg_offset, #8
1513    b 1b
15143:  // SKIP_FLOAT
1515    add \arg_offset, \arg_offset, #4
1516    b 1b
15174:  // SKIP_DOUBLE
1518    add \arg_offset, \arg_offset, #8
1519    b 1b
1520.endm
1521
1522.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished
1523    str \gpr32, [\regs, \arg_offset]
1524    sub \ins, \ins, #1
1525    str \gpr32, [\refs, \arg_offset]
1526    add \arg_offset, \arg_offset, #4
1527    cbz \ins, \finished
1528.endm
1529
1530// Uses ip2 as temporary.
1531.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset
15321:
1533    ldr wip2, [\stack_ptr, \arg_offset]
1534    sub \ins, \ins, #1
1535    str wip2, [\regs, \arg_offset]
1536    str wip2, [\refs, \arg_offset]
1537    add \arg_offset, \arg_offset, #4
1538    cbnz \ins, 1b
1539.endm
1540
1541.macro CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot, if_not_hot
1542    ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1543    tbz wip, #ART_METHOD_IS_MEMORY_SHARED_FLAG_BIT, \if_hot
1544    // Intrinsics are always in the boot image and considered hot.
1545    tbnz wip, #ART_METHOD_IS_INTRINSIC_FLAG_BIT, \if_hot
1546    ldr wip, [xSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET]
1547    cbz wip, \if_hot
1548    add wip, wip, #-1
1549    str wip, [xSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET]
1550    b \if_not_hot
1551.endm
1552
1553.macro DO_SUSPEND_CHECK continue_label
1554    ldr wip, [xSELF, #THREAD_FLAGS_OFFSET]
1555    tst wip, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
1556    b.eq \continue_label
1557    EXPORT_PC
1558    bl    art_quick_test_suspend
1559.endm
1560
1561/*
1562 * ArtMethod entry point.
1563 *
1564 * On entry:
1565 *  x0   ArtMethod* callee
1566 *  rest  method parameters
1567 */
1568
1569OAT_ENTRY ExecuteNterpWithClinitImpl
1570    .cfi_startproc
1571    // For simplicity, we don't do a read barrier here, but instead rely
1572    // on art_quick_resolution_trampoline to always have a suspend point before
1573    // calling back here.
1574    ldr wip, [x0, #ART_METHOD_DECLARING_CLASS_OFFSET]
1575    ldr wip2, [ip, #MIRROR_CLASS_STATUS_OFFSET]
1576    lsr wip2, wip2, #MIRROR_CLASS_STATUS_SHIFT
1577    cmp wip2, #MIRROR_CLASS_STATUS_VISIBLY_INITIALIZED
1578    b.hs ExecuteNterpImpl
1579    cmp wip2, #MIRROR_CLASS_STATUS_INITIALIZED
1580    b.lo .Linitializing_check
1581    dmb ish
1582    b ExecuteNterpImpl
1583.Linitializing_check:
1584    cmp wip2, #MIRROR_CLASS_STATUS_INITIALIZING
1585    b.lo .Lresolution_trampoline
1586    ldr wip2, [ip, #MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET]
1587    ldr wip, [xSELF, #THREAD_TID_OFFSET]
1588    cmp wip, wip2
1589    b.eq ExecuteNterpImpl
1590.Lresolution_trampoline:
1591    b art_quick_resolution_trampoline
1592    .cfi_endproc
1593    .type EndExecuteNterpWithClinitImpl, #function
1594    .hidden EndExecuteNterpWithClinitImpl
1595    .global EndExecuteNterpWithClinitImpl
1596EndExecuteNterpWithClinitImpl:
1597
1598OAT_ENTRY ExecuteNterpImpl
1599    .cfi_startproc
1600    sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES
1601    ldr wzr, [x16]
1602    /* Spill callee save regs */
1603    SPILL_ALL_CALLEE_SAVES
1604
1605    ldr xPC, [x0, #ART_METHOD_DATA_OFFSET_64]
1606    // Setup the stack for executing the method.
1607    SETUP_STACK_FRAME xPC, xREFS, xFP, CFI_REFS, load_ins=1
1608
1609    // Setup the parameters
1610    cbz w15, .Lxmm_setup_finished
1611
1612    sub ip2, ip, x15
1613    ldr w26, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET]
1614    lsl x27, ip2, #2 // x27 is now the offset for inputs into the registers array.
1615
1616    tbz w26, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG_BIT, .Lsetup_slow_path
1617    // Setup pointer to inputs in FP and pointer to inputs in REFS
1618    add x10, xFP, x27
1619    add x11, xREFS, x27
1620    mov x12, #0
1621    SETUP_REFERENCE_PARAMETER_IN_GPR w1, x10, x11, w15, x12, .Lxmm_setup_finished
1622    SETUP_REFERENCE_PARAMETER_IN_GPR w2, x10, x11, w15, x12, .Lxmm_setup_finished
1623    SETUP_REFERENCE_PARAMETER_IN_GPR w3, x10, x11, w15, x12, .Lxmm_setup_finished
1624    SETUP_REFERENCE_PARAMETER_IN_GPR w4, x10, x11, w15, x12, .Lxmm_setup_finished
1625    SETUP_REFERENCE_PARAMETER_IN_GPR w5, x10, x11, w15, x12, .Lxmm_setup_finished
1626    SETUP_REFERENCE_PARAMETER_IN_GPR w6, x10, x11, w15, x12, .Lxmm_setup_finished
1627    SETUP_REFERENCE_PARAMETER_IN_GPR w7, x10, x11, w15, x12, .Lxmm_setup_finished
1628    add x28, x28, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK
1629    SETUP_REFERENCE_PARAMETERS_IN_STACK x10, x11, w15, x28, x12
1630    b .Lxmm_setup_finished
1631
1632.Lsetup_slow_path:
1633    // If the method is not static and there is one argument ('this'), we don't need to fetch the
1634    // shorty.
1635    tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lsetup_with_shorty
1636    str w1, [xFP, x27]
1637    str w1, [xREFS, x27]
1638    cmp w15, #1
1639    b.eq .Lxmm_setup_finished
1640
1641.Lsetup_with_shorty:
1642    // TODO: Get shorty in a better way and remove below
1643    SPILL_ALL_ARGUMENTS
1644    bl NterpGetShorty
1645    // Save shorty in callee-save xIBASE.
1646    mov xIBASE, x0
1647    RESTORE_ALL_ARGUMENTS
1648
1649    // Setup pointer to inputs in FP and pointer to inputs in REFS
1650    add x10, xFP, x27
1651    add x11, xREFS, x27
1652    mov x12, #0
1653
1654    add x9, xIBASE, #1  // shorty + 1  ; ie skip return arg character
1655    tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lhandle_static_method
1656    add x10, x10, #4
1657    add x11, x11, #4
1658    add x28, x28, #4
1659    b .Lcontinue_setup_gprs
1660.Lhandle_static_method:
1661    LOOP_OVER_SHORTY_STORING_GPRS x1, w1, x9, x12, x10, x11, .Lgpr_setup_finished
1662.Lcontinue_setup_gprs:
1663    LOOP_OVER_SHORTY_STORING_GPRS x2, w2, x9, x12, x10, x11, .Lgpr_setup_finished
1664    LOOP_OVER_SHORTY_STORING_GPRS x3, w3, x9, x12, x10, x11, .Lgpr_setup_finished
1665    LOOP_OVER_SHORTY_STORING_GPRS x4, w4, x9, x12, x10, x11, .Lgpr_setup_finished
1666    LOOP_OVER_SHORTY_STORING_GPRS x5, w5, x9, x12, x10, x11, .Lgpr_setup_finished
1667    LOOP_OVER_SHORTY_STORING_GPRS x6, w6, x9, x12, x10, x11, .Lgpr_setup_finished
1668    LOOP_OVER_SHORTY_STORING_GPRS x7, w7, x9, x12, x10, x11, .Lgpr_setup_finished
1669    LOOP_OVER_INTs x9, x12, x10, x11, x28, .Lgpr_setup_finished
1670.Lgpr_setup_finished:
1671    add x9, xIBASE, #1  // shorty + 1  ; ie skip return arg character
1672    mov x12, #0  // reset counter
1673    LOOP_OVER_SHORTY_STORING_FPS d0, s0, x9, x12, x10, .Lxmm_setup_finished
1674    LOOP_OVER_SHORTY_STORING_FPS d1, s1, x9, x12, x10, .Lxmm_setup_finished
1675    LOOP_OVER_SHORTY_STORING_FPS d2, s2, x9, x12, x10, .Lxmm_setup_finished
1676    LOOP_OVER_SHORTY_STORING_FPS d3, s3, x9, x12, x10, .Lxmm_setup_finished
1677    LOOP_OVER_SHORTY_STORING_FPS d4, s4, x9, x12, x10, .Lxmm_setup_finished
1678    LOOP_OVER_SHORTY_STORING_FPS d5, s5, x9, x12, x10, .Lxmm_setup_finished
1679    LOOP_OVER_SHORTY_STORING_FPS d6, s6, x9, x12, x10, .Lxmm_setup_finished
1680    LOOP_OVER_SHORTY_STORING_FPS d7, s7, x9, x12, x10, .Lxmm_setup_finished
1681    LOOP_OVER_FPs x9, x12, x10, x28, .Lxmm_setup_finished
1682.Lxmm_setup_finished:
1683    CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
1684
1685    // Set rIBASE
1686    adr xIBASE, artNterpAsmInstructionStart
1687    /* start executing the instruction at xPC */
1688    START_EXECUTING_INSTRUCTIONS
1689    /* NOTE: no fallthrough */
1690    // cfi info continues, and covers the whole nterp implementation.
1691    SIZE ExecuteNterpImpl
1692
1693    .type artNterpAsmInstructionStart, #function
1694    .hidden artNterpAsmInstructionStart
1695    .global artNterpAsmInstructionStart
1696artNterpAsmInstructionStart = .L_op_nop
1697    .text
1698
1699/* ------------------------------ */
1700    .balign NTERP_HANDLER_SIZE
1701.L_op_nop: /* 0x00 */
1702    NAME_START nterp_op_nop
1703    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1704    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1705
1706    FETCH_ADVANCE_INST 1                // advance to next instr, load rINST
1707    GET_INST_OPCODE ip                  // ip<- opcode from rINST
1708    GOTO_OPCODE ip                      // execute it
1709
1710    NAME_END nterp_op_nop
1711    // Advance to the end of this handler. Causes error if we are past that point.
1712    .org nterp_op_nop + NTERP_HANDLER_SIZE  // op_nop handler is too big!
1713
1714/* ------------------------------ */
1715    .balign NTERP_HANDLER_SIZE
1716.L_op_move: /* 0x01 */
1717    NAME_START nterp_op_move
1718    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1719    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1720
1721    /* for move, move-object, long-to-int */
1722    /* op vA, vB */
1723    lsr     w1, wINST, #12              // x1<- B from 15:12
1724    ubfx    w0, wINST, #8, #4           // x0<- A from 11:8
1725    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1726    GET_VREG w2, w1                     // x2<- fp[B]
1727    GET_INST_OPCODE ip                  // ip<- opcode from wINST
1728    .if 0
1729    SET_VREG_OBJECT w2, w0              // fp[A]<- x2
1730    .else
1731    SET_VREG w2, w0                     // fp[A]<- x2
1732    .endif
1733    GOTO_OPCODE ip                      // execute next instruction
1734
1735    NAME_END nterp_op_move
1736    // Advance to the end of this handler. Causes error if we are past that point.
1737    .org nterp_op_move + NTERP_HANDLER_SIZE  // op_move handler is too big!
1738
1739/* ------------------------------ */
1740    .balign NTERP_HANDLER_SIZE
1741.L_op_move_from16: /* 0x02 */
1742    NAME_START nterp_op_move_from16
1743    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1744    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1745
1746    /* for: move/from16, move-object/from16 */
1747    /* op vAA, vBBBB */
1748    FETCH w1, 1                         // r1<- BBBB
1749    lsr     w0, wINST, #8               // r0<- AA
1750    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
1751    GET_VREG w2, w1                     // r2<- fp[BBBB]
1752    GET_INST_OPCODE ip                  // extract opcode from wINST
1753    .if 0
1754    SET_VREG_OBJECT w2, w0              // fp[AA]<- r2
1755    .else
1756    SET_VREG w2, w0                     // fp[AA]<- r2
1757    .endif
1758    GOTO_OPCODE ip                      // jump to next instruction
1759
1760    NAME_END nterp_op_move_from16
1761    // Advance to the end of this handler. Causes error if we are past that point.
1762    .org nterp_op_move_from16 + NTERP_HANDLER_SIZE  // op_move_from16 handler is too big!
1763
1764/* ------------------------------ */
1765    .balign NTERP_HANDLER_SIZE
1766.L_op_move_16: /* 0x03 */
1767    NAME_START nterp_op_move_16
1768    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1769    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1770
1771    /* for: move/16, move-object/16 */
1772    /* op vAAAA, vBBBB */
1773    FETCH w1, 2                         // w1<- BBBB
1774    FETCH w0, 1                         // w0<- AAAA
1775    FETCH_ADVANCE_INST 3                // advance xPC, load xINST
1776    GET_VREG w2, w1                     // w2<- fp[BBBB]
1777    GET_INST_OPCODE ip                  // extract opcode from xINST
1778    .if 0
1779    SET_VREG_OBJECT w2, w0              // fp[AAAA]<- w2
1780    .else
1781    SET_VREG w2, w0                     // fp[AAAA]<- w2
1782    .endif
1783    GOTO_OPCODE ip                      // jump to next instruction
1784
1785    NAME_END nterp_op_move_16
1786    // Advance to the end of this handler. Causes error if we are past that point.
1787    .org nterp_op_move_16 + NTERP_HANDLER_SIZE  // op_move_16 handler is too big!
1788
1789/* ------------------------------ */
1790    .balign NTERP_HANDLER_SIZE
1791.L_op_move_wide: /* 0x04 */
1792    NAME_START nterp_op_move_wide
1793    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1794    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1795
1796    /* move-wide vA, vB */
1797    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
1798    lsr     w3, wINST, #12              // w3<- B
1799    ubfx    w2, wINST, #8, #4           // w2<- A
1800    GET_VREG_WIDE  x3, w3
1801    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1802    GET_INST_OPCODE ip                  // extract opcode from wINST
1803    SET_VREG_WIDE  x3, w2
1804    GOTO_OPCODE ip                      // jump to next instruction
1805
1806    NAME_END nterp_op_move_wide
1807    // Advance to the end of this handler. Causes error if we are past that point.
1808    .org nterp_op_move_wide + NTERP_HANDLER_SIZE  // op_move_wide handler is too big!
1809
1810/* ------------------------------ */
1811    .balign NTERP_HANDLER_SIZE
1812.L_op_move_wide_from16: /* 0x05 */
1813    NAME_START nterp_op_move_wide_from16
1814    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1815    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1816
1817    /* move-wide/from16 vAA, vBBBB */
1818    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
1819    FETCH w3, 1                         // w3<- BBBB
1820    lsr     w2, wINST, #8               // w2<- AA
1821    GET_VREG_WIDE x3, w3
1822    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
1823    GET_INST_OPCODE ip                  // extract opcode from wINST
1824    SET_VREG_WIDE x3, w2
1825    GOTO_OPCODE ip                      // jump to next instruction
1826
1827    NAME_END nterp_op_move_wide_from16
1828    // Advance to the end of this handler. Causes error if we are past that point.
1829    .org nterp_op_move_wide_from16 + NTERP_HANDLER_SIZE  // op_move_wide_from16 handler is too big!
1830
1831/* ------------------------------ */
1832    .balign NTERP_HANDLER_SIZE
1833.L_op_move_wide_16: /* 0x06 */
1834    NAME_START nterp_op_move_wide_16
1835    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1836    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1837
1838    /* move-wide/16 vAAAA, vBBBB */
1839    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
1840    FETCH w3, 2                         // w3<- BBBB
1841    FETCH w2, 1                         // w2<- AAAA
1842    GET_VREG_WIDE x3, w3
1843    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
1844    SET_VREG_WIDE x3, w2
1845    GET_INST_OPCODE ip                  // extract opcode from rINST
1846    GOTO_OPCODE ip                      // jump to next instruction
1847
1848    NAME_END nterp_op_move_wide_16
1849    // Advance to the end of this handler. Causes error if we are past that point.
1850    .org nterp_op_move_wide_16 + NTERP_HANDLER_SIZE  // op_move_wide_16 handler is too big!
1851
1852/* ------------------------------ */
1853    .balign NTERP_HANDLER_SIZE
1854.L_op_move_object: /* 0x07 */
1855    NAME_START nterp_op_move_object
1856    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1857    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1858
1859    /* for move, move-object, long-to-int */
1860    /* op vA, vB */
1861    lsr     w1, wINST, #12              // x1<- B from 15:12
1862    ubfx    w0, wINST, #8, #4           // x0<- A from 11:8
1863    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1864    GET_VREG w2, w1                     // x2<- fp[B]
1865    GET_INST_OPCODE ip                  // ip<- opcode from wINST
1866    .if 1
1867    SET_VREG_OBJECT w2, w0              // fp[A]<- x2
1868    .else
1869    SET_VREG w2, w0                     // fp[A]<- x2
1870    .endif
1871    GOTO_OPCODE ip                      // execute next instruction
1872
1873    NAME_END nterp_op_move_object
1874    // Advance to the end of this handler. Causes error if we are past that point.
1875    .org nterp_op_move_object + NTERP_HANDLER_SIZE  // op_move_object handler is too big!
1876
1877/* ------------------------------ */
1878    .balign NTERP_HANDLER_SIZE
1879.L_op_move_object_from16: /* 0x08 */
1880    NAME_START nterp_op_move_object_from16
1881    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1882    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1883
1884    /* for: move/from16, move-object/from16 */
1885    /* op vAA, vBBBB */
1886    FETCH w1, 1                         // r1<- BBBB
1887    lsr     w0, wINST, #8               // r0<- AA
1888    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
1889    GET_VREG w2, w1                     // r2<- fp[BBBB]
1890    GET_INST_OPCODE ip                  // extract opcode from wINST
1891    .if 1
1892    SET_VREG_OBJECT w2, w0              // fp[AA]<- r2
1893    .else
1894    SET_VREG w2, w0                     // fp[AA]<- r2
1895    .endif
1896    GOTO_OPCODE ip                      // jump to next instruction
1897
1898    NAME_END nterp_op_move_object_from16
1899    // Advance to the end of this handler. Causes error if we are past that point.
1900    .org nterp_op_move_object_from16 + NTERP_HANDLER_SIZE  // op_move_object_from16 handler is too big!
1901
1902/* ------------------------------ */
1903    .balign NTERP_HANDLER_SIZE
1904.L_op_move_object_16: /* 0x09 */
1905    NAME_START nterp_op_move_object_16
1906    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1907    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1908
1909    /* for: move/16, move-object/16 */
1910    /* op vAAAA, vBBBB */
1911    FETCH w1, 2                         // w1<- BBBB
1912    FETCH w0, 1                         // w0<- AAAA
1913    FETCH_ADVANCE_INST 3                // advance xPC, load xINST
1914    GET_VREG w2, w1                     // w2<- fp[BBBB]
1915    GET_INST_OPCODE ip                  // extract opcode from xINST
1916    .if 1
1917    SET_VREG_OBJECT w2, w0              // fp[AAAA]<- w2
1918    .else
1919    SET_VREG w2, w0                     // fp[AAAA]<- w2
1920    .endif
1921    GOTO_OPCODE ip                      // jump to next instruction
1922
1923    NAME_END nterp_op_move_object_16
1924    // Advance to the end of this handler. Causes error if we are past that point.
1925    .org nterp_op_move_object_16 + NTERP_HANDLER_SIZE  // op_move_object_16 handler is too big!
1926
1927/* ------------------------------ */
1928    .balign NTERP_HANDLER_SIZE
1929.L_op_move_result: /* 0x0a */
1930    NAME_START nterp_op_move_result
1931    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1932    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1933
1934    /* for: move-result, move-result-object */
1935    /* op vAA */
1936    lsr     w2, wINST, #8               // r2<- AA
1937    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1938    GET_INST_OPCODE ip                  // extract opcode from wINST
1939    .if 0
1940    SET_VREG_OBJECT w0, w2              // fp[AA]<- r0
1941    .else
1942    SET_VREG w0, w2                     // fp[AA]<- r0
1943    .endif
1944    GOTO_OPCODE ip                      // jump to next instruction
1945
1946    NAME_END nterp_op_move_result
1947    // Advance to the end of this handler. Causes error if we are past that point.
1948    .org nterp_op_move_result + NTERP_HANDLER_SIZE  // op_move_result handler is too big!
1949
1950/* ------------------------------ */
1951    .balign NTERP_HANDLER_SIZE
1952.L_op_move_result_wide: /* 0x0b */
1953    NAME_START nterp_op_move_result_wide
1954    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1955    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1956
1957    /* for: move-result-wide */
1958    /* op vAA */
1959    lsr     w2, wINST, #8               // r2<- AA
1960    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1961    GET_INST_OPCODE ip                  // extract opcode from wINST
1962    SET_VREG_WIDE x0, w2                // fp[AA]<- r0
1963    GOTO_OPCODE ip                      // jump to next instruction
1964
1965    NAME_END nterp_op_move_result_wide
1966    // Advance to the end of this handler. Causes error if we are past that point.
1967    .org nterp_op_move_result_wide + NTERP_HANDLER_SIZE  // op_move_result_wide handler is too big!
1968
1969/* ------------------------------ */
1970    .balign NTERP_HANDLER_SIZE
1971.L_op_move_result_object: /* 0x0c */
1972    NAME_START nterp_op_move_result_object
1973    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1974    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1975
1976    /* for: move-result, move-result-object */
1977    /* op vAA */
1978    lsr     w2, wINST, #8               // r2<- AA
1979    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
1980    GET_INST_OPCODE ip                  // extract opcode from wINST
1981    .if 1
1982    SET_VREG_OBJECT w0, w2              // fp[AA]<- r0
1983    .else
1984    SET_VREG w0, w2                     // fp[AA]<- r0
1985    .endif
1986    GOTO_OPCODE ip                      // jump to next instruction
1987
1988    NAME_END nterp_op_move_result_object
1989    // Advance to the end of this handler. Causes error if we are past that point.
1990    .org nterp_op_move_result_object + NTERP_HANDLER_SIZE  // op_move_result_object handler is too big!
1991
1992/* ------------------------------ */
1993    .balign NTERP_HANDLER_SIZE
1994.L_op_move_exception: /* 0x0d */
1995    NAME_START nterp_op_move_exception
1996    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
1997    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
1998
1999    /* move-exception vAA */
2000    lsr     w2, wINST, #8               // w2<- AA
2001    ldr     x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
2002    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
2003    SET_VREG_OBJECT w3, w2              // fp[AA]<- exception obj
2004    GET_INST_OPCODE ip                  // extract opcode from rINST
2005    str     xzr, [xSELF, #THREAD_EXCEPTION_OFFSET]  // clear exception
2006    GOTO_OPCODE ip                      // jump to next instruction
2007
2008    NAME_END nterp_op_move_exception
2009    // Advance to the end of this handler. Causes error if we are past that point.
2010    .org nterp_op_move_exception + NTERP_HANDLER_SIZE  // op_move_exception handler is too big!
2011
2012/* ------------------------------ */
2013    .balign NTERP_HANDLER_SIZE
2014.L_op_return_void: /* 0x0e */
2015    NAME_START nterp_op_return_void
2016    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2017    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2018
2019    .if 1
2020      // Thread fence for constructor
2021      dmb ishst
2022    .else
2023      lsr     w2, wINST, #8               // w2<- AA
2024      .if 0
2025        GET_VREG_WIDE x0, w2                // x0<- vAA
2026        // In case we're going back to compiled code, put the
2027        // result also in d0
2028        fmov d0, x0
2029      .else
2030        GET_VREG w0, w2                     // r0<- vAA
2031        .if !0
2032        // In case we're going back to compiled code, put the
2033        // result also in s0.
2034        fmov s0, w0
2035        .endif
2036      .endif
2037    .endif
2038    .cfi_remember_state
2039    ldr ip, [xREFS, #-8]
2040    mov sp, ip
2041    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
2042    RESTORE_ALL_CALLEE_SAVES
2043    ret
2044    .cfi_restore_state
2045    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2046
2047    NAME_END nterp_op_return_void
2048    // Advance to the end of this handler. Causes error if we are past that point.
2049    .org nterp_op_return_void + NTERP_HANDLER_SIZE  // op_return_void handler is too big!
2050
2051/* ------------------------------ */
2052    .balign NTERP_HANDLER_SIZE
2053.L_op_return: /* 0x0f */
2054    NAME_START nterp_op_return
2055    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2056    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2057
2058    .if 0
2059      // Thread fence for constructor
2060      dmb ishst
2061    .else
2062      lsr     w2, wINST, #8               // w2<- AA
2063      .if 0
2064        GET_VREG_WIDE x0, w2                // x0<- vAA
2065        // In case we're going back to compiled code, put the
2066        // result also in d0
2067        fmov d0, x0
2068      .else
2069        GET_VREG w0, w2                     // r0<- vAA
2070        .if !0
2071        // In case we're going back to compiled code, put the
2072        // result also in s0.
2073        fmov s0, w0
2074        .endif
2075      .endif
2076    .endif
2077    .cfi_remember_state
2078    ldr ip, [xREFS, #-8]
2079    mov sp, ip
2080    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
2081    RESTORE_ALL_CALLEE_SAVES
2082    ret
2083    .cfi_restore_state
2084    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2085
2086    NAME_END nterp_op_return
2087    // Advance to the end of this handler. Causes error if we are past that point.
2088    .org nterp_op_return + NTERP_HANDLER_SIZE  // op_return handler is too big!
2089
2090/* ------------------------------ */
2091    .balign NTERP_HANDLER_SIZE
2092.L_op_return_wide: /* 0x10 */
2093    NAME_START nterp_op_return_wide
2094    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2095    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2096
2097    .if 0
2098      // Thread fence for constructor
2099      dmb ishst
2100    .else
2101      lsr     w2, wINST, #8               // w2<- AA
2102      .if 1
2103        GET_VREG_WIDE x0, w2                // x0<- vAA
2104        // In case we're going back to compiled code, put the
2105        // result also in d0
2106        fmov d0, x0
2107      .else
2108        GET_VREG w0, w2                     // r0<- vAA
2109        .if !0
2110        // In case we're going back to compiled code, put the
2111        // result also in s0.
2112        fmov s0, w0
2113        .endif
2114      .endif
2115    .endif
2116    .cfi_remember_state
2117    ldr ip, [xREFS, #-8]
2118    mov sp, ip
2119    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
2120    RESTORE_ALL_CALLEE_SAVES
2121    ret
2122    .cfi_restore_state
2123    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2124
2125    NAME_END nterp_op_return_wide
2126    // Advance to the end of this handler. Causes error if we are past that point.
2127    .org nterp_op_return_wide + NTERP_HANDLER_SIZE  // op_return_wide handler is too big!
2128
2129/* ------------------------------ */
2130    .balign NTERP_HANDLER_SIZE
2131.L_op_return_object: /* 0x11 */
2132    NAME_START nterp_op_return_object
2133    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2134    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2135
2136    .if 0
2137      // Thread fence for constructor
2138      dmb ishst
2139    .else
2140      lsr     w2, wINST, #8               // w2<- AA
2141      .if 0
2142        GET_VREG_WIDE x0, w2                // x0<- vAA
2143        // In case we're going back to compiled code, put the
2144        // result also in d0
2145        fmov d0, x0
2146      .else
2147        GET_VREG w0, w2                     // r0<- vAA
2148        .if !1
2149        // In case we're going back to compiled code, put the
2150        // result also in s0.
2151        fmov s0, w0
2152        .endif
2153      .endif
2154    .endif
2155    .cfi_remember_state
2156    ldr ip, [xREFS, #-8]
2157    mov sp, ip
2158    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
2159    RESTORE_ALL_CALLEE_SAVES
2160    ret
2161    .cfi_restore_state
2162    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2163
2164    NAME_END nterp_op_return_object
2165    // Advance to the end of this handler. Causes error if we are past that point.
2166    .org nterp_op_return_object + NTERP_HANDLER_SIZE  // op_return_object handler is too big!
2167
2168/* ------------------------------ */
2169    .balign NTERP_HANDLER_SIZE
2170.L_op_const_4: /* 0x12 */
2171    NAME_START nterp_op_const_4
2172    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2173    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2174
2175    /* const/4 vA, #+B */
2176    sbfx    w1, wINST, #12, #4          // w1<- sssssssB
2177    ubfx    w0, wINST, #8, #4           // w0<- A
2178    FETCH_ADVANCE_INST 1                // advance xPC, load wINST
2179    GET_INST_OPCODE ip                  // ip<- opcode from xINST
2180    SET_VREG w1, w0                     // fp[A]<- w1
2181    GOTO_OPCODE ip                      // execute next instruction
2182
2183    NAME_END nterp_op_const_4
2184    // Advance to the end of this handler. Causes error if we are past that point.
2185    .org nterp_op_const_4 + NTERP_HANDLER_SIZE  // op_const_4 handler is too big!
2186
2187/* ------------------------------ */
2188    .balign NTERP_HANDLER_SIZE
2189.L_op_const_16: /* 0x13 */
2190    NAME_START nterp_op_const_16
2191    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2192    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2193
2194    /* const/16 vAA, #+BBBB */
2195    FETCH_S w0, 1                       // w0<- ssssBBBB (sign-extended)
2196    lsr     w3, wINST, #8               // w3<- AA
2197    FETCH_ADVANCE_INST 2                // advance xPC, load wINST
2198    SET_VREG w0, w3                     // vAA<- w0
2199    GET_INST_OPCODE ip                  // extract opcode from wINST
2200    GOTO_OPCODE ip                      // jump to next instruction
2201
2202    NAME_END nterp_op_const_16
2203    // Advance to the end of this handler. Causes error if we are past that point.
2204    .org nterp_op_const_16 + NTERP_HANDLER_SIZE  // op_const_16 handler is too big!
2205
2206/* ------------------------------ */
2207    .balign NTERP_HANDLER_SIZE
2208.L_op_const: /* 0x14 */
2209    NAME_START nterp_op_const
2210    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2211    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2212
2213    /* const vAA, #+BBBBbbbb */
2214    lsr     w3, wINST, #8               // w3<- AA
2215    FETCH w0, 1                         // w0<- bbbb (low)
2216    FETCH w1, 2                         // w1<- BBBB (high)
2217    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
2218    orr     w0, w0, w1, lsl #16         // w0<- BBBBbbbb
2219    GET_INST_OPCODE ip                  // extract opcode from wINST
2220    SET_VREG w0, w3                     // vAA<- w0
2221    GOTO_OPCODE ip                      // jump to next instruction
2222
2223    NAME_END nterp_op_const
2224    // Advance to the end of this handler. Causes error if we are past that point.
2225    .org nterp_op_const + NTERP_HANDLER_SIZE  // op_const handler is too big!
2226
2227/* ------------------------------ */
2228    .balign NTERP_HANDLER_SIZE
2229.L_op_const_high16: /* 0x15 */
2230    NAME_START nterp_op_const_high16
2231    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2232    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2233
2234    /* const/high16 vAA, #+BBBB0000 */
2235    FETCH   w0, 1                       // r0<- 0000BBBB (zero-extended)
2236    lsr     w3, wINST, #8               // r3<- AA
2237    lsl     w0, w0, #16                 // r0<- BBBB0000
2238    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
2239    SET_VREG w0, w3                     // vAA<- r0
2240    GET_INST_OPCODE ip                  // extract opcode from rINST
2241    GOTO_OPCODE ip                      // jump to next instruction
2242
2243    NAME_END nterp_op_const_high16
2244    // Advance to the end of this handler. Causes error if we are past that point.
2245    .org nterp_op_const_high16 + NTERP_HANDLER_SIZE  // op_const_high16 handler is too big!
2246
2247/* ------------------------------ */
2248    .balign NTERP_HANDLER_SIZE
2249.L_op_const_wide_16: /* 0x16 */
2250    NAME_START nterp_op_const_wide_16
2251    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2252    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2253
2254    /* const-wide/16 vAA, #+BBBB */
2255    FETCH_S x0, 1                       // x0<- ssssssssssssBBBB (sign-extended)
2256    lsr     w3, wINST, #8               // w3<- AA
2257    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
2258    GET_INST_OPCODE ip                  // extract opcode from rINST
2259    SET_VREG_WIDE x0, w3
2260    GOTO_OPCODE ip                      // jump to next instruction
2261
2262    NAME_END nterp_op_const_wide_16
2263    // Advance to the end of this handler. Causes error if we are past that point.
2264    .org nterp_op_const_wide_16 + NTERP_HANDLER_SIZE  // op_const_wide_16 handler is too big!
2265
2266/* ------------------------------ */
2267    .balign NTERP_HANDLER_SIZE
2268.L_op_const_wide_32: /* 0x17 */
2269    NAME_START nterp_op_const_wide_32
2270    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2271    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2272
2273    /* const-wide/32 vAA, #+BBBBbbbb */
2274    FETCH   w0, 1                       // x0<- 000000000000bbbb (low)
2275    lsr     w3, wINST, #8               // w3<- AA
2276    FETCH_S x2, 2                       // x2<- ssssssssssssBBBB (high)
2277    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
2278    GET_INST_OPCODE ip                  // extract opcode from wINST
2279    orr     x0, x0, x2, lsl #16         // x0<- ssssssssBBBBbbbb
2280    SET_VREG_WIDE x0, w3
2281    GOTO_OPCODE ip                      // jump to next instruction
2282
2283    NAME_END nterp_op_const_wide_32
2284    // Advance to the end of this handler. Causes error if we are past that point.
2285    .org nterp_op_const_wide_32 + NTERP_HANDLER_SIZE  // op_const_wide_32 handler is too big!
2286
2287/* ------------------------------ */
2288    .balign NTERP_HANDLER_SIZE
2289.L_op_const_wide: /* 0x18 */
2290    NAME_START nterp_op_const_wide
2291    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2292    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2293
2294    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
2295    FETCH w0, 1                         // w0<- bbbb (low)
2296    FETCH w1, 2                         // w1<- BBBB (low middle)
2297    FETCH w2, 3                         // w2<- hhhh (high middle)
2298    FETCH w3, 4                         // w3<- HHHH (high)
2299    lsr     w4, wINST, #8               // r4<- AA
2300    FETCH_ADVANCE_INST 5                // advance rPC, load wINST
2301    GET_INST_OPCODE ip                  // extract opcode from wINST
2302    orr     w0, w0, w1, lsl #16         // w0<-         BBBBbbbb
2303    orr     x0, x0, x2, lsl #32         // w0<-     hhhhBBBBbbbb
2304    orr     x0, x0, x3, lsl #48         // w0<- HHHHhhhhBBBBbbbb
2305    SET_VREG_WIDE x0, w4
2306    GOTO_OPCODE ip                      // jump to next instruction
2307
2308    NAME_END nterp_op_const_wide
2309    // Advance to the end of this handler. Causes error if we are past that point.
2310    .org nterp_op_const_wide + NTERP_HANDLER_SIZE  // op_const_wide handler is too big!
2311
2312/* ------------------------------ */
2313    .balign NTERP_HANDLER_SIZE
2314.L_op_const_wide_high16: /* 0x19 */
2315    NAME_START nterp_op_const_wide_high16
2316    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2317    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2318
2319    /* const-wide/high16 vAA, #+BBBB000000000000 */
2320    FETCH w0, 1                         // w0<- 0000BBBB (zero-extended)
2321    lsr     w1, wINST, #8               // w1<- AA
2322    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
2323    lsl     x0, x0, #48
2324    SET_VREG_WIDE x0, w1
2325    GET_INST_OPCODE ip                  // extract opcode from wINST
2326    GOTO_OPCODE ip                      // jump to next instruction
2327
2328    NAME_END nterp_op_const_wide_high16
2329    // Advance to the end of this handler. Causes error if we are past that point.
2330    .org nterp_op_const_wide_high16 + NTERP_HANDLER_SIZE  // op_const_wide_high16 handler is too big!
2331
2332/* ------------------------------ */
2333    .balign NTERP_HANDLER_SIZE
2334.L_op_const_string: /* 0x1a */
2335    NAME_START nterp_op_const_string
2336    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2337    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2338
2339   /* const/string vAA, String@BBBB */
2340   // Fast-path which gets the object from thread-local cache.
2341   // Fetch some information from the thread cache.
2342   // Uses ip and ip2 as temporaries.
2343   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2344   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2345   add      ip, ip, ip2, lsl #4            // entry address within the cache
2346   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
2347   cmp      ip, xPC
2348   b.ne     2f
2349
2350   TEST_IF_MARKING 3f
23511:
2352   lsr     w1, wINST, #8               // w1<- AA
2353   .if 0
2354   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
2355   .else
2356   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
2357   .endif
2358   GET_INST_OPCODE ip                  // extract opcode from wINST
2359   SET_VREG_OBJECT w0, w1              // vAA <- value
2360   GOTO_OPCODE ip                      // jump to next instruction
23612:
2362   EXPORT_PC
2363   mov x0, xSELF
2364   ldr x1, [sp]
2365   mov x2, xPC
2366   bl nterp_load_object
2367   b 1b
23683:
2369   bl art_quick_read_barrier_mark_reg00
2370   b 1b
2371
2372    NAME_END nterp_op_const_string
2373    // Advance to the end of this handler. Causes error if we are past that point.
2374    .org nterp_op_const_string + NTERP_HANDLER_SIZE  // op_const_string handler is too big!
2375
2376/* ------------------------------ */
2377    .balign NTERP_HANDLER_SIZE
2378.L_op_const_string_jumbo: /* 0x1b */
2379    NAME_START nterp_op_const_string_jumbo
2380    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2381    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2382
2383   /* const/string vAA, String@BBBBBBBB */
2384   // Fast-path which gets the object from thread-local cache.
2385   // Fetch some information from the thread cache.
2386   // Uses ip and ip2 as temporaries.
2387   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2388   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2389   add      ip, ip, ip2, lsl #4            // entry address within the cache
2390   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
2391   cmp      ip, xPC
2392   b.ne     2f
2393
2394   TEST_IF_MARKING 3f
23951:
2396   lsr     w1, wINST, #8               // w1<- AA
2397   .if 1
2398   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
2399   .else
2400   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
2401   .endif
2402   GET_INST_OPCODE ip                  // extract opcode from wINST
2403   SET_VREG_OBJECT w0, w1              // vAA <- value
2404   GOTO_OPCODE ip                      // jump to next instruction
24052:
2406   EXPORT_PC
2407   mov x0, xSELF
2408   ldr x1, [sp]
2409   mov x2, xPC
2410   bl nterp_load_object
2411   b 1b
24123:
2413   bl art_quick_read_barrier_mark_reg00
2414   b 1b
2415
2416    NAME_END nterp_op_const_string_jumbo
2417    // Advance to the end of this handler. Causes error if we are past that point.
2418    .org nterp_op_const_string_jumbo + NTERP_HANDLER_SIZE  // op_const_string_jumbo handler is too big!
2419
2420/* ------------------------------ */
2421    .balign NTERP_HANDLER_SIZE
2422.L_op_const_class: /* 0x1c */
2423    NAME_START nterp_op_const_class
2424    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2425    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2426
2427   // Fast-path which gets the object from thread-local cache.
2428   // Fetch some information from the thread cache.
2429   // Uses ip and ip2 as temporaries.
2430   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2431   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2432   add      ip, ip, ip2, lsl #4            // entry address within the cache
2433   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
2434   cmp      ip, xPC
2435   b.ne     2f
2436
2437   TEST_IF_MARKING 3f
24381:
2439   lsr     w1, wINST, #8               // w1<- AA
2440   .if 0
2441   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
2442   .else
2443   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
2444   .endif
2445   GET_INST_OPCODE ip                  // extract opcode from wINST
2446   SET_VREG_OBJECT w0, w1              // vAA <- value
2447   GOTO_OPCODE ip                      // jump to next instruction
24482:
2449   EXPORT_PC
2450   mov x0, xSELF
2451   ldr x1, [sp]
2452   mov x2, xPC
2453   bl nterp_get_class
2454   b 1b
24553:
2456   bl art_quick_read_barrier_mark_reg00
2457   b 1b
2458
2459    NAME_END nterp_op_const_class
2460    // Advance to the end of this handler. Causes error if we are past that point.
2461    .org nterp_op_const_class + NTERP_HANDLER_SIZE  // op_const_class handler is too big!
2462
2463/* ------------------------------ */
2464    .balign NTERP_HANDLER_SIZE
2465.L_op_monitor_enter: /* 0x1d */
2466    NAME_START nterp_op_monitor_enter
2467    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2468    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2469
2470/*
2471 * Synchronize on an object.
2472 */
2473    /* monitor-enter vAA */
2474    EXPORT_PC
2475    lsr      w2, wINST, #8               // w2<- AA
2476    GET_VREG w0, w2
2477    bl art_quick_lock_object
2478    FETCH_ADVANCE_INST 1
2479    GET_INST_OPCODE ip                   // extract opcode from rINST
2480    GOTO_OPCODE ip                       // jump to next instruction
2481
2482    NAME_END nterp_op_monitor_enter
2483    // Advance to the end of this handler. Causes error if we are past that point.
2484    .org nterp_op_monitor_enter + NTERP_HANDLER_SIZE  // op_monitor_enter handler is too big!
2485
2486/* ------------------------------ */
2487    .balign NTERP_HANDLER_SIZE
2488.L_op_monitor_exit: /* 0x1e */
2489    NAME_START nterp_op_monitor_exit
2490    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2491    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2492
2493/*
2494 * Unlock an object.
2495 *
2496 * Exceptions that occur when unlocking a monitor need to appear as
2497 * if they happened at the following instruction.  See the Dalvik
2498 * instruction spec.
2499 */
2500    /* monitor-exit vAA */
2501    EXPORT_PC
2502    lsr      w2, wINST, #8               // w2<- AA
2503    GET_VREG w0, w2
2504    bl art_quick_unlock_object
2505    FETCH_ADVANCE_INST 1
2506    GET_INST_OPCODE ip                   // extract opcode from rINST
2507    GOTO_OPCODE ip                       // jump to next instruction
2508
2509    NAME_END nterp_op_monitor_exit
2510    // Advance to the end of this handler. Causes error if we are past that point.
2511    .org nterp_op_monitor_exit + NTERP_HANDLER_SIZE  // op_monitor_exit handler is too big!
2512
2513/* ------------------------------ */
2514    .balign NTERP_HANDLER_SIZE
2515.L_op_check_cast: /* 0x1f */
2516    NAME_START nterp_op_check_cast
2517    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2518    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2519
2520   // Fast-path which gets the class from thread-local cache.
2521   // Fetch some information from the thread cache.
2522   // Uses ip and ip2 as temporaries.
2523   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2524   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2525   add      ip, ip, ip2, lsl #4            // entry address within the cache
2526   ldp      ip, x1, [ip]          // entry key (pc) and value (offset)
2527   cmp      ip, xPC
2528   b.ne     2f
2529
25301:
2531   lsr     w2, wINST, #8               // w2<- A
2532   GET_VREG w0, w2                     // w0<- vA (object)
2533   cbz     w0, .Lop_check_cast_resume
2534   ldr     w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET]
2535   UNPOISON_HEAP_REF w2
2536   // Fast path: do a comparison without read barrier.
2537   cmp     w1, w2
2538   bne     nterp_op_check_cast_slow_path
2539.Lop_check_cast_resume:
2540   FETCH_ADVANCE_INST 2
2541   GET_INST_OPCODE ip
2542   GOTO_OPCODE ip
25432:
2544   EXPORT_PC
2545   mov     x0, xSELF
2546   ldr     x1, [sp]
2547   mov     x2, xPC
2548   bl      nterp_get_class
2549   mov     x1, x0
2550   b       1b
2551
2552    NAME_END nterp_op_check_cast
2553    // Advance to the end of this handler. Causes error if we are past that point.
2554    .org nterp_op_check_cast + NTERP_HANDLER_SIZE  // op_check_cast handler is too big!
2555
2556/* ------------------------------ */
2557    .balign NTERP_HANDLER_SIZE
2558.L_op_instance_of: /* 0x20 */
2559    NAME_START nterp_op_instance_of
2560    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2561    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2562
2563   /* instance-of vA, vB, class@CCCC */
2564   // Fast-path which gets the class from thread-local cache.
2565   // Fetch some information from the thread cache.
2566   // Uses ip and ip2 as temporaries.
2567   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2568   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2569   add      ip, ip, ip2, lsl #4            // entry address within the cache
2570   ldp      ip, x1, [ip]          // entry key (pc) and value (offset)
2571   cmp      ip, xPC
2572   b.ne     2f
2573
25741:
2575   lsr     w2, wINST, #12              // w2<- B
2576   GET_VREG w0, w2                     // w0<- vB (object)
2577   cbz     w0, .Lop_instance_of_resume
2578   ldr     w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET]
2579   UNPOISON_HEAP_REF w2
2580   // Fast path: do a comparison without read barrier.
2581   cmp     w1, w2
2582   bne     nterp_op_instance_of_slow_path
2583.Lop_instance_of_set_one:
2584   mov     w0, #1
2585.Lop_instance_of_resume:
2586   ubfx    w1, wINST, #8, #4           // w1<- A
2587   SET_VREG w0, w1
2588   FETCH_ADVANCE_INST 2
2589   GET_INST_OPCODE ip
2590   GOTO_OPCODE ip
25912:
2592   EXPORT_PC
2593   mov     x0, xSELF
2594   ldr     x1, [sp]
2595   mov     x2, xPC
2596   bl      nterp_get_class
2597   mov     x1, x0
2598   b       1b
2599
2600    NAME_END nterp_op_instance_of
2601    // Advance to the end of this handler. Causes error if we are past that point.
2602    .org nterp_op_instance_of + NTERP_HANDLER_SIZE  // op_instance_of handler is too big!
2603
2604/* ------------------------------ */
2605    .balign NTERP_HANDLER_SIZE
2606.L_op_array_length: /* 0x21 */
2607    NAME_START nterp_op_array_length
2608    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2609    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2610
2611    /*
2612     * Return the length of an array.
2613     */
2614    lsr     w1, wINST, #12              // w1<- B
2615    ubfx    w2, wINST, #8, #4           // w2<- A
2616    GET_VREG w0, w1                     // w0<- vB (object ref)
2617    cbz     w0, common_errNullObject    // bail if null
2618    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
2619    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- array length
2620    GET_INST_OPCODE ip                  // extract opcode from rINST
2621    SET_VREG w3, w2                     // vB<- length
2622    GOTO_OPCODE ip                      // jump to next instruction
2623
2624    NAME_END nterp_op_array_length
2625    // Advance to the end of this handler. Causes error if we are past that point.
2626    .org nterp_op_array_length + NTERP_HANDLER_SIZE  // op_array_length handler is too big!
2627
2628/* ------------------------------ */
2629    .balign NTERP_HANDLER_SIZE
2630.L_op_new_instance: /* 0x22 */
2631    NAME_START nterp_op_new_instance
2632    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2633    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2634
2635   EXPORT_PC
2636   // Fast-path which gets the class from thread-local cache.
2637   // Fetch some information from the thread cache.
2638   // Uses ip and ip2 as temporaries.
2639   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2640   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2641   add      ip, ip, ip2, lsl #4            // entry address within the cache
2642   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
2643   cmp      ip, xPC
2644   b.ne     2f
2645
2646   TEST_IF_MARKING 3f
26474:
2648   ldr     lr, [xSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET]
2649   blr     lr
2650   dmb     ishst                       // need fence for making object's class visible
26511:
2652   lsr     w1, wINST, #8               // w1 <- A
2653   SET_VREG_OBJECT w0, w1              // fp[A] <- value
2654   FETCH_ADVANCE_INST 2
2655   GET_INST_OPCODE ip
2656   GOTO_OPCODE ip
26572:
2658   mov     x0, xSELF
2659   ldr     x1, [sp]
2660   mov     x2, xPC
2661   bl      nterp_allocate_object
2662   b       1b
26633:
2664   bl      art_quick_read_barrier_mark_reg00
2665   b       4b
2666    NAME_END nterp_op_new_instance
2667    // Advance to the end of this handler. Causes error if we are past that point.
2668    .org nterp_op_new_instance + NTERP_HANDLER_SIZE  // op_new_instance handler is too big!
2669
2670/* ------------------------------ */
2671    .balign NTERP_HANDLER_SIZE
2672.L_op_new_array: /* 0x23 */
2673    NAME_START nterp_op_new_array
2674    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2675    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2676
2677   /* new-array vA, vB, class@CCCC */
2678   EXPORT_PC
2679   // Fast-path which gets the class from thread-local cache.
2680   // Fetch some information from the thread cache.
2681   // Uses ip and ip2 as temporaries.
2682   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
2683   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
2684   add      ip, ip, ip2, lsl #4            // entry address within the cache
2685   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
2686   cmp      ip, xPC
2687   b.ne     2f
2688
2689   TEST_IF_MARKING 3f
26901:
2691   lsr     w1, wINST, #12              // w1<- B
2692   GET_VREG w1, w1                     // w1<- vB (array length)
2693   ldr lr, [xSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
2694   blr lr
2695   dmb ishst                           // need fence for making array's class visible
2696   ubfx    w1, wINST, #8, #4           // w1<- A
2697   SET_VREG_OBJECT w0, w1
2698   FETCH_ADVANCE_INST 2
2699   GET_INST_OPCODE ip
2700   GOTO_OPCODE ip
27012:
2702   mov x0, xSELF
2703   ldr x1, [sp, 0]
2704   mov x2, xPC
2705   bl nterp_get_class
2706   b 1b
27073:
2708   bl art_quick_read_barrier_mark_reg00
2709   b 1b
2710    NAME_END nterp_op_new_array
2711    // Advance to the end of this handler. Causes error if we are past that point.
2712    .org nterp_op_new_array + NTERP_HANDLER_SIZE  // op_new_array handler is too big!
2713
2714/* ------------------------------ */
2715    .balign NTERP_HANDLER_SIZE
2716.L_op_filled_new_array: /* 0x24 */
2717    NAME_START nterp_op_filled_new_array
2718    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2719    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2720
2721/*
2722 * Create a new array with elements filled from registers.
2723 *
2724 * for: filled-new-array, filled-new-array/range
2725 */
2726    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2727    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
2728    EXPORT_PC
2729    mov     x0, xSELF
2730    ldr     x1, [sp]
2731    mov     x2, xFP
2732    mov     x3, xPC
2733    bl      nterp_filled_new_array
2734    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
2735    GET_INST_OPCODE ip                  // extract opcode from rINST
2736    GOTO_OPCODE ip                      // jump to next instruction
2737
2738    NAME_END nterp_op_filled_new_array
2739    // Advance to the end of this handler. Causes error if we are past that point.
2740    .org nterp_op_filled_new_array + NTERP_HANDLER_SIZE  // op_filled_new_array handler is too big!
2741
2742/* ------------------------------ */
2743    .balign NTERP_HANDLER_SIZE
2744.L_op_filled_new_array_range: /* 0x25 */
2745    NAME_START nterp_op_filled_new_array_range
2746    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2747    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2748
2749/*
2750 * Create a new array with elements filled from registers.
2751 *
2752 * for: filled-new-array, filled-new-array/range
2753 */
2754    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2755    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
2756    EXPORT_PC
2757    mov     x0, xSELF
2758    ldr     x1, [sp]
2759    mov     x2, xFP
2760    mov     x3, xPC
2761    bl      nterp_filled_new_array_range
2762    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
2763    GET_INST_OPCODE ip                  // extract opcode from rINST
2764    GOTO_OPCODE ip                      // jump to next instruction
2765
2766    NAME_END nterp_op_filled_new_array_range
2767    // Advance to the end of this handler. Causes error if we are past that point.
2768    .org nterp_op_filled_new_array_range + NTERP_HANDLER_SIZE  // op_filled_new_array_range handler is too big!
2769
2770/* ------------------------------ */
2771    .balign NTERP_HANDLER_SIZE
2772.L_op_fill_array_data: /* 0x26 */
2773    NAME_START nterp_op_fill_array_data
2774    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2775    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2776
2777    /* fill-array-data vAA, +BBBBBBBB */
2778    EXPORT_PC
2779    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
2780    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
2781    lsr     w3, wINST, #8               // w3<- AA
2782    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
2783    GET_VREG w1, w3                     // w1<- vAA (array object)
2784    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2 (array data off.)
2785    bl      art_quick_handle_fill_data
2786    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
2787    GET_INST_OPCODE ip                  // extract opcode from rINST
2788    GOTO_OPCODE ip                      // jump to next instruction
2789
2790    NAME_END nterp_op_fill_array_data
2791    // Advance to the end of this handler. Causes error if we are past that point.
2792    .org nterp_op_fill_array_data + NTERP_HANDLER_SIZE  // op_fill_array_data handler is too big!
2793
2794/* ------------------------------ */
2795    .balign NTERP_HANDLER_SIZE
2796.L_op_throw: /* 0x27 */
2797    NAME_START nterp_op_throw
2798    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2799    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2800
2801  EXPORT_PC
2802  lsr      w2, wINST, #8               // r2<- AA
2803  GET_VREG w0, w2                      // r0<- vAA (exception object)
2804  mov x1, xSELF
2805  bl art_quick_deliver_exception
2806  brk 0
2807    NAME_END nterp_op_throw
2808    // Advance to the end of this handler. Causes error if we are past that point.
2809    .org nterp_op_throw + NTERP_HANDLER_SIZE  // op_throw handler is too big!
2810
2811/* ------------------------------ */
2812    .balign NTERP_HANDLER_SIZE
2813.L_op_goto: /* 0x28 */
2814    NAME_START nterp_op_goto
2815    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2816    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2817
2818/*
2819 * Unconditional branch, 8-bit offset.
2820 *
2821 * The branch distance is a signed code-unit offset, which we need to
2822 * double to get a byte offset.
2823 */
2824    /* goto +AA */
2825    sbfx    wINST, wINST, #8, #8           // wINST<- ssssssAA (sign-extended)
2826    BRANCH
2827
2828    NAME_END nterp_op_goto
2829    // Advance to the end of this handler. Causes error if we are past that point.
2830    .org nterp_op_goto + NTERP_HANDLER_SIZE  // op_goto handler is too big!
2831
2832/* ------------------------------ */
2833    .balign NTERP_HANDLER_SIZE
2834.L_op_goto_16: /* 0x29 */
2835    NAME_START nterp_op_goto_16
2836    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2837    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2838
2839/*
2840 * Unconditional branch, 16-bit offset.
2841 *
2842 * The branch distance is a signed code-unit offset, which we need to
2843 * double to get a byte offset.
2844 */
2845    /* goto/16 +AAAA */
2846    FETCH_S wINST, 1                    // wINST<- ssssAAAA (sign-extended)
2847    BRANCH
2848
2849    NAME_END nterp_op_goto_16
2850    // Advance to the end of this handler. Causes error if we are past that point.
2851    .org nterp_op_goto_16 + NTERP_HANDLER_SIZE  // op_goto_16 handler is too big!
2852
2853/* ------------------------------ */
2854    .balign NTERP_HANDLER_SIZE
2855.L_op_goto_32: /* 0x2a */
2856    NAME_START nterp_op_goto_32
2857    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2858    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2859
2860/*
2861 * Unconditional branch, 32-bit offset.
2862 *
2863 * The branch distance is a signed code-unit offset, which we need to
2864 * double to get a byte offset.
2865 *
2866 * Because we need the SF bit set, we'll use an adds
2867 * to convert from Dalvik offset to byte offset.
2868 */
2869    /* goto/32 +AAAAAAAA */
2870    FETCH w0, 1                         // w0<- aaaa (lo)
2871    FETCH w1, 2                         // w1<- AAAA (hi)
2872    orr     wINST, w0, w1, lsl #16      // wINST<- AAAAaaaa
2873    BRANCH
2874
2875    NAME_END nterp_op_goto_32
2876    // Advance to the end of this handler. Causes error if we are past that point.
2877    .org nterp_op_goto_32 + NTERP_HANDLER_SIZE  // op_goto_32 handler is too big!
2878
2879/* ------------------------------ */
2880    .balign NTERP_HANDLER_SIZE
2881.L_op_packed_switch: /* 0x2b */
2882    NAME_START nterp_op_packed_switch
2883    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2884    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2885
2886/*
2887 * Handle a packed-switch or sparse-switch instruction.  In both cases
2888 * we decode it and hand it off to a helper function.
2889 *
2890 * We don't really expect backward branches in a switch statement, but
2891 * they're perfectly legal, so we check for them here.
2892 *
2893 * for: packed-switch, sparse-switch
2894 */
2895    /* op vAA, +BBBB */
2896    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
2897    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
2898    lsr     w3, wINST, #8               // w3<- AA
2899    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
2900    GET_VREG w1, w3                     // w1<- vAA
2901    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2
2902    bl      NterpDoPackedSwitch                       // w0<- code-unit branch offset
2903    sxtw    xINST, w0
2904    BRANCH
2905
2906    NAME_END nterp_op_packed_switch
2907    // Advance to the end of this handler. Causes error if we are past that point.
2908    .org nterp_op_packed_switch + NTERP_HANDLER_SIZE  // op_packed_switch handler is too big!
2909
2910/* ------------------------------ */
2911    .balign NTERP_HANDLER_SIZE
2912.L_op_sparse_switch: /* 0x2c */
2913    NAME_START nterp_op_sparse_switch
2914    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2915    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2916
2917/*
2918 * Handle a packed-switch or sparse-switch instruction.  In both cases
2919 * we decode it and hand it off to a helper function.
2920 *
2921 * We don't really expect backward branches in a switch statement, but
2922 * they're perfectly legal, so we check for them here.
2923 *
2924 * for: packed-switch, sparse-switch
2925 */
2926    /* op vAA, +BBBB */
2927    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
2928    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
2929    lsr     w3, wINST, #8               // w3<- AA
2930    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
2931    GET_VREG w1, w3                     // w1<- vAA
2932    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2
2933    bl      NterpDoSparseSwitch                       // w0<- code-unit branch offset
2934    sxtw    xINST, w0
2935    BRANCH
2936
2937/*
2938 * Return a 32-bit value.
2939 */
2940    NAME_END nterp_op_sparse_switch
2941    // Advance to the end of this handler. Causes error if we are past that point.
2942    .org nterp_op_sparse_switch + NTERP_HANDLER_SIZE  // op_sparse_switch handler is too big!
2943
2944/* ------------------------------ */
2945    .balign NTERP_HANDLER_SIZE
2946.L_op_cmpl_float: /* 0x2d */
2947    NAME_START nterp_op_cmpl_float
2948    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2949    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2950
2951    /*
2952     * Compare two floating-point values.  Puts 0, 1, or -1 into the
2953     * destination register based on the results of the comparison.
2954     */
2955    /* op vAA, vBB, vCC */
2956    FETCH w0, 1                         // w0<- CCBB
2957    lsr     w4, wINST, #8               // w4<- AA
2958    and     w2, w0, #255                // w2<- BB
2959    lsr     w3, w0, #8                  // w3<- CC
2960    GET_VREG s1, w2
2961    GET_VREG s2, w3
2962    fcmp s1, s2
2963    cset w0, ne
2964    cneg w0, w0, lt
2965    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
2966    GET_INST_OPCODE ip                  // extract opcode from rINST
2967    SET_VREG w0, w4                     // vAA<- w0
2968    GOTO_OPCODE ip                      // jump to next instruction
2969
2970    NAME_END nterp_op_cmpl_float
2971    // Advance to the end of this handler. Causes error if we are past that point.
2972    .org nterp_op_cmpl_float + NTERP_HANDLER_SIZE  // op_cmpl_float handler is too big!
2973
2974/* ------------------------------ */
2975    .balign NTERP_HANDLER_SIZE
2976.L_op_cmpg_float: /* 0x2e */
2977    NAME_START nterp_op_cmpg_float
2978    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
2979    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
2980
2981    /*
2982     * Compare two floating-point values.  Puts 0, 1, or -1 into the
2983     * destination register based on the results of the comparison.
2984     */
2985    /* op vAA, vBB, vCC */
2986    FETCH w0, 1                         // w0<- CCBB
2987    lsr     w4, wINST, #8               // w4<- AA
2988    and     w2, w0, #255                // w2<- BB
2989    lsr     w3, w0, #8                  // w3<- CC
2990    GET_VREG s1, w2
2991    GET_VREG s2, w3
2992    fcmp s1, s2
2993    cset w0, ne
2994    cneg w0, w0, cc
2995    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
2996    GET_INST_OPCODE ip                  // extract opcode from rINST
2997    SET_VREG w0, w4                     // vAA<- w0
2998    GOTO_OPCODE ip                      // jump to next instruction
2999
3000    NAME_END nterp_op_cmpg_float
3001    // Advance to the end of this handler. Causes error if we are past that point.
3002    .org nterp_op_cmpg_float + NTERP_HANDLER_SIZE  // op_cmpg_float handler is too big!
3003
3004/* ------------------------------ */
3005    .balign NTERP_HANDLER_SIZE
3006.L_op_cmpl_double: /* 0x2f */
3007    NAME_START nterp_op_cmpl_double
3008    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3009    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3010
3011    /*
3012     * Compare two floating-point values.  Puts 0, 1, or -1 into the
3013     * destination register based on the results of the comparison.
3014     */
3015    /* op vAA, vBB, vCC */
3016    FETCH w0, 1                         // w0<- CCBB
3017    LOAD_SCALED_VREG_MASK w5, 0xff      // w4<- ff * sizeof(vreg)
3018    lsr     w4, wINST, #8               // w4<- AA
3019    EXTRACT_SCALED_VREG w2, w5, w0, 0   // w2<- BB * sizeof(vreg)
3020    EXTRACT_SCALED_VREG w3, w5, w0, 8   // w3<- CC * sizeof(vreg)
3021    GET_VREG_DOUBLE_PRESCALED d1, w2
3022    GET_VREG_DOUBLE_PRESCALED d2, w3
3023    fcmp d1, d2
3024    cset w0, ne
3025    cneg w0, w0, lt
3026    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3027    GET_INST_OPCODE ip                  // extract opcode from rINST
3028    SET_VREG w0, w4                     // vAA<- w0
3029    GOTO_OPCODE ip                      // jump to next instruction
3030
3031    NAME_END nterp_op_cmpl_double
3032    // Advance to the end of this handler. Causes error if we are past that point.
3033    .org nterp_op_cmpl_double + NTERP_HANDLER_SIZE  // op_cmpl_double handler is too big!
3034
3035/* ------------------------------ */
3036    .balign NTERP_HANDLER_SIZE
3037.L_op_cmpg_double: /* 0x30 */
3038    NAME_START nterp_op_cmpg_double
3039    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3040    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3041
3042    /*
3043     * Compare two floating-point values.  Puts 0, 1, or -1 into the
3044     * destination register based on the results of the comparison.
3045     */
3046    /* op vAA, vBB, vCC */
3047    FETCH w0, 1                         // w0<- CCBB
3048    LOAD_SCALED_VREG_MASK w5, 0xff      // w4<- ff * sizeof(vreg)
3049    lsr     w4, wINST, #8               // w4<- AA
3050    EXTRACT_SCALED_VREG w2, w5, w0, 0   // w2<- BB * sizeof(vreg)
3051    EXTRACT_SCALED_VREG w3, w5, w0, 8   // w3<- CC * sizeof(vreg)
3052    GET_VREG_DOUBLE_PRESCALED d1, w2
3053    GET_VREG_DOUBLE_PRESCALED d2, w3
3054    fcmp d1, d2
3055    cset w0, ne
3056    cneg w0, w0, cc
3057    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3058    GET_INST_OPCODE ip                  // extract opcode from rINST
3059    SET_VREG w0, w4                     // vAA<- w0
3060    GOTO_OPCODE ip                      // jump to next instruction
3061
3062    NAME_END nterp_op_cmpg_double
3063    // Advance to the end of this handler. Causes error if we are past that point.
3064    .org nterp_op_cmpg_double + NTERP_HANDLER_SIZE  // op_cmpg_double handler is too big!
3065
3066/* ------------------------------ */
3067    .balign NTERP_HANDLER_SIZE
3068.L_op_cmp_long: /* 0x31 */
3069    NAME_START nterp_op_cmp_long
3070    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3071    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3072
3073    FETCH w0, 1                         // w0<- CCBB
3074    LOAD_SCALED_VREG_MASK w5, 0xff      // w4<- ff * sizeof(vreg)
3075    lsr     w4, wINST, #8               // w4<- AA
3076    EXTRACT_SCALED_VREG w2, w5, w0, 0   // w2<- BB * sizeof(vreg)
3077    EXTRACT_SCALED_VREG w3, w5, w0, 8   // w3<- CC * sizeof(vreg)
3078    GET_VREG_WIDE_PRESCALED x1, w2
3079    GET_VREG_WIDE_PRESCALED x2, w3
3080    cmp     x1, x2
3081    cset    w0, ne
3082    cneg    w0, w0, lt
3083    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
3084    SET_VREG w0, w4
3085    GET_INST_OPCODE ip                  // extract opcode from wINST
3086    GOTO_OPCODE ip                      // jump to next instruction
3087
3088    NAME_END nterp_op_cmp_long
3089    // Advance to the end of this handler. Causes error if we are past that point.
3090    .org nterp_op_cmp_long + NTERP_HANDLER_SIZE  // op_cmp_long handler is too big!
3091
3092/* ------------------------------ */
3093    .balign NTERP_HANDLER_SIZE
3094.L_op_if_eq: /* 0x32 */
3095    NAME_START nterp_op_if_eq
3096    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3097    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3098
3099    /*
3100     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3101     * fragment that specifies the comparison to perform.
3102     *
3103     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3104     */
3105    /* if-cmp vA, vB, +CCCC */
3106    lsr     w1, wINST, #12              // w1<- B
3107    ubfx    w0, wINST, #8, #4           // w0<- A
3108    GET_VREG w3, w1                     // w3<- vB
3109    GET_VREG w2, w0                     // w2<- vA
3110    cmp     w2, w3                      // compare (vA, vB)
3111    b.eq 1f
3112    FETCH_ADVANCE_INST 2
3113    GET_INST_OPCODE ip                  // extract opcode from wINST
3114    GOTO_OPCODE ip                      // jump to next instruction
31151:
3116    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3117    BRANCH
3118
3119    NAME_END nterp_op_if_eq
3120    // Advance to the end of this handler. Causes error if we are past that point.
3121    .org nterp_op_if_eq + NTERP_HANDLER_SIZE  // op_if_eq handler is too big!
3122
3123/* ------------------------------ */
3124    .balign NTERP_HANDLER_SIZE
3125.L_op_if_ne: /* 0x33 */
3126    NAME_START nterp_op_if_ne
3127    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3128    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3129
3130    /*
3131     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3132     * fragment that specifies the comparison to perform.
3133     *
3134     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3135     */
3136    /* if-cmp vA, vB, +CCCC */
3137    lsr     w1, wINST, #12              // w1<- B
3138    ubfx    w0, wINST, #8, #4           // w0<- A
3139    GET_VREG w3, w1                     // w3<- vB
3140    GET_VREG w2, w0                     // w2<- vA
3141    cmp     w2, w3                      // compare (vA, vB)
3142    b.ne 1f
3143    FETCH_ADVANCE_INST 2
3144    GET_INST_OPCODE ip                  // extract opcode from wINST
3145    GOTO_OPCODE ip                      // jump to next instruction
31461:
3147    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3148    BRANCH
3149
3150    NAME_END nterp_op_if_ne
3151    // Advance to the end of this handler. Causes error if we are past that point.
3152    .org nterp_op_if_ne + NTERP_HANDLER_SIZE  // op_if_ne handler is too big!
3153
3154/* ------------------------------ */
3155    .balign NTERP_HANDLER_SIZE
3156.L_op_if_lt: /* 0x34 */
3157    NAME_START nterp_op_if_lt
3158    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3159    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3160
3161    /*
3162     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3163     * fragment that specifies the comparison to perform.
3164     *
3165     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3166     */
3167    /* if-cmp vA, vB, +CCCC */
3168    lsr     w1, wINST, #12              // w1<- B
3169    ubfx    w0, wINST, #8, #4           // w0<- A
3170    GET_VREG w3, w1                     // w3<- vB
3171    GET_VREG w2, w0                     // w2<- vA
3172    cmp     w2, w3                      // compare (vA, vB)
3173    b.lt 1f
3174    FETCH_ADVANCE_INST 2
3175    GET_INST_OPCODE ip                  // extract opcode from wINST
3176    GOTO_OPCODE ip                      // jump to next instruction
31771:
3178    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3179    BRANCH
3180
3181    NAME_END nterp_op_if_lt
3182    // Advance to the end of this handler. Causes error if we are past that point.
3183    .org nterp_op_if_lt + NTERP_HANDLER_SIZE  // op_if_lt handler is too big!
3184
3185/* ------------------------------ */
3186    .balign NTERP_HANDLER_SIZE
3187.L_op_if_ge: /* 0x35 */
3188    NAME_START nterp_op_if_ge
3189    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3190    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3191
3192    /*
3193     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3194     * fragment that specifies the comparison to perform.
3195     *
3196     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3197     */
3198    /* if-cmp vA, vB, +CCCC */
3199    lsr     w1, wINST, #12              // w1<- B
3200    ubfx    w0, wINST, #8, #4           // w0<- A
3201    GET_VREG w3, w1                     // w3<- vB
3202    GET_VREG w2, w0                     // w2<- vA
3203    cmp     w2, w3                      // compare (vA, vB)
3204    b.ge 1f
3205    FETCH_ADVANCE_INST 2
3206    GET_INST_OPCODE ip                  // extract opcode from wINST
3207    GOTO_OPCODE ip                      // jump to next instruction
32081:
3209    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3210    BRANCH
3211
3212    NAME_END nterp_op_if_ge
3213    // Advance to the end of this handler. Causes error if we are past that point.
3214    .org nterp_op_if_ge + NTERP_HANDLER_SIZE  // op_if_ge handler is too big!
3215
3216/* ------------------------------ */
3217    .balign NTERP_HANDLER_SIZE
3218.L_op_if_gt: /* 0x36 */
3219    NAME_START nterp_op_if_gt
3220    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3221    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3222
3223    /*
3224     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3225     * fragment that specifies the comparison to perform.
3226     *
3227     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3228     */
3229    /* if-cmp vA, vB, +CCCC */
3230    lsr     w1, wINST, #12              // w1<- B
3231    ubfx    w0, wINST, #8, #4           // w0<- A
3232    GET_VREG w3, w1                     // w3<- vB
3233    GET_VREG w2, w0                     // w2<- vA
3234    cmp     w2, w3                      // compare (vA, vB)
3235    b.gt 1f
3236    FETCH_ADVANCE_INST 2
3237    GET_INST_OPCODE ip                  // extract opcode from wINST
3238    GOTO_OPCODE ip                      // jump to next instruction
32391:
3240    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3241    BRANCH
3242
3243    NAME_END nterp_op_if_gt
3244    // Advance to the end of this handler. Causes error if we are past that point.
3245    .org nterp_op_if_gt + NTERP_HANDLER_SIZE  // op_if_gt handler is too big!
3246
3247/* ------------------------------ */
3248    .balign NTERP_HANDLER_SIZE
3249.L_op_if_le: /* 0x37 */
3250    NAME_START nterp_op_if_le
3251    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3252    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3253
3254    /*
3255     * Generic two-operand compare-and-branch operation.  Provide a "condition"
3256     * fragment that specifies the comparison to perform.
3257     *
3258     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
3259     */
3260    /* if-cmp vA, vB, +CCCC */
3261    lsr     w1, wINST, #12              // w1<- B
3262    ubfx    w0, wINST, #8, #4           // w0<- A
3263    GET_VREG w3, w1                     // w3<- vB
3264    GET_VREG w2, w0                     // w2<- vA
3265    cmp     w2, w3                      // compare (vA, vB)
3266    b.le 1f
3267    FETCH_ADVANCE_INST 2
3268    GET_INST_OPCODE ip                  // extract opcode from wINST
3269    GOTO_OPCODE ip                      // jump to next instruction
32701:
3271    FETCH_S wINST, 1                    // wINST<- branch offset, in code units
3272    BRANCH
3273
3274    NAME_END nterp_op_if_le
3275    // Advance to the end of this handler. Causes error if we are past that point.
3276    .org nterp_op_if_le + NTERP_HANDLER_SIZE  // op_if_le handler is too big!
3277
3278/* ------------------------------ */
3279    .balign NTERP_HANDLER_SIZE
3280.L_op_if_eqz: /* 0x38 */
3281    NAME_START nterp_op_if_eqz
3282    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3283    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3284
3285    /*
3286     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3287     * fragment that specifies the comparison to perform.
3288     *
3289     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3290     */
3291    /* if-cmp vAA, +BBBB */
3292    lsr     w0, wINST, #8               // w0<- AA
3293    GET_VREG w2, w0                     // w2<- vAA
3294    .if 0
3295    cmp     w2, #0                      // compare (vA, 0)
3296    .endif
3297    cbz     w2, 1f
3298    FETCH_ADVANCE_INST 2
3299    GET_INST_OPCODE ip                  // extract opcode from wINST
3300    GOTO_OPCODE ip                      // jump to next instruction
33011:
3302    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3303    BRANCH
3304
3305    NAME_END nterp_op_if_eqz
3306    // Advance to the end of this handler. Causes error if we are past that point.
3307    .org nterp_op_if_eqz + NTERP_HANDLER_SIZE  // op_if_eqz handler is too big!
3308
3309/* ------------------------------ */
3310    .balign NTERP_HANDLER_SIZE
3311.L_op_if_nez: /* 0x39 */
3312    NAME_START nterp_op_if_nez
3313    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3314    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3315
3316    /*
3317     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3318     * fragment that specifies the comparison to perform.
3319     *
3320     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3321     */
3322    /* if-cmp vAA, +BBBB */
3323    lsr     w0, wINST, #8               // w0<- AA
3324    GET_VREG w2, w0                     // w2<- vAA
3325    .if 0
3326    cmp     w2, #0                      // compare (vA, 0)
3327    .endif
3328    cbnz    w2, 1f
3329    FETCH_ADVANCE_INST 2
3330    GET_INST_OPCODE ip                  // extract opcode from wINST
3331    GOTO_OPCODE ip                      // jump to next instruction
33321:
3333    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3334    BRANCH
3335
3336    NAME_END nterp_op_if_nez
3337    // Advance to the end of this handler. Causes error if we are past that point.
3338    .org nterp_op_if_nez + NTERP_HANDLER_SIZE  // op_if_nez handler is too big!
3339
3340/* ------------------------------ */
3341    .balign NTERP_HANDLER_SIZE
3342.L_op_if_ltz: /* 0x3a */
3343    NAME_START nterp_op_if_ltz
3344    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3345    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3346
3347    /*
3348     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3349     * fragment that specifies the comparison to perform.
3350     *
3351     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3352     */
3353    /* if-cmp vAA, +BBBB */
3354    lsr     w0, wINST, #8               // w0<- AA
3355    GET_VREG w2, w0                     // w2<- vAA
3356    .if 0
3357    cmp     w2, #0                      // compare (vA, 0)
3358    .endif
3359    tbnz    w2, #31, 1f
3360    FETCH_ADVANCE_INST 2
3361    GET_INST_OPCODE ip                  // extract opcode from wINST
3362    GOTO_OPCODE ip                      // jump to next instruction
33631:
3364    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3365    BRANCH
3366
3367    NAME_END nterp_op_if_ltz
3368    // Advance to the end of this handler. Causes error if we are past that point.
3369    .org nterp_op_if_ltz + NTERP_HANDLER_SIZE  // op_if_ltz handler is too big!
3370
3371/* ------------------------------ */
3372    .balign NTERP_HANDLER_SIZE
3373.L_op_if_gez: /* 0x3b */
3374    NAME_START nterp_op_if_gez
3375    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3376    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3377
3378    /*
3379     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3380     * fragment that specifies the comparison to perform.
3381     *
3382     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3383     */
3384    /* if-cmp vAA, +BBBB */
3385    lsr     w0, wINST, #8               // w0<- AA
3386    GET_VREG w2, w0                     // w2<- vAA
3387    .if 0
3388    cmp     w2, #0                      // compare (vA, 0)
3389    .endif
3390    tbz     w2, #31, 1f
3391    FETCH_ADVANCE_INST 2
3392    GET_INST_OPCODE ip                  // extract opcode from wINST
3393    GOTO_OPCODE ip                      // jump to next instruction
33941:
3395    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3396    BRANCH
3397
3398    NAME_END nterp_op_if_gez
3399    // Advance to the end of this handler. Causes error if we are past that point.
3400    .org nterp_op_if_gez + NTERP_HANDLER_SIZE  // op_if_gez handler is too big!
3401
3402/* ------------------------------ */
3403    .balign NTERP_HANDLER_SIZE
3404.L_op_if_gtz: /* 0x3c */
3405    NAME_START nterp_op_if_gtz
3406    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3407    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3408
3409    /*
3410     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3411     * fragment that specifies the comparison to perform.
3412     *
3413     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3414     */
3415    /* if-cmp vAA, +BBBB */
3416    lsr     w0, wINST, #8               // w0<- AA
3417    GET_VREG w2, w0                     // w2<- vAA
3418    .if 1
3419    cmp     w2, #0                      // compare (vA, 0)
3420    .endif
3421    b.gt 1f
3422    FETCH_ADVANCE_INST 2
3423    GET_INST_OPCODE ip                  // extract opcode from wINST
3424    GOTO_OPCODE ip                      // jump to next instruction
34251:
3426    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3427    BRANCH
3428
3429    NAME_END nterp_op_if_gtz
3430    // Advance to the end of this handler. Causes error if we are past that point.
3431    .org nterp_op_if_gtz + NTERP_HANDLER_SIZE  // op_if_gtz handler is too big!
3432
3433/* ------------------------------ */
3434    .balign NTERP_HANDLER_SIZE
3435.L_op_if_lez: /* 0x3d */
3436    NAME_START nterp_op_if_lez
3437    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3438    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3439
3440    /*
3441     * Generic one-operand compare-and-branch operation.  Provide a "condition"
3442     * fragment that specifies the comparison to perform.
3443     *
3444     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
3445     */
3446    /* if-cmp vAA, +BBBB */
3447    lsr     w0, wINST, #8               // w0<- AA
3448    GET_VREG w2, w0                     // w2<- vAA
3449    .if 1
3450    cmp     w2, #0                      // compare (vA, 0)
3451    .endif
3452    b.le 1f
3453    FETCH_ADVANCE_INST 2
3454    GET_INST_OPCODE ip                  // extract opcode from wINST
3455    GOTO_OPCODE ip                      // jump to next instruction
34561:
3457    FETCH_S wINST, 1                    // w1<- branch offset, in code units
3458    BRANCH
3459
3460    NAME_END nterp_op_if_lez
3461    // Advance to the end of this handler. Causes error if we are past that point.
3462    .org nterp_op_if_lez + NTERP_HANDLER_SIZE  // op_if_lez handler is too big!
3463
3464/* ------------------------------ */
3465    .balign NTERP_HANDLER_SIZE
3466.L_op_unused_3e: /* 0x3e */
3467    NAME_START nterp_op_unused_3e
3468    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3469    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3470
3471    brk 42
3472
3473    NAME_END nterp_op_unused_3e
3474    // Advance to the end of this handler. Causes error if we are past that point.
3475    .org nterp_op_unused_3e + NTERP_HANDLER_SIZE  // op_unused_3e handler is too big!
3476
3477/* ------------------------------ */
3478    .balign NTERP_HANDLER_SIZE
3479.L_op_unused_3f: /* 0x3f */
3480    NAME_START nterp_op_unused_3f
3481    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3482    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3483
3484    brk 42
3485
3486    NAME_END nterp_op_unused_3f
3487    // Advance to the end of this handler. Causes error if we are past that point.
3488    .org nterp_op_unused_3f + NTERP_HANDLER_SIZE  // op_unused_3f handler is too big!
3489
3490/* ------------------------------ */
3491    .balign NTERP_HANDLER_SIZE
3492.L_op_unused_40: /* 0x40 */
3493    NAME_START nterp_op_unused_40
3494    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3495    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3496
3497    brk 42
3498
3499    NAME_END nterp_op_unused_40
3500    // Advance to the end of this handler. Causes error if we are past that point.
3501    .org nterp_op_unused_40 + NTERP_HANDLER_SIZE  // op_unused_40 handler is too big!
3502
3503/* ------------------------------ */
3504    .balign NTERP_HANDLER_SIZE
3505.L_op_unused_41: /* 0x41 */
3506    NAME_START nterp_op_unused_41
3507    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3508    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3509
3510    brk 42
3511
3512    NAME_END nterp_op_unused_41
3513    // Advance to the end of this handler. Causes error if we are past that point.
3514    .org nterp_op_unused_41 + NTERP_HANDLER_SIZE  // op_unused_41 handler is too big!
3515
3516/* ------------------------------ */
3517    .balign NTERP_HANDLER_SIZE
3518.L_op_unused_42: /* 0x42 */
3519    NAME_START nterp_op_unused_42
3520    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3521    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3522
3523    brk 42
3524
3525    NAME_END nterp_op_unused_42
3526    // Advance to the end of this handler. Causes error if we are past that point.
3527    .org nterp_op_unused_42 + NTERP_HANDLER_SIZE  // op_unused_42 handler is too big!
3528
3529/* ------------------------------ */
3530    .balign NTERP_HANDLER_SIZE
3531.L_op_unused_43: /* 0x43 */
3532    NAME_START nterp_op_unused_43
3533    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3534    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3535
3536    brk 42
3537
3538    NAME_END nterp_op_unused_43
3539    // Advance to the end of this handler. Causes error if we are past that point.
3540    .org nterp_op_unused_43 + NTERP_HANDLER_SIZE  // op_unused_43 handler is too big!
3541
3542/* ------------------------------ */
3543    .balign NTERP_HANDLER_SIZE
3544.L_op_aget: /* 0x44 */
3545    NAME_START nterp_op_aget
3546    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3547    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3548
3549/*
3550 * Array get.  vAA <- vBB[vCC].
3551 *
3552 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3553 *
3554 */
3555    FETCH_B w2, 1, 0                    // w2<- BB
3556    lsr     w9, wINST, #8               // w9<- AA
3557    FETCH_B w3, 1, 1                    // w3<- CC
3558    GET_VREG w0, w2                     // w0<- vBB (array object)
3559    GET_VREG w1, w3                     // w1<- vCC (requested index)
3560    cbz     x0, common_errNullObject    // bail if null array object.
3561    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3562    add     x0, x0, w1, uxtw #2    // w0<- arrayObj + index*width
3563    cmp     w1, w3                      // compare unsigned index, length
3564    bcs     common_errArrayIndex        // index >= length, bail
3565    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3566    GET_INST_OPCODE x10                 // extract opcode from wINST
3567    .if 0
3568    ldr     x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3569    SET_VREG_WIDE x2, w9
3570    GOTO_OPCODE x10                     // jump to next instruction
3571    .elseif 0
3572    ldr   w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3573    UNPOISON_HEAP_REF w2
3574    TEST_IF_MARKING 2f
35751:
3576    SET_VREG_OBJECT w2, w9              // vAA<- w2
3577    GOTO_OPCODE x10                     // jump to next instruction
35782:
3579    bl art_quick_read_barrier_mark_reg02
3580    b 1b
3581    .else
3582    ldr   w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3583    SET_VREG w2, w9                     // vAA<- w2
3584    GOTO_OPCODE x10                     // jump to next instruction
3585    .endif
3586
3587    NAME_END nterp_op_aget
3588    // Advance to the end of this handler. Causes error if we are past that point.
3589    .org nterp_op_aget + NTERP_HANDLER_SIZE  // op_aget handler is too big!
3590
3591/* ------------------------------ */
3592    .balign NTERP_HANDLER_SIZE
3593.L_op_aget_wide: /* 0x45 */
3594    NAME_START nterp_op_aget_wide
3595    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3596    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3597
3598/*
3599 * Array get.  vAA <- vBB[vCC].
3600 *
3601 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3602 *
3603 */
3604    FETCH_B w2, 1, 0                    // w2<- BB
3605    lsr     w9, wINST, #8               // w9<- AA
3606    FETCH_B w3, 1, 1                    // w3<- CC
3607    GET_VREG w0, w2                     // w0<- vBB (array object)
3608    GET_VREG w1, w3                     // w1<- vCC (requested index)
3609    cbz     x0, common_errNullObject    // bail if null array object.
3610    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3611    add     x0, x0, w1, uxtw #3    // w0<- arrayObj + index*width
3612    cmp     w1, w3                      // compare unsigned index, length
3613    bcs     common_errArrayIndex        // index >= length, bail
3614    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3615    GET_INST_OPCODE x10                 // extract opcode from wINST
3616    .if 1
3617    ldr     x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3618    SET_VREG_WIDE x2, w9
3619    GOTO_OPCODE x10                     // jump to next instruction
3620    .elseif 0
3621    ldr   w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3622    UNPOISON_HEAP_REF w2
3623    TEST_IF_MARKING 2f
36241:
3625    SET_VREG_OBJECT w2, w9              // vAA<- w2
3626    GOTO_OPCODE x10                     // jump to next instruction
36272:
3628    bl art_quick_read_barrier_mark_reg02
3629    b 1b
3630    .else
3631    ldr   w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3632    SET_VREG w2, w9                     // vAA<- w2
3633    GOTO_OPCODE x10                     // jump to next instruction
3634    .endif
3635
3636    NAME_END nterp_op_aget_wide
3637    // Advance to the end of this handler. Causes error if we are past that point.
3638    .org nterp_op_aget_wide + NTERP_HANDLER_SIZE  // op_aget_wide handler is too big!
3639
3640/* ------------------------------ */
3641    .balign NTERP_HANDLER_SIZE
3642.L_op_aget_object: /* 0x46 */
3643    NAME_START nterp_op_aget_object
3644    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3645    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3646
3647/*
3648 * Array get.  vAA <- vBB[vCC].
3649 *
3650 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3651 *
3652 */
3653    FETCH_B w2, 1, 0                    // w2<- BB
3654    lsr     w9, wINST, #8               // w9<- AA
3655    FETCH_B w3, 1, 1                    // w3<- CC
3656    GET_VREG w0, w2                     // w0<- vBB (array object)
3657    GET_VREG w1, w3                     // w1<- vCC (requested index)
3658    cbz     x0, common_errNullObject    // bail if null array object.
3659    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3660    add     x0, x0, w1, uxtw #2    // w0<- arrayObj + index*width
3661    cmp     w1, w3                      // compare unsigned index, length
3662    bcs     common_errArrayIndex        // index >= length, bail
3663    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3664    GET_INST_OPCODE x10                 // extract opcode from wINST
3665    .if 0
3666    ldr     x2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3667    SET_VREG_WIDE x2, w9
3668    GOTO_OPCODE x10                     // jump to next instruction
3669    .elseif 1
3670    ldr   w2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3671    UNPOISON_HEAP_REF w2
3672    TEST_IF_MARKING 2f
36731:
3674    SET_VREG_OBJECT w2, w9              // vAA<- w2
3675    GOTO_OPCODE x10                     // jump to next instruction
36762:
3677    bl art_quick_read_barrier_mark_reg02
3678    b 1b
3679    .else
3680    ldr   w2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3681    SET_VREG w2, w9                     // vAA<- w2
3682    GOTO_OPCODE x10                     // jump to next instruction
3683    .endif
3684
3685    NAME_END nterp_op_aget_object
3686    // Advance to the end of this handler. Causes error if we are past that point.
3687    .org nterp_op_aget_object + NTERP_HANDLER_SIZE  // op_aget_object handler is too big!
3688
3689/* ------------------------------ */
3690    .balign NTERP_HANDLER_SIZE
3691.L_op_aget_boolean: /* 0x47 */
3692    NAME_START nterp_op_aget_boolean
3693    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3694    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3695
3696/*
3697 * Array get.  vAA <- vBB[vCC].
3698 *
3699 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3700 *
3701 */
3702    FETCH_B w2, 1, 0                    // w2<- BB
3703    lsr     w9, wINST, #8               // w9<- AA
3704    FETCH_B w3, 1, 1                    // w3<- CC
3705    GET_VREG w0, w2                     // w0<- vBB (array object)
3706    GET_VREG w1, w3                     // w1<- vCC (requested index)
3707    cbz     x0, common_errNullObject    // bail if null array object.
3708    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3709    add     x0, x0, w1, uxtw #0    // w0<- arrayObj + index*width
3710    cmp     w1, w3                      // compare unsigned index, length
3711    bcs     common_errArrayIndex        // index >= length, bail
3712    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3713    GET_INST_OPCODE x10                 // extract opcode from wINST
3714    .if 0
3715    ldr     x2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3716    SET_VREG_WIDE x2, w9
3717    GOTO_OPCODE x10                     // jump to next instruction
3718    .elseif 0
3719    ldrb   w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3720    UNPOISON_HEAP_REF w2
3721    TEST_IF_MARKING 2f
37221:
3723    SET_VREG_OBJECT w2, w9              // vAA<- w2
3724    GOTO_OPCODE x10                     // jump to next instruction
37252:
3726    bl art_quick_read_barrier_mark_reg02
3727    b 1b
3728    .else
3729    ldrb   w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3730    SET_VREG w2, w9                     // vAA<- w2
3731    GOTO_OPCODE x10                     // jump to next instruction
3732    .endif
3733
3734    NAME_END nterp_op_aget_boolean
3735    // Advance to the end of this handler. Causes error if we are past that point.
3736    .org nterp_op_aget_boolean + NTERP_HANDLER_SIZE  // op_aget_boolean handler is too big!
3737
3738/* ------------------------------ */
3739    .balign NTERP_HANDLER_SIZE
3740.L_op_aget_byte: /* 0x48 */
3741    NAME_START nterp_op_aget_byte
3742    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3743    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3744
3745/*
3746 * Array get.  vAA <- vBB[vCC].
3747 *
3748 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3749 *
3750 */
3751    FETCH_B w2, 1, 0                    // w2<- BB
3752    lsr     w9, wINST, #8               // w9<- AA
3753    FETCH_B w3, 1, 1                    // w3<- CC
3754    GET_VREG w0, w2                     // w0<- vBB (array object)
3755    GET_VREG w1, w3                     // w1<- vCC (requested index)
3756    cbz     x0, common_errNullObject    // bail if null array object.
3757    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3758    add     x0, x0, w1, uxtw #0    // w0<- arrayObj + index*width
3759    cmp     w1, w3                      // compare unsigned index, length
3760    bcs     common_errArrayIndex        // index >= length, bail
3761    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3762    GET_INST_OPCODE x10                 // extract opcode from wINST
3763    .if 0
3764    ldr     x2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3765    SET_VREG_WIDE x2, w9
3766    GOTO_OPCODE x10                     // jump to next instruction
3767    .elseif 0
3768    ldrsb   w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3769    UNPOISON_HEAP_REF w2
3770    TEST_IF_MARKING 2f
37711:
3772    SET_VREG_OBJECT w2, w9              // vAA<- w2
3773    GOTO_OPCODE x10                     // jump to next instruction
37742:
3775    bl art_quick_read_barrier_mark_reg02
3776    b 1b
3777    .else
3778    ldrsb   w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3779    SET_VREG w2, w9                     // vAA<- w2
3780    GOTO_OPCODE x10                     // jump to next instruction
3781    .endif
3782
3783    NAME_END nterp_op_aget_byte
3784    // Advance to the end of this handler. Causes error if we are past that point.
3785    .org nterp_op_aget_byte + NTERP_HANDLER_SIZE  // op_aget_byte handler is too big!
3786
3787/* ------------------------------ */
3788    .balign NTERP_HANDLER_SIZE
3789.L_op_aget_char: /* 0x49 */
3790    NAME_START nterp_op_aget_char
3791    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3792    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3793
3794/*
3795 * Array get.  vAA <- vBB[vCC].
3796 *
3797 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3798 *
3799 */
3800    FETCH_B w2, 1, 0                    // w2<- BB
3801    lsr     w9, wINST, #8               // w9<- AA
3802    FETCH_B w3, 1, 1                    // w3<- CC
3803    GET_VREG w0, w2                     // w0<- vBB (array object)
3804    GET_VREG w1, w3                     // w1<- vCC (requested index)
3805    cbz     x0, common_errNullObject    // bail if null array object.
3806    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3807    add     x0, x0, w1, uxtw #1    // w0<- arrayObj + index*width
3808    cmp     w1, w3                      // compare unsigned index, length
3809    bcs     common_errArrayIndex        // index >= length, bail
3810    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3811    GET_INST_OPCODE x10                 // extract opcode from wINST
3812    .if 0
3813    ldr     x2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3814    SET_VREG_WIDE x2, w9
3815    GOTO_OPCODE x10                     // jump to next instruction
3816    .elseif 0
3817    ldrh   w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3818    UNPOISON_HEAP_REF w2
3819    TEST_IF_MARKING 2f
38201:
3821    SET_VREG_OBJECT w2, w9              // vAA<- w2
3822    GOTO_OPCODE x10                     // jump to next instruction
38232:
3824    bl art_quick_read_barrier_mark_reg02
3825    b 1b
3826    .else
3827    ldrh   w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3828    SET_VREG w2, w9                     // vAA<- w2
3829    GOTO_OPCODE x10                     // jump to next instruction
3830    .endif
3831
3832    NAME_END nterp_op_aget_char
3833    // Advance to the end of this handler. Causes error if we are past that point.
3834    .org nterp_op_aget_char + NTERP_HANDLER_SIZE  // op_aget_char handler is too big!
3835
3836/* ------------------------------ */
3837    .balign NTERP_HANDLER_SIZE
3838.L_op_aget_short: /* 0x4a */
3839    NAME_START nterp_op_aget_short
3840    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3841    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3842
3843/*
3844 * Array get.  vAA <- vBB[vCC].
3845 *
3846 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
3847 *
3848 */
3849    FETCH_B w2, 1, 0                    // w2<- BB
3850    lsr     w9, wINST, #8               // w9<- AA
3851    FETCH_B w3, 1, 1                    // w3<- CC
3852    GET_VREG w0, w2                     // w0<- vBB (array object)
3853    GET_VREG w1, w3                     // w1<- vCC (requested index)
3854    cbz     x0, common_errNullObject    // bail if null array object.
3855    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
3856    add     x0, x0, w1, uxtw #1    // w0<- arrayObj + index*width
3857    cmp     w1, w3                      // compare unsigned index, length
3858    bcs     common_errArrayIndex        // index >= length, bail
3859    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3860    GET_INST_OPCODE x10                 // extract opcode from wINST
3861    .if 0
3862    ldr     x2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET]     // x2<- vBB[vCC]
3863    SET_VREG_WIDE x2, w9
3864    GOTO_OPCODE x10                     // jump to next instruction
3865    .elseif 0
3866    ldrsh   w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3867    UNPOISON_HEAP_REF w2
3868    TEST_IF_MARKING 2f
38691:
3870    SET_VREG_OBJECT w2, w9              // vAA<- w2
3871    GOTO_OPCODE x10                     // jump to next instruction
38722:
3873    bl art_quick_read_barrier_mark_reg02
3874    b 1b
3875    .else
3876    ldrsh   w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET]     // w2<- vBB[vCC]
3877    SET_VREG w2, w9                     // vAA<- w2
3878    GOTO_OPCODE x10                     // jump to next instruction
3879    .endif
3880
3881    NAME_END nterp_op_aget_short
3882    // Advance to the end of this handler. Causes error if we are past that point.
3883    .org nterp_op_aget_short + NTERP_HANDLER_SIZE  // op_aget_short handler is too big!
3884
3885/* ------------------------------ */
3886    .balign NTERP_HANDLER_SIZE
3887.L_op_aput: /* 0x4b */
3888    NAME_START nterp_op_aput
3889    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3890    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3891
3892/*
3893 * Array put.  vBB[vCC] <- vAA.
3894 *
3895 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
3896 *
3897 */
3898    FETCH_B w2, 1, 0                    // w2<- BB
3899    lsr     w9, wINST, #8               // w9<- AA
3900    FETCH_B w3, 1, 1                    // w3<- CC
3901    GET_VREG w0, w2                     // w0<- vBB (array object)
3902    GET_VREG w1, w3                     // w1<- vCC (requested index)
3903    cbz     w0, common_errNullObject    // bail if null
3904    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
3905    .if !0
3906    add     x0, x0, w1, uxtw #2    // w0<- arrayObj + index*width
3907    .endif
3908    cmp     w1, w3                      // compare unsigned index, length
3909    bcs     common_errArrayIndex        // index >= length, bail
3910    .if 0
3911    EXPORT_PC                           // Export PC before overwriting it.
3912    .endif
3913    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3914    .if 0
3915    GET_VREG_WIDE x2, w9                // x2<- vAA
3916    .else
3917    GET_VREG w2, w9                     // w2<- vAA
3918    .endif
3919    .if 0
3920    str  x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
3921    .elseif 0
3922    bl art_quick_aput_obj
3923    .else
3924    str  w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
3925    .endif
3926    GET_INST_OPCODE ip                  // extract opcode from rINST
3927    GOTO_OPCODE ip                      // jump to next instruction
3928
3929    NAME_END nterp_op_aput
3930    // Advance to the end of this handler. Causes error if we are past that point.
3931    .org nterp_op_aput + NTERP_HANDLER_SIZE  // op_aput handler is too big!
3932
3933/* ------------------------------ */
3934    .balign NTERP_HANDLER_SIZE
3935.L_op_aput_wide: /* 0x4c */
3936    NAME_START nterp_op_aput_wide
3937    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3938    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3939
3940/*
3941 * Array put.  vBB[vCC] <- vAA.
3942 *
3943 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
3944 *
3945 */
3946    FETCH_B w2, 1, 0                    // w2<- BB
3947    lsr     w9, wINST, #8               // w9<- AA
3948    FETCH_B w3, 1, 1                    // w3<- CC
3949    GET_VREG w0, w2                     // w0<- vBB (array object)
3950    GET_VREG w1, w3                     // w1<- vCC (requested index)
3951    cbz     w0, common_errNullObject    // bail if null
3952    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
3953    .if !0
3954    add     x0, x0, w1, uxtw #3    // w0<- arrayObj + index*width
3955    .endif
3956    cmp     w1, w3                      // compare unsigned index, length
3957    bcs     common_errArrayIndex        // index >= length, bail
3958    .if 0
3959    EXPORT_PC                           // Export PC before overwriting it.
3960    .endif
3961    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
3962    .if 1
3963    GET_VREG_WIDE x2, w9                // x2<- vAA
3964    .else
3965    GET_VREG w2, w9                     // w2<- vAA
3966    .endif
3967    .if 1
3968    str  x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
3969    .elseif 0
3970    bl art_quick_aput_obj
3971    .else
3972    str  w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
3973    .endif
3974    GET_INST_OPCODE ip                  // extract opcode from rINST
3975    GOTO_OPCODE ip                      // jump to next instruction
3976
3977    NAME_END nterp_op_aput_wide
3978    // Advance to the end of this handler. Causes error if we are past that point.
3979    .org nterp_op_aput_wide + NTERP_HANDLER_SIZE  // op_aput_wide handler is too big!
3980
3981/* ------------------------------ */
3982    .balign NTERP_HANDLER_SIZE
3983.L_op_aput_object: /* 0x4d */
3984    NAME_START nterp_op_aput_object
3985    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
3986    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
3987
3988/*
3989 * Array put.  vBB[vCC] <- vAA.
3990 *
3991 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
3992 *
3993 */
3994    FETCH_B w2, 1, 0                    // w2<- BB
3995    lsr     w9, wINST, #8               // w9<- AA
3996    FETCH_B w3, 1, 1                    // w3<- CC
3997    GET_VREG w0, w2                     // w0<- vBB (array object)
3998    GET_VREG w1, w3                     // w1<- vCC (requested index)
3999    cbz     w0, common_errNullObject    // bail if null
4000    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
4001    .if !1
4002    add     x0, x0, w1, uxtw #2    // w0<- arrayObj + index*width
4003    .endif
4004    cmp     w1, w3                      // compare unsigned index, length
4005    bcs     common_errArrayIndex        // index >= length, bail
4006    .if 1
4007    EXPORT_PC                           // Export PC before overwriting it.
4008    .endif
4009    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
4010    .if 0
4011    GET_VREG_WIDE x2, w9                // x2<- vAA
4012    .else
4013    GET_VREG w2, w9                     // w2<- vAA
4014    .endif
4015    .if 0
4016    str  x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
4017    .elseif 1
4018    bl art_quick_aput_obj
4019    .else
4020    str  w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
4021    .endif
4022    GET_INST_OPCODE ip                  // extract opcode from rINST
4023    GOTO_OPCODE ip                      // jump to next instruction
4024
4025    NAME_END nterp_op_aput_object
4026    // Advance to the end of this handler. Causes error if we are past that point.
4027    .org nterp_op_aput_object + NTERP_HANDLER_SIZE  // op_aput_object handler is too big!
4028
4029/* ------------------------------ */
4030    .balign NTERP_HANDLER_SIZE
4031.L_op_aput_boolean: /* 0x4e */
4032    NAME_START nterp_op_aput_boolean
4033    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4034    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4035
4036/*
4037 * Array put.  vBB[vCC] <- vAA.
4038 *
4039 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
4040 *
4041 */
4042    FETCH_B w2, 1, 0                    // w2<- BB
4043    lsr     w9, wINST, #8               // w9<- AA
4044    FETCH_B w3, 1, 1                    // w3<- CC
4045    GET_VREG w0, w2                     // w0<- vBB (array object)
4046    GET_VREG w1, w3                     // w1<- vCC (requested index)
4047    cbz     w0, common_errNullObject    // bail if null
4048    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
4049    .if !0
4050    add     x0, x0, w1, uxtw #0    // w0<- arrayObj + index*width
4051    .endif
4052    cmp     w1, w3                      // compare unsigned index, length
4053    bcs     common_errArrayIndex        // index >= length, bail
4054    .if 0
4055    EXPORT_PC                           // Export PC before overwriting it.
4056    .endif
4057    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
4058    .if 0
4059    GET_VREG_WIDE x2, w9                // x2<- vAA
4060    .else
4061    GET_VREG w2, w9                     // w2<- vAA
4062    .endif
4063    .if 0
4064    strb  x2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
4065    .elseif 0
4066    bl art_quick_aput_obj
4067    .else
4068    strb  w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
4069    .endif
4070    GET_INST_OPCODE ip                  // extract opcode from rINST
4071    GOTO_OPCODE ip                      // jump to next instruction
4072
4073    NAME_END nterp_op_aput_boolean
4074    // Advance to the end of this handler. Causes error if we are past that point.
4075    .org nterp_op_aput_boolean + NTERP_HANDLER_SIZE  // op_aput_boolean handler is too big!
4076
4077/* ------------------------------ */
4078    .balign NTERP_HANDLER_SIZE
4079.L_op_aput_byte: /* 0x4f */
4080    NAME_START nterp_op_aput_byte
4081    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4082    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4083
4084/*
4085 * Array put.  vBB[vCC] <- vAA.
4086 *
4087 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
4088 *
4089 */
4090    FETCH_B w2, 1, 0                    // w2<- BB
4091    lsr     w9, wINST, #8               // w9<- AA
4092    FETCH_B w3, 1, 1                    // w3<- CC
4093    GET_VREG w0, w2                     // w0<- vBB (array object)
4094    GET_VREG w1, w3                     // w1<- vCC (requested index)
4095    cbz     w0, common_errNullObject    // bail if null
4096    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
4097    .if !0
4098    add     x0, x0, w1, uxtw #0    // w0<- arrayObj + index*width
4099    .endif
4100    cmp     w1, w3                      // compare unsigned index, length
4101    bcs     common_errArrayIndex        // index >= length, bail
4102    .if 0
4103    EXPORT_PC                           // Export PC before overwriting it.
4104    .endif
4105    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
4106    .if 0
4107    GET_VREG_WIDE x2, w9                // x2<- vAA
4108    .else
4109    GET_VREG w2, w9                     // w2<- vAA
4110    .endif
4111    .if 0
4112    strb  x2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
4113    .elseif 0
4114    bl art_quick_aput_obj
4115    .else
4116    strb  w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
4117    .endif
4118    GET_INST_OPCODE ip                  // extract opcode from rINST
4119    GOTO_OPCODE ip                      // jump to next instruction
4120
4121    NAME_END nterp_op_aput_byte
4122    // Advance to the end of this handler. Causes error if we are past that point.
4123    .org nterp_op_aput_byte + NTERP_HANDLER_SIZE  // op_aput_byte handler is too big!
4124
4125/* ------------------------------ */
4126    .balign NTERP_HANDLER_SIZE
4127.L_op_aput_char: /* 0x50 */
4128    NAME_START nterp_op_aput_char
4129    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4130    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4131
4132/*
4133 * Array put.  vBB[vCC] <- vAA.
4134 *
4135 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
4136 *
4137 */
4138    FETCH_B w2, 1, 0                    // w2<- BB
4139    lsr     w9, wINST, #8               // w9<- AA
4140    FETCH_B w3, 1, 1                    // w3<- CC
4141    GET_VREG w0, w2                     // w0<- vBB (array object)
4142    GET_VREG w1, w3                     // w1<- vCC (requested index)
4143    cbz     w0, common_errNullObject    // bail if null
4144    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
4145    .if !0
4146    add     x0, x0, w1, uxtw #1    // w0<- arrayObj + index*width
4147    .endif
4148    cmp     w1, w3                      // compare unsigned index, length
4149    bcs     common_errArrayIndex        // index >= length, bail
4150    .if 0
4151    EXPORT_PC                           // Export PC before overwriting it.
4152    .endif
4153    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
4154    .if 0
4155    GET_VREG_WIDE x2, w9                // x2<- vAA
4156    .else
4157    GET_VREG w2, w9                     // w2<- vAA
4158    .endif
4159    .if 0
4160    strh  x2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
4161    .elseif 0
4162    bl art_quick_aput_obj
4163    .else
4164    strh  w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
4165    .endif
4166    GET_INST_OPCODE ip                  // extract opcode from rINST
4167    GOTO_OPCODE ip                      // jump to next instruction
4168
4169    NAME_END nterp_op_aput_char
4170    // Advance to the end of this handler. Causes error if we are past that point.
4171    .org nterp_op_aput_char + NTERP_HANDLER_SIZE  // op_aput_char handler is too big!
4172
4173/* ------------------------------ */
4174    .balign NTERP_HANDLER_SIZE
4175.L_op_aput_short: /* 0x51 */
4176    NAME_START nterp_op_aput_short
4177    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4178    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4179
4180/*
4181 * Array put.  vBB[vCC] <- vAA.
4182 *
4183 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
4184 *
4185 */
4186    FETCH_B w2, 1, 0                    // w2<- BB
4187    lsr     w9, wINST, #8               // w9<- AA
4188    FETCH_B w3, 1, 1                    // w3<- CC
4189    GET_VREG w0, w2                     // w0<- vBB (array object)
4190    GET_VREG w1, w3                     // w1<- vCC (requested index)
4191    cbz     w0, common_errNullObject    // bail if null
4192    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
4193    .if !0
4194    add     x0, x0, w1, uxtw #1    // w0<- arrayObj + index*width
4195    .endif
4196    cmp     w1, w3                      // compare unsigned index, length
4197    bcs     common_errArrayIndex        // index >= length, bail
4198    .if 0
4199    EXPORT_PC                           // Export PC before overwriting it.
4200    .endif
4201    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
4202    .if 0
4203    GET_VREG_WIDE x2, w9                // x2<- vAA
4204    .else
4205    GET_VREG w2, w9                     // w2<- vAA
4206    .endif
4207    .if 0
4208    strh  x2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- x2
4209    .elseif 0
4210    bl art_quick_aput_obj
4211    .else
4212    strh  w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET]     // vBB[vCC]<- w2
4213    .endif
4214    GET_INST_OPCODE ip                  // extract opcode from rINST
4215    GOTO_OPCODE ip                      // jump to next instruction
4216
4217    NAME_END nterp_op_aput_short
4218    // Advance to the end of this handler. Causes error if we are past that point.
4219    .org nterp_op_aput_short + NTERP_HANDLER_SIZE  // op_aput_short handler is too big!
4220
4221/* ------------------------------ */
4222    .balign NTERP_HANDLER_SIZE
4223.L_op_iget: /* 0x52 */
4224    NAME_START nterp_op_iget
4225    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4226    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4227
4228   // Fast-path which gets the field from thread-local cache.
4229   // Fetch some information from the thread cache.
4230   // Uses ip and ip2 as temporaries.
4231   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4232   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4233   add      ip, ip, ip2, lsl #4            // entry address within the cache
4234   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4235   cmp      ip, xPC
4236   b.ne     nterp_op_iget_slow_path
4237
4238.Lop_iget_resume:
4239   lsr     w2, wINST, #12              // w2<- B
4240   GET_VREG w3, w2                     // w3<- object we're operating on
4241   ubfx    w2, wINST, #8, #4           // w2<- A
4242   cbz     w3, common_errNullObject    // object was null
4243   .if 0
4244   ldr   x0, [x3, x0]
4245   SET_VREG_WIDE x0, w2                // fp[A] <- value
4246   .elseif 0
4247   ldr   w0, [x3, x0]
4248   UNPOISON_HEAP_REF w0
4249   TEST_IF_MARKING .Lop_iget_read_barrier
4250.Lop_iget_resume_after_read_barrier:
4251   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4252   .else
4253   ldr   w0, [x3, x0]
4254   SET_VREG w0, w2                     // fp[A] <- value
4255   .endif
4256   FETCH_ADVANCE_INST 2
4257   GET_INST_OPCODE ip
4258   GOTO_OPCODE ip
4259   .if 0
4260.Lop_iget_read_barrier:
4261   bl      art_quick_read_barrier_mark_reg00
4262   b       .Lop_iget_resume_after_read_barrier
4263   .endif
4264
4265    NAME_END nterp_op_iget
4266    // Advance to the end of this handler. Causes error if we are past that point.
4267    .org nterp_op_iget + NTERP_HANDLER_SIZE  // op_iget handler is too big!
4268
4269/* ------------------------------ */
4270    .balign NTERP_HANDLER_SIZE
4271.L_op_iget_wide: /* 0x53 */
4272    NAME_START nterp_op_iget_wide
4273    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4274    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4275
4276   // Fast-path which gets the field from thread-local cache.
4277   // Fetch some information from the thread cache.
4278   // Uses ip and ip2 as temporaries.
4279   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4280   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4281   add      ip, ip, ip2, lsl #4            // entry address within the cache
4282   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4283   cmp      ip, xPC
4284   b.ne     nterp_op_iget_wide_slow_path
4285
4286.Lop_iget_wide_resume:
4287   lsr     w2, wINST, #12              // w2<- B
4288   GET_VREG w3, w2                     // w3<- object we're operating on
4289   ubfx    w2, wINST, #8, #4           // w2<- A
4290   cbz     w3, common_errNullObject    // object was null
4291   .if 1
4292   ldr   x0, [x3, x0]
4293   SET_VREG_WIDE x0, w2                // fp[A] <- value
4294   .elseif 0
4295   ldr   w0, [x3, x0]
4296   UNPOISON_HEAP_REF w0
4297   TEST_IF_MARKING .Lop_iget_wide_read_barrier
4298.Lop_iget_wide_resume_after_read_barrier:
4299   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4300   .else
4301   ldr   w0, [x3, x0]
4302   SET_VREG w0, w2                     // fp[A] <- value
4303   .endif
4304   FETCH_ADVANCE_INST 2
4305   GET_INST_OPCODE ip
4306   GOTO_OPCODE ip
4307   .if 0
4308.Lop_iget_wide_read_barrier:
4309   bl      art_quick_read_barrier_mark_reg00
4310   b       .Lop_iget_wide_resume_after_read_barrier
4311   .endif
4312
4313    NAME_END nterp_op_iget_wide
4314    // Advance to the end of this handler. Causes error if we are past that point.
4315    .org nterp_op_iget_wide + NTERP_HANDLER_SIZE  // op_iget_wide handler is too big!
4316
4317/* ------------------------------ */
4318    .balign NTERP_HANDLER_SIZE
4319.L_op_iget_object: /* 0x54 */
4320    NAME_START nterp_op_iget_object
4321    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4322    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4323
4324   // Fast-path which gets the field from thread-local cache.
4325   // Fetch some information from the thread cache.
4326   // Uses ip and ip2 as temporaries.
4327   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4328   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4329   add      ip, ip, ip2, lsl #4            // entry address within the cache
4330   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4331   cmp      ip, xPC
4332   b.ne     nterp_op_iget_object_slow_path
4333
4334.Lop_iget_object_resume:
4335   lsr     w2, wINST, #12              // w2<- B
4336   GET_VREG w3, w2                     // w3<- object we're operating on
4337   ubfx    w2, wINST, #8, #4           // w2<- A
4338   cbz     w3, common_errNullObject    // object was null
4339   .if 0
4340   ldr   x0, [x3, x0]
4341   SET_VREG_WIDE x0, w2                // fp[A] <- value
4342   .elseif 1
4343   ldr   w0, [x3, x0]
4344   UNPOISON_HEAP_REF w0
4345   TEST_IF_MARKING .Lop_iget_object_read_barrier
4346.Lop_iget_object_resume_after_read_barrier:
4347   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4348   .else
4349   ldr   w0, [x3, x0]
4350   SET_VREG w0, w2                     // fp[A] <- value
4351   .endif
4352   FETCH_ADVANCE_INST 2
4353   GET_INST_OPCODE ip
4354   GOTO_OPCODE ip
4355   .if 1
4356.Lop_iget_object_read_barrier:
4357   bl      art_quick_read_barrier_mark_reg00
4358   b       .Lop_iget_object_resume_after_read_barrier
4359   .endif
4360
4361    NAME_END nterp_op_iget_object
4362    // Advance to the end of this handler. Causes error if we are past that point.
4363    .org nterp_op_iget_object + NTERP_HANDLER_SIZE  // op_iget_object handler is too big!
4364
4365/* ------------------------------ */
4366    .balign NTERP_HANDLER_SIZE
4367.L_op_iget_boolean: /* 0x55 */
4368    NAME_START nterp_op_iget_boolean
4369    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4370    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4371
4372   // Fast-path which gets the field from thread-local cache.
4373   // Fetch some information from the thread cache.
4374   // Uses ip and ip2 as temporaries.
4375   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4376   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4377   add      ip, ip, ip2, lsl #4            // entry address within the cache
4378   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4379   cmp      ip, xPC
4380   b.ne     nterp_op_iget_boolean_slow_path
4381
4382.Lop_iget_boolean_resume:
4383   lsr     w2, wINST, #12              // w2<- B
4384   GET_VREG w3, w2                     // w3<- object we're operating on
4385   ubfx    w2, wINST, #8, #4           // w2<- A
4386   cbz     w3, common_errNullObject    // object was null
4387   .if 0
4388   ldrb   x0, [x3, x0]
4389   SET_VREG_WIDE x0, w2                // fp[A] <- value
4390   .elseif 0
4391   ldrb   w0, [x3, x0]
4392   UNPOISON_HEAP_REF w0
4393   TEST_IF_MARKING .Lop_iget_boolean_read_barrier
4394.Lop_iget_boolean_resume_after_read_barrier:
4395   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4396   .else
4397   ldrb   w0, [x3, x0]
4398   SET_VREG w0, w2                     // fp[A] <- value
4399   .endif
4400   FETCH_ADVANCE_INST 2
4401   GET_INST_OPCODE ip
4402   GOTO_OPCODE ip
4403   .if 0
4404.Lop_iget_boolean_read_barrier:
4405   bl      art_quick_read_barrier_mark_reg00
4406   b       .Lop_iget_boolean_resume_after_read_barrier
4407   .endif
4408
4409    NAME_END nterp_op_iget_boolean
4410    // Advance to the end of this handler. Causes error if we are past that point.
4411    .org nterp_op_iget_boolean + NTERP_HANDLER_SIZE  // op_iget_boolean handler is too big!
4412
4413/* ------------------------------ */
4414    .balign NTERP_HANDLER_SIZE
4415.L_op_iget_byte: /* 0x56 */
4416    NAME_START nterp_op_iget_byte
4417    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4418    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4419
4420   // Fast-path which gets the field from thread-local cache.
4421   // Fetch some information from the thread cache.
4422   // Uses ip and ip2 as temporaries.
4423   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4424   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4425   add      ip, ip, ip2, lsl #4            // entry address within the cache
4426   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4427   cmp      ip, xPC
4428   b.ne     nterp_op_iget_byte_slow_path
4429
4430.Lop_iget_byte_resume:
4431   lsr     w2, wINST, #12              // w2<- B
4432   GET_VREG w3, w2                     // w3<- object we're operating on
4433   ubfx    w2, wINST, #8, #4           // w2<- A
4434   cbz     w3, common_errNullObject    // object was null
4435   .if 0
4436   ldrsb   x0, [x3, x0]
4437   SET_VREG_WIDE x0, w2                // fp[A] <- value
4438   .elseif 0
4439   ldrsb   w0, [x3, x0]
4440   UNPOISON_HEAP_REF w0
4441   TEST_IF_MARKING .Lop_iget_byte_read_barrier
4442.Lop_iget_byte_resume_after_read_barrier:
4443   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4444   .else
4445   ldrsb   w0, [x3, x0]
4446   SET_VREG w0, w2                     // fp[A] <- value
4447   .endif
4448   FETCH_ADVANCE_INST 2
4449   GET_INST_OPCODE ip
4450   GOTO_OPCODE ip
4451   .if 0
4452.Lop_iget_byte_read_barrier:
4453   bl      art_quick_read_barrier_mark_reg00
4454   b       .Lop_iget_byte_resume_after_read_barrier
4455   .endif
4456
4457    NAME_END nterp_op_iget_byte
4458    // Advance to the end of this handler. Causes error if we are past that point.
4459    .org nterp_op_iget_byte + NTERP_HANDLER_SIZE  // op_iget_byte handler is too big!
4460
4461/* ------------------------------ */
4462    .balign NTERP_HANDLER_SIZE
4463.L_op_iget_char: /* 0x57 */
4464    NAME_START nterp_op_iget_char
4465    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4466    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4467
4468   // Fast-path which gets the field from thread-local cache.
4469   // Fetch some information from the thread cache.
4470   // Uses ip and ip2 as temporaries.
4471   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4472   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4473   add      ip, ip, ip2, lsl #4            // entry address within the cache
4474   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4475   cmp      ip, xPC
4476   b.ne     nterp_op_iget_char_slow_path
4477
4478.Lop_iget_char_resume:
4479   lsr     w2, wINST, #12              // w2<- B
4480   GET_VREG w3, w2                     // w3<- object we're operating on
4481   ubfx    w2, wINST, #8, #4           // w2<- A
4482   cbz     w3, common_errNullObject    // object was null
4483   .if 0
4484   ldrh   x0, [x3, x0]
4485   SET_VREG_WIDE x0, w2                // fp[A] <- value
4486   .elseif 0
4487   ldrh   w0, [x3, x0]
4488   UNPOISON_HEAP_REF w0
4489   TEST_IF_MARKING .Lop_iget_char_read_barrier
4490.Lop_iget_char_resume_after_read_barrier:
4491   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4492   .else
4493   ldrh   w0, [x3, x0]
4494   SET_VREG w0, w2                     // fp[A] <- value
4495   .endif
4496   FETCH_ADVANCE_INST 2
4497   GET_INST_OPCODE ip
4498   GOTO_OPCODE ip
4499   .if 0
4500.Lop_iget_char_read_barrier:
4501   bl      art_quick_read_barrier_mark_reg00
4502   b       .Lop_iget_char_resume_after_read_barrier
4503   .endif
4504
4505    NAME_END nterp_op_iget_char
4506    // Advance to the end of this handler. Causes error if we are past that point.
4507    .org nterp_op_iget_char + NTERP_HANDLER_SIZE  // op_iget_char handler is too big!
4508
4509/* ------------------------------ */
4510    .balign NTERP_HANDLER_SIZE
4511.L_op_iget_short: /* 0x58 */
4512    NAME_START nterp_op_iget_short
4513    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4514    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4515
4516   // Fast-path which gets the field from thread-local cache.
4517   // Fetch some information from the thread cache.
4518   // Uses ip and ip2 as temporaries.
4519   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4520   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4521   add      ip, ip, ip2, lsl #4            // entry address within the cache
4522   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4523   cmp      ip, xPC
4524   b.ne     nterp_op_iget_short_slow_path
4525
4526.Lop_iget_short_resume:
4527   lsr     w2, wINST, #12              // w2<- B
4528   GET_VREG w3, w2                     // w3<- object we're operating on
4529   ubfx    w2, wINST, #8, #4           // w2<- A
4530   cbz     w3, common_errNullObject    // object was null
4531   .if 0
4532   ldrsh   x0, [x3, x0]
4533   SET_VREG_WIDE x0, w2                // fp[A] <- value
4534   .elseif 0
4535   ldrsh   w0, [x3, x0]
4536   UNPOISON_HEAP_REF w0
4537   TEST_IF_MARKING .Lop_iget_short_read_barrier
4538.Lop_iget_short_resume_after_read_barrier:
4539   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4540   .else
4541   ldrsh   w0, [x3, x0]
4542   SET_VREG w0, w2                     // fp[A] <- value
4543   .endif
4544   FETCH_ADVANCE_INST 2
4545   GET_INST_OPCODE ip
4546   GOTO_OPCODE ip
4547   .if 0
4548.Lop_iget_short_read_barrier:
4549   bl      art_quick_read_barrier_mark_reg00
4550   b       .Lop_iget_short_resume_after_read_barrier
4551   .endif
4552
4553    NAME_END nterp_op_iget_short
4554    // Advance to the end of this handler. Causes error if we are past that point.
4555    .org nterp_op_iget_short + NTERP_HANDLER_SIZE  // op_iget_short handler is too big!
4556
4557/* ------------------------------ */
4558    .balign NTERP_HANDLER_SIZE
4559.L_op_iput: /* 0x59 */
4560    NAME_START nterp_op_iput
4561    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4562    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4563
4564   ubfx    w1, wINST, #8, #4           // w1<- A
4565   .if 0
4566   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4567   .else
4568   GET_VREG w26, w1                    // w26 <- v[A]
4569   .endif
4570   // Fast-path which gets the field from thread-local cache.
4571   // Fetch some information from the thread cache.
4572   // Uses ip and ip2 as temporaries.
4573   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4574   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4575   add      ip, ip, ip2, lsl #4            // entry address within the cache
4576   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4577   cmp      ip, xPC
4578   b.ne     nterp_op_iput_slow_path
4579
4580.Lop_iput_resume:
4581   lsr     w2, wINST, #12              // w2<- B
4582   GET_VREG w2, w2                     // vB (object we're operating on)
4583   cbz w2, common_errNullObject
4584   .if 0
4585   str  x26, [x2, x0]
4586   .else
4587   POISON_HEAP_REF_IF_OBJECT 0, w26
4588   str  w26, [x2, x0]
4589   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_skip_write_barrier
4590   .endif
4591   FETCH_ADVANCE_INST 2
4592   GET_INST_OPCODE ip
4593   GOTO_OPCODE ip
4594
4595    NAME_END nterp_op_iput
4596    // Advance to the end of this handler. Causes error if we are past that point.
4597    .org nterp_op_iput + NTERP_HANDLER_SIZE  // op_iput handler is too big!
4598
4599/* ------------------------------ */
4600    .balign NTERP_HANDLER_SIZE
4601.L_op_iput_wide: /* 0x5a */
4602    NAME_START nterp_op_iput_wide
4603    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4604    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4605
4606   ubfx    w1, wINST, #8, #4           // w1<- A
4607   .if 1
4608   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4609   .else
4610   GET_VREG w26, w1                    // w26 <- v[A]
4611   .endif
4612   // Fast-path which gets the field from thread-local cache.
4613   // Fetch some information from the thread cache.
4614   // Uses ip and ip2 as temporaries.
4615   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4616   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4617   add      ip, ip, ip2, lsl #4            // entry address within the cache
4618   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4619   cmp      ip, xPC
4620   b.ne     nterp_op_iput_wide_slow_path
4621
4622.Lop_iput_wide_resume:
4623   lsr     w2, wINST, #12              // w2<- B
4624   GET_VREG w2, w2                     // vB (object we're operating on)
4625   cbz w2, common_errNullObject
4626   .if 1
4627   str  x26, [x2, x0]
4628   .else
4629   POISON_HEAP_REF_IF_OBJECT 0, w26
4630   str  w26, [x2, x0]
4631   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_wide_skip_write_barrier
4632   .endif
4633   FETCH_ADVANCE_INST 2
4634   GET_INST_OPCODE ip
4635   GOTO_OPCODE ip
4636
4637    NAME_END nterp_op_iput_wide
4638    // Advance to the end of this handler. Causes error if we are past that point.
4639    .org nterp_op_iput_wide + NTERP_HANDLER_SIZE  // op_iput_wide handler is too big!
4640
4641/* ------------------------------ */
4642    .balign NTERP_HANDLER_SIZE
4643.L_op_iput_object: /* 0x5b */
4644    NAME_START nterp_op_iput_object
4645    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4646    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4647
4648   ubfx    w1, wINST, #8, #4           // w1<- A
4649   .if 0
4650   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4651   .else
4652   GET_VREG w26, w1                    // w26 <- v[A]
4653   .endif
4654   // Fast-path which gets the field from thread-local cache.
4655   // Fetch some information from the thread cache.
4656   // Uses ip and ip2 as temporaries.
4657   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4658   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4659   add      ip, ip, ip2, lsl #4            // entry address within the cache
4660   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4661   cmp      ip, xPC
4662   b.ne     nterp_op_iput_object_slow_path
4663
4664.Lop_iput_object_resume:
4665   lsr     w2, wINST, #12              // w2<- B
4666   GET_VREG w2, w2                     // vB (object we're operating on)
4667   cbz w2, common_errNullObject
4668   .if 0
4669   str  x26, [x2, x0]
4670   .else
4671   POISON_HEAP_REF_IF_OBJECT 1, w26
4672   str  w26, [x2, x0]
4673   WRITE_BARRIER_IF_OBJECT 1, w26, w2, .Lop_iput_object_skip_write_barrier
4674   .endif
4675   FETCH_ADVANCE_INST 2
4676   GET_INST_OPCODE ip
4677   GOTO_OPCODE ip
4678
4679    NAME_END nterp_op_iput_object
4680    // Advance to the end of this handler. Causes error if we are past that point.
4681    .org nterp_op_iput_object + NTERP_HANDLER_SIZE  // op_iput_object handler is too big!
4682
4683/* ------------------------------ */
4684    .balign NTERP_HANDLER_SIZE
4685.L_op_iput_boolean: /* 0x5c */
4686    NAME_START nterp_op_iput_boolean
4687    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4688    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4689
4690   ubfx    w1, wINST, #8, #4           // w1<- A
4691   .if 0
4692   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4693   .else
4694   GET_VREG w26, w1                    // w26 <- v[A]
4695   .endif
4696   // Fast-path which gets the field from thread-local cache.
4697   // Fetch some information from the thread cache.
4698   // Uses ip and ip2 as temporaries.
4699   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4700   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4701   add      ip, ip, ip2, lsl #4            // entry address within the cache
4702   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4703   cmp      ip, xPC
4704   b.ne     nterp_op_iput_boolean_slow_path
4705
4706.Lop_iput_boolean_resume:
4707   lsr     w2, wINST, #12              // w2<- B
4708   GET_VREG w2, w2                     // vB (object we're operating on)
4709   cbz w2, common_errNullObject
4710   .if 0
4711   strb  x26, [x2, x0]
4712   .else
4713   POISON_HEAP_REF_IF_OBJECT 0, w26
4714   strb  w26, [x2, x0]
4715   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_boolean_skip_write_barrier
4716   .endif
4717   FETCH_ADVANCE_INST 2
4718   GET_INST_OPCODE ip
4719   GOTO_OPCODE ip
4720
4721    NAME_END nterp_op_iput_boolean
4722    // Advance to the end of this handler. Causes error if we are past that point.
4723    .org nterp_op_iput_boolean + NTERP_HANDLER_SIZE  // op_iput_boolean handler is too big!
4724
4725/* ------------------------------ */
4726    .balign NTERP_HANDLER_SIZE
4727.L_op_iput_byte: /* 0x5d */
4728    NAME_START nterp_op_iput_byte
4729    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4730    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4731
4732   ubfx    w1, wINST, #8, #4           // w1<- A
4733   .if 0
4734   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4735   .else
4736   GET_VREG w26, w1                    // w26 <- v[A]
4737   .endif
4738   // Fast-path which gets the field from thread-local cache.
4739   // Fetch some information from the thread cache.
4740   // Uses ip and ip2 as temporaries.
4741   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4742   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4743   add      ip, ip, ip2, lsl #4            // entry address within the cache
4744   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4745   cmp      ip, xPC
4746   b.ne     nterp_op_iput_byte_slow_path
4747
4748.Lop_iput_byte_resume:
4749   lsr     w2, wINST, #12              // w2<- B
4750   GET_VREG w2, w2                     // vB (object we're operating on)
4751   cbz w2, common_errNullObject
4752   .if 0
4753   strb  x26, [x2, x0]
4754   .else
4755   POISON_HEAP_REF_IF_OBJECT 0, w26
4756   strb  w26, [x2, x0]
4757   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_byte_skip_write_barrier
4758   .endif
4759   FETCH_ADVANCE_INST 2
4760   GET_INST_OPCODE ip
4761   GOTO_OPCODE ip
4762
4763    NAME_END nterp_op_iput_byte
4764    // Advance to the end of this handler. Causes error if we are past that point.
4765    .org nterp_op_iput_byte + NTERP_HANDLER_SIZE  // op_iput_byte handler is too big!
4766
4767/* ------------------------------ */
4768    .balign NTERP_HANDLER_SIZE
4769.L_op_iput_char: /* 0x5e */
4770    NAME_START nterp_op_iput_char
4771    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4772    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4773
4774   ubfx    w1, wINST, #8, #4           // w1<- A
4775   .if 0
4776   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4777   .else
4778   GET_VREG w26, w1                    // w26 <- v[A]
4779   .endif
4780   // Fast-path which gets the field from thread-local cache.
4781   // Fetch some information from the thread cache.
4782   // Uses ip and ip2 as temporaries.
4783   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4784   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4785   add      ip, ip, ip2, lsl #4            // entry address within the cache
4786   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4787   cmp      ip, xPC
4788   b.ne     nterp_op_iput_char_slow_path
4789
4790.Lop_iput_char_resume:
4791   lsr     w2, wINST, #12              // w2<- B
4792   GET_VREG w2, w2                     // vB (object we're operating on)
4793   cbz w2, common_errNullObject
4794   .if 0
4795   strh  x26, [x2, x0]
4796   .else
4797   POISON_HEAP_REF_IF_OBJECT 0, w26
4798   strh  w26, [x2, x0]
4799   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_char_skip_write_barrier
4800   .endif
4801   FETCH_ADVANCE_INST 2
4802   GET_INST_OPCODE ip
4803   GOTO_OPCODE ip
4804
4805    NAME_END nterp_op_iput_char
4806    // Advance to the end of this handler. Causes error if we are past that point.
4807    .org nterp_op_iput_char + NTERP_HANDLER_SIZE  // op_iput_char handler is too big!
4808
4809/* ------------------------------ */
4810    .balign NTERP_HANDLER_SIZE
4811.L_op_iput_short: /* 0x5f */
4812    NAME_START nterp_op_iput_short
4813    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4814    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4815
4816   ubfx    w1, wINST, #8, #4           // w1<- A
4817   .if 0
4818   GET_VREG_WIDE x26, w1               // x26<- fp[A]/fp[A+1]
4819   .else
4820   GET_VREG w26, w1                    // w26 <- v[A]
4821   .endif
4822   // Fast-path which gets the field from thread-local cache.
4823   // Fetch some information from the thread cache.
4824   // Uses ip and ip2 as temporaries.
4825   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4826   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4827   add      ip, ip, ip2, lsl #4            // entry address within the cache
4828   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4829   cmp      ip, xPC
4830   b.ne     nterp_op_iput_short_slow_path
4831
4832.Lop_iput_short_resume:
4833   lsr     w2, wINST, #12              // w2<- B
4834   GET_VREG w2, w2                     // vB (object we're operating on)
4835   cbz w2, common_errNullObject
4836   .if 0
4837   strh  x26, [x2, x0]
4838   .else
4839   POISON_HEAP_REF_IF_OBJECT 0, w26
4840   strh  w26, [x2, x0]
4841   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_short_skip_write_barrier
4842   .endif
4843   FETCH_ADVANCE_INST 2
4844   GET_INST_OPCODE ip
4845   GOTO_OPCODE ip
4846
4847    NAME_END nterp_op_iput_short
4848    // Advance to the end of this handler. Causes error if we are past that point.
4849    .org nterp_op_iput_short + NTERP_HANDLER_SIZE  // op_iput_short handler is too big!
4850
4851/* ------------------------------ */
4852    .balign NTERP_HANDLER_SIZE
4853.L_op_sget: /* 0x60 */
4854    NAME_START nterp_op_sget
4855    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4856    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4857
4858   // Fast-path which gets the field from thread-local cache.
4859   // Fetch some information from the thread cache.
4860   // Uses ip and ip2 as temporaries.
4861   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4862   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4863   add      ip, ip, ip2, lsl #4            // entry address within the cache
4864   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4865   cmp      ip, xPC
4866   b.ne     nterp_op_sget_slow_path
4867
4868.Lop_sget_resume:
4869   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
4870   lsr     w2, wINST, #8               // w2 <- A
4871   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
4872   TEST_IF_MARKING .Lop_sget_read_barrier
4873.Lop_sget_resume_after_read_barrier:
4874   .if 0
4875   ldr     x0, [x0, x1]
4876   SET_VREG_WIDE x0, w2                // fp[A] <- value
4877   .elseif 0
4878   ldr   w0, [x0, x1]
4879   UNPOISON_HEAP_REF w0
4880   // No need to check the marking register, we know it's not set here.
4881.Lop_sget_after_reference_load:
4882   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4883   .else
4884   ldr   w0, [x0, x1]
4885   SET_VREG w0, w2                     // fp[A] <- value
4886   .endif
4887   FETCH_ADVANCE_INST 2
4888   GET_INST_OPCODE ip
4889   GOTO_OPCODE ip
4890.Lop_sget_read_barrier:
4891   bl      art_quick_read_barrier_mark_reg00
4892   .if 0
4893   ldr   w0, [x0, x1]
4894   UNPOISON_HEAP_REF w0
4895.Lop_sget_mark_after_load:
4896   // Here, we know the marking register is set.
4897   bl      art_quick_read_barrier_mark_reg00
4898   b       .Lop_sget_after_reference_load
4899   .else
4900   b       .Lop_sget_resume_after_read_barrier
4901   .endif
4902
4903    NAME_END nterp_op_sget
4904    // Advance to the end of this handler. Causes error if we are past that point.
4905    .org nterp_op_sget + NTERP_HANDLER_SIZE  // op_sget handler is too big!
4906
4907/* ------------------------------ */
4908    .balign NTERP_HANDLER_SIZE
4909.L_op_sget_wide: /* 0x61 */
4910    NAME_START nterp_op_sget_wide
4911    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4912    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4913
4914   // Fast-path which gets the field from thread-local cache.
4915   // Fetch some information from the thread cache.
4916   // Uses ip and ip2 as temporaries.
4917   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4918   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4919   add      ip, ip, ip2, lsl #4            // entry address within the cache
4920   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4921   cmp      ip, xPC
4922   b.ne     nterp_op_sget_wide_slow_path
4923
4924.Lop_sget_wide_resume:
4925   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
4926   lsr     w2, wINST, #8               // w2 <- A
4927   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
4928   TEST_IF_MARKING .Lop_sget_wide_read_barrier
4929.Lop_sget_wide_resume_after_read_barrier:
4930   .if 1
4931   ldr     x0, [x0, x1]
4932   SET_VREG_WIDE x0, w2                // fp[A] <- value
4933   .elseif 0
4934   ldr   w0, [x0, x1]
4935   UNPOISON_HEAP_REF w0
4936   // No need to check the marking register, we know it's not set here.
4937.Lop_sget_wide_after_reference_load:
4938   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4939   .else
4940   ldr   w0, [x0, x1]
4941   SET_VREG w0, w2                     // fp[A] <- value
4942   .endif
4943   FETCH_ADVANCE_INST 2
4944   GET_INST_OPCODE ip
4945   GOTO_OPCODE ip
4946.Lop_sget_wide_read_barrier:
4947   bl      art_quick_read_barrier_mark_reg00
4948   .if 0
4949   ldr   w0, [x0, x1]
4950   UNPOISON_HEAP_REF w0
4951.Lop_sget_wide_mark_after_load:
4952   // Here, we know the marking register is set.
4953   bl      art_quick_read_barrier_mark_reg00
4954   b       .Lop_sget_wide_after_reference_load
4955   .else
4956   b       .Lop_sget_wide_resume_after_read_barrier
4957   .endif
4958
4959    NAME_END nterp_op_sget_wide
4960    // Advance to the end of this handler. Causes error if we are past that point.
4961    .org nterp_op_sget_wide + NTERP_HANDLER_SIZE  // op_sget_wide handler is too big!
4962
4963/* ------------------------------ */
4964    .balign NTERP_HANDLER_SIZE
4965.L_op_sget_object: /* 0x62 */
4966    NAME_START nterp_op_sget_object
4967    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
4968    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
4969
4970   // Fast-path which gets the field from thread-local cache.
4971   // Fetch some information from the thread cache.
4972   // Uses ip and ip2 as temporaries.
4973   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
4974   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
4975   add      ip, ip, ip2, lsl #4            // entry address within the cache
4976   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
4977   cmp      ip, xPC
4978   b.ne     nterp_op_sget_object_slow_path
4979
4980.Lop_sget_object_resume:
4981   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
4982   lsr     w2, wINST, #8               // w2 <- A
4983   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
4984   TEST_IF_MARKING .Lop_sget_object_read_barrier
4985.Lop_sget_object_resume_after_read_barrier:
4986   .if 0
4987   ldr     x0, [x0, x1]
4988   SET_VREG_WIDE x0, w2                // fp[A] <- value
4989   .elseif 1
4990   ldr   w0, [x0, x1]
4991   UNPOISON_HEAP_REF w0
4992   // No need to check the marking register, we know it's not set here.
4993.Lop_sget_object_after_reference_load:
4994   SET_VREG_OBJECT w0, w2              // fp[A] <- value
4995   .else
4996   ldr   w0, [x0, x1]
4997   SET_VREG w0, w2                     // fp[A] <- value
4998   .endif
4999   FETCH_ADVANCE_INST 2
5000   GET_INST_OPCODE ip
5001   GOTO_OPCODE ip
5002.Lop_sget_object_read_barrier:
5003   bl      art_quick_read_barrier_mark_reg00
5004   .if 1
5005   ldr   w0, [x0, x1]
5006   UNPOISON_HEAP_REF w0
5007.Lop_sget_object_mark_after_load:
5008   // Here, we know the marking register is set.
5009   bl      art_quick_read_barrier_mark_reg00
5010   b       .Lop_sget_object_after_reference_load
5011   .else
5012   b       .Lop_sget_object_resume_after_read_barrier
5013   .endif
5014
5015    NAME_END nterp_op_sget_object
5016    // Advance to the end of this handler. Causes error if we are past that point.
5017    .org nterp_op_sget_object + NTERP_HANDLER_SIZE  // op_sget_object handler is too big!
5018
5019/* ------------------------------ */
5020    .balign NTERP_HANDLER_SIZE
5021.L_op_sget_boolean: /* 0x63 */
5022    NAME_START nterp_op_sget_boolean
5023    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5024    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5025
5026   // Fast-path which gets the field from thread-local cache.
5027   // Fetch some information from the thread cache.
5028   // Uses ip and ip2 as temporaries.
5029   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5030   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5031   add      ip, ip, ip2, lsl #4            // entry address within the cache
5032   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5033   cmp      ip, xPC
5034   b.ne     nterp_op_sget_boolean_slow_path
5035
5036.Lop_sget_boolean_resume:
5037   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5038   lsr     w2, wINST, #8               // w2 <- A
5039   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5040   TEST_IF_MARKING .Lop_sget_boolean_read_barrier
5041.Lop_sget_boolean_resume_after_read_barrier:
5042   .if 0
5043   ldr     x0, [x0, x1]
5044   SET_VREG_WIDE x0, w2                // fp[A] <- value
5045   .elseif 0
5046   ldrb   w0, [x0, x1]
5047   UNPOISON_HEAP_REF w0
5048   // No need to check the marking register, we know it's not set here.
5049.Lop_sget_boolean_after_reference_load:
5050   SET_VREG_OBJECT w0, w2              // fp[A] <- value
5051   .else
5052   ldrb   w0, [x0, x1]
5053   SET_VREG w0, w2                     // fp[A] <- value
5054   .endif
5055   FETCH_ADVANCE_INST 2
5056   GET_INST_OPCODE ip
5057   GOTO_OPCODE ip
5058.Lop_sget_boolean_read_barrier:
5059   bl      art_quick_read_barrier_mark_reg00
5060   .if 0
5061   ldrb   w0, [x0, x1]
5062   UNPOISON_HEAP_REF w0
5063.Lop_sget_boolean_mark_after_load:
5064   // Here, we know the marking register is set.
5065   bl      art_quick_read_barrier_mark_reg00
5066   b       .Lop_sget_boolean_after_reference_load
5067   .else
5068   b       .Lop_sget_boolean_resume_after_read_barrier
5069   .endif
5070
5071    NAME_END nterp_op_sget_boolean
5072    // Advance to the end of this handler. Causes error if we are past that point.
5073    .org nterp_op_sget_boolean + NTERP_HANDLER_SIZE  // op_sget_boolean handler is too big!
5074
5075/* ------------------------------ */
5076    .balign NTERP_HANDLER_SIZE
5077.L_op_sget_byte: /* 0x64 */
5078    NAME_START nterp_op_sget_byte
5079    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5080    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5081
5082   // Fast-path which gets the field from thread-local cache.
5083   // Fetch some information from the thread cache.
5084   // Uses ip and ip2 as temporaries.
5085   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5086   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5087   add      ip, ip, ip2, lsl #4            // entry address within the cache
5088   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5089   cmp      ip, xPC
5090   b.ne     nterp_op_sget_byte_slow_path
5091
5092.Lop_sget_byte_resume:
5093   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5094   lsr     w2, wINST, #8               // w2 <- A
5095   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5096   TEST_IF_MARKING .Lop_sget_byte_read_barrier
5097.Lop_sget_byte_resume_after_read_barrier:
5098   .if 0
5099   ldr     x0, [x0, x1]
5100   SET_VREG_WIDE x0, w2                // fp[A] <- value
5101   .elseif 0
5102   ldrsb   w0, [x0, x1]
5103   UNPOISON_HEAP_REF w0
5104   // No need to check the marking register, we know it's not set here.
5105.Lop_sget_byte_after_reference_load:
5106   SET_VREG_OBJECT w0, w2              // fp[A] <- value
5107   .else
5108   ldrsb   w0, [x0, x1]
5109   SET_VREG w0, w2                     // fp[A] <- value
5110   .endif
5111   FETCH_ADVANCE_INST 2
5112   GET_INST_OPCODE ip
5113   GOTO_OPCODE ip
5114.Lop_sget_byte_read_barrier:
5115   bl      art_quick_read_barrier_mark_reg00
5116   .if 0
5117   ldrsb   w0, [x0, x1]
5118   UNPOISON_HEAP_REF w0
5119.Lop_sget_byte_mark_after_load:
5120   // Here, we know the marking register is set.
5121   bl      art_quick_read_barrier_mark_reg00
5122   b       .Lop_sget_byte_after_reference_load
5123   .else
5124   b       .Lop_sget_byte_resume_after_read_barrier
5125   .endif
5126
5127    NAME_END nterp_op_sget_byte
5128    // Advance to the end of this handler. Causes error if we are past that point.
5129    .org nterp_op_sget_byte + NTERP_HANDLER_SIZE  // op_sget_byte handler is too big!
5130
5131/* ------------------------------ */
5132    .balign NTERP_HANDLER_SIZE
5133.L_op_sget_char: /* 0x65 */
5134    NAME_START nterp_op_sget_char
5135    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5136    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5137
5138   // Fast-path which gets the field from thread-local cache.
5139   // Fetch some information from the thread cache.
5140   // Uses ip and ip2 as temporaries.
5141   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5142   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5143   add      ip, ip, ip2, lsl #4            // entry address within the cache
5144   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5145   cmp      ip, xPC
5146   b.ne     nterp_op_sget_char_slow_path
5147
5148.Lop_sget_char_resume:
5149   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5150   lsr     w2, wINST, #8               // w2 <- A
5151   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5152   TEST_IF_MARKING .Lop_sget_char_read_barrier
5153.Lop_sget_char_resume_after_read_barrier:
5154   .if 0
5155   ldr     x0, [x0, x1]
5156   SET_VREG_WIDE x0, w2                // fp[A] <- value
5157   .elseif 0
5158   ldrh   w0, [x0, x1]
5159   UNPOISON_HEAP_REF w0
5160   // No need to check the marking register, we know it's not set here.
5161.Lop_sget_char_after_reference_load:
5162   SET_VREG_OBJECT w0, w2              // fp[A] <- value
5163   .else
5164   ldrh   w0, [x0, x1]
5165   SET_VREG w0, w2                     // fp[A] <- value
5166   .endif
5167   FETCH_ADVANCE_INST 2
5168   GET_INST_OPCODE ip
5169   GOTO_OPCODE ip
5170.Lop_sget_char_read_barrier:
5171   bl      art_quick_read_barrier_mark_reg00
5172   .if 0
5173   ldrh   w0, [x0, x1]
5174   UNPOISON_HEAP_REF w0
5175.Lop_sget_char_mark_after_load:
5176   // Here, we know the marking register is set.
5177   bl      art_quick_read_barrier_mark_reg00
5178   b       .Lop_sget_char_after_reference_load
5179   .else
5180   b       .Lop_sget_char_resume_after_read_barrier
5181   .endif
5182
5183    NAME_END nterp_op_sget_char
5184    // Advance to the end of this handler. Causes error if we are past that point.
5185    .org nterp_op_sget_char + NTERP_HANDLER_SIZE  // op_sget_char handler is too big!
5186
5187/* ------------------------------ */
5188    .balign NTERP_HANDLER_SIZE
5189.L_op_sget_short: /* 0x66 */
5190    NAME_START nterp_op_sget_short
5191    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5192    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5193
5194   // Fast-path which gets the field from thread-local cache.
5195   // Fetch some information from the thread cache.
5196   // Uses ip and ip2 as temporaries.
5197   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5198   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5199   add      ip, ip, ip2, lsl #4            // entry address within the cache
5200   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5201   cmp      ip, xPC
5202   b.ne     nterp_op_sget_short_slow_path
5203
5204.Lop_sget_short_resume:
5205   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5206   lsr     w2, wINST, #8               // w2 <- A
5207   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5208   TEST_IF_MARKING .Lop_sget_short_read_barrier
5209.Lop_sget_short_resume_after_read_barrier:
5210   .if 0
5211   ldr     x0, [x0, x1]
5212   SET_VREG_WIDE x0, w2                // fp[A] <- value
5213   .elseif 0
5214   ldrsh   w0, [x0, x1]
5215   UNPOISON_HEAP_REF w0
5216   // No need to check the marking register, we know it's not set here.
5217.Lop_sget_short_after_reference_load:
5218   SET_VREG_OBJECT w0, w2              // fp[A] <- value
5219   .else
5220   ldrsh   w0, [x0, x1]
5221   SET_VREG w0, w2                     // fp[A] <- value
5222   .endif
5223   FETCH_ADVANCE_INST 2
5224   GET_INST_OPCODE ip
5225   GOTO_OPCODE ip
5226.Lop_sget_short_read_barrier:
5227   bl      art_quick_read_barrier_mark_reg00
5228   .if 0
5229   ldrsh   w0, [x0, x1]
5230   UNPOISON_HEAP_REF w0
5231.Lop_sget_short_mark_after_load:
5232   // Here, we know the marking register is set.
5233   bl      art_quick_read_barrier_mark_reg00
5234   b       .Lop_sget_short_after_reference_load
5235   .else
5236   b       .Lop_sget_short_resume_after_read_barrier
5237   .endif
5238
5239    NAME_END nterp_op_sget_short
5240    // Advance to the end of this handler. Causes error if we are past that point.
5241    .org nterp_op_sget_short + NTERP_HANDLER_SIZE  // op_sget_short handler is too big!
5242
5243/* ------------------------------ */
5244    .balign NTERP_HANDLER_SIZE
5245.L_op_sput: /* 0x67 */
5246    NAME_START nterp_op_sput
5247    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5248    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5249
5250   lsr     w2, wINST, #8               // w2 <- A
5251   .if 0
5252   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5253   .else
5254   GET_VREG w26, w2                    // w26 <- v[A]
5255   .endif
5256   // Fast-path which gets the field from thread-local cache.
5257   // Fetch some information from the thread cache.
5258   // Uses ip and ip2 as temporaries.
5259   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5260   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5261   add      ip, ip, ip2, lsl #4            // entry address within the cache
5262   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5263   cmp      ip, xPC
5264   b.ne     nterp_op_sput_slow_path
5265
5266.Lop_sput_resume:
5267   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5268   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5269   TEST_IF_MARKING .Lop_sput_read_barrier
5270.Lop_sput_resume_after_read_barrier:
5271   .if 0
5272   str  x26, [x0, x1]
5273   .else
5274   POISON_HEAP_REF_IF_OBJECT 0, w26
5275   str  w26, [x0, x1]
5276   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_skip_write_barrier
5277   .endif
5278   FETCH_ADVANCE_INST 2
5279   GET_INST_OPCODE ip
5280   GOTO_OPCODE ip
5281.Lop_sput_read_barrier:
5282   bl      art_quick_read_barrier_mark_reg00
5283   b       .Lop_sput_resume_after_read_barrier
5284
5285    NAME_END nterp_op_sput
5286    // Advance to the end of this handler. Causes error if we are past that point.
5287    .org nterp_op_sput + NTERP_HANDLER_SIZE  // op_sput handler is too big!
5288
5289/* ------------------------------ */
5290    .balign NTERP_HANDLER_SIZE
5291.L_op_sput_wide: /* 0x68 */
5292    NAME_START nterp_op_sput_wide
5293    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5294    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5295
5296   lsr     w2, wINST, #8               // w2 <- A
5297   .if 1
5298   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5299   .else
5300   GET_VREG w26, w2                    // w26 <- v[A]
5301   .endif
5302   // Fast-path which gets the field from thread-local cache.
5303   // Fetch some information from the thread cache.
5304   // Uses ip and ip2 as temporaries.
5305   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5306   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5307   add      ip, ip, ip2, lsl #4            // entry address within the cache
5308   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5309   cmp      ip, xPC
5310   b.ne     nterp_op_sput_wide_slow_path
5311
5312.Lop_sput_wide_resume:
5313   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5314   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5315   TEST_IF_MARKING .Lop_sput_wide_read_barrier
5316.Lop_sput_wide_resume_after_read_barrier:
5317   .if 1
5318   str  x26, [x0, x1]
5319   .else
5320   POISON_HEAP_REF_IF_OBJECT 0, w26
5321   str  w26, [x0, x1]
5322   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_wide_skip_write_barrier
5323   .endif
5324   FETCH_ADVANCE_INST 2
5325   GET_INST_OPCODE ip
5326   GOTO_OPCODE ip
5327.Lop_sput_wide_read_barrier:
5328   bl      art_quick_read_barrier_mark_reg00
5329   b       .Lop_sput_wide_resume_after_read_barrier
5330
5331    NAME_END nterp_op_sput_wide
5332    // Advance to the end of this handler. Causes error if we are past that point.
5333    .org nterp_op_sput_wide + NTERP_HANDLER_SIZE  // op_sput_wide handler is too big!
5334
5335/* ------------------------------ */
5336    .balign NTERP_HANDLER_SIZE
5337.L_op_sput_object: /* 0x69 */
5338    NAME_START nterp_op_sput_object
5339    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5340    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5341
5342   lsr     w2, wINST, #8               // w2 <- A
5343   .if 0
5344   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5345   .else
5346   GET_VREG w26, w2                    // w26 <- v[A]
5347   .endif
5348   // Fast-path which gets the field from thread-local cache.
5349   // Fetch some information from the thread cache.
5350   // Uses ip and ip2 as temporaries.
5351   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5352   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5353   add      ip, ip, ip2, lsl #4            // entry address within the cache
5354   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5355   cmp      ip, xPC
5356   b.ne     nterp_op_sput_object_slow_path
5357
5358.Lop_sput_object_resume:
5359   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5360   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5361   TEST_IF_MARKING .Lop_sput_object_read_barrier
5362.Lop_sput_object_resume_after_read_barrier:
5363   .if 0
5364   str  x26, [x0, x1]
5365   .else
5366   POISON_HEAP_REF_IF_OBJECT 1, w26
5367   str  w26, [x0, x1]
5368   WRITE_BARRIER_IF_OBJECT 1, w26, w0, .Lop_sput_object_skip_write_barrier
5369   .endif
5370   FETCH_ADVANCE_INST 2
5371   GET_INST_OPCODE ip
5372   GOTO_OPCODE ip
5373.Lop_sput_object_read_barrier:
5374   bl      art_quick_read_barrier_mark_reg00
5375   b       .Lop_sput_object_resume_after_read_barrier
5376
5377    NAME_END nterp_op_sput_object
5378    // Advance to the end of this handler. Causes error if we are past that point.
5379    .org nterp_op_sput_object + NTERP_HANDLER_SIZE  // op_sput_object handler is too big!
5380
5381/* ------------------------------ */
5382    .balign NTERP_HANDLER_SIZE
5383.L_op_sput_boolean: /* 0x6a */
5384    NAME_START nterp_op_sput_boolean
5385    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5386    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5387
5388   lsr     w2, wINST, #8               // w2 <- A
5389   .if 0
5390   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5391   .else
5392   GET_VREG w26, w2                    // w26 <- v[A]
5393   .endif
5394   // Fast-path which gets the field from thread-local cache.
5395   // Fetch some information from the thread cache.
5396   // Uses ip and ip2 as temporaries.
5397   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5398   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5399   add      ip, ip, ip2, lsl #4            // entry address within the cache
5400   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5401   cmp      ip, xPC
5402   b.ne     nterp_op_sput_boolean_slow_path
5403
5404.Lop_sput_boolean_resume:
5405   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5406   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5407   TEST_IF_MARKING .Lop_sput_boolean_read_barrier
5408.Lop_sput_boolean_resume_after_read_barrier:
5409   .if 0
5410   strb  x26, [x0, x1]
5411   .else
5412   POISON_HEAP_REF_IF_OBJECT 0, w26
5413   strb  w26, [x0, x1]
5414   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_boolean_skip_write_barrier
5415   .endif
5416   FETCH_ADVANCE_INST 2
5417   GET_INST_OPCODE ip
5418   GOTO_OPCODE ip
5419.Lop_sput_boolean_read_barrier:
5420   bl      art_quick_read_barrier_mark_reg00
5421   b       .Lop_sput_boolean_resume_after_read_barrier
5422
5423    NAME_END nterp_op_sput_boolean
5424    // Advance to the end of this handler. Causes error if we are past that point.
5425    .org nterp_op_sput_boolean + NTERP_HANDLER_SIZE  // op_sput_boolean handler is too big!
5426
5427/* ------------------------------ */
5428    .balign NTERP_HANDLER_SIZE
5429.L_op_sput_byte: /* 0x6b */
5430    NAME_START nterp_op_sput_byte
5431    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5432    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5433
5434   lsr     w2, wINST, #8               // w2 <- A
5435   .if 0
5436   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5437   .else
5438   GET_VREG w26, w2                    // w26 <- v[A]
5439   .endif
5440   // Fast-path which gets the field from thread-local cache.
5441   // Fetch some information from the thread cache.
5442   // Uses ip and ip2 as temporaries.
5443   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5444   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5445   add      ip, ip, ip2, lsl #4            // entry address within the cache
5446   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5447   cmp      ip, xPC
5448   b.ne     nterp_op_sput_byte_slow_path
5449
5450.Lop_sput_byte_resume:
5451   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5452   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5453   TEST_IF_MARKING .Lop_sput_byte_read_barrier
5454.Lop_sput_byte_resume_after_read_barrier:
5455   .if 0
5456   strb  x26, [x0, x1]
5457   .else
5458   POISON_HEAP_REF_IF_OBJECT 0, w26
5459   strb  w26, [x0, x1]
5460   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_byte_skip_write_barrier
5461   .endif
5462   FETCH_ADVANCE_INST 2
5463   GET_INST_OPCODE ip
5464   GOTO_OPCODE ip
5465.Lop_sput_byte_read_barrier:
5466   bl      art_quick_read_barrier_mark_reg00
5467   b       .Lop_sput_byte_resume_after_read_barrier
5468
5469    NAME_END nterp_op_sput_byte
5470    // Advance to the end of this handler. Causes error if we are past that point.
5471    .org nterp_op_sput_byte + NTERP_HANDLER_SIZE  // op_sput_byte handler is too big!
5472
5473/* ------------------------------ */
5474    .balign NTERP_HANDLER_SIZE
5475.L_op_sput_char: /* 0x6c */
5476    NAME_START nterp_op_sput_char
5477    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5478    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5479
5480   lsr     w2, wINST, #8               // w2 <- A
5481   .if 0
5482   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5483   .else
5484   GET_VREG w26, w2                    // w26 <- v[A]
5485   .endif
5486   // Fast-path which gets the field from thread-local cache.
5487   // Fetch some information from the thread cache.
5488   // Uses ip and ip2 as temporaries.
5489   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5490   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5491   add      ip, ip, ip2, lsl #4            // entry address within the cache
5492   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5493   cmp      ip, xPC
5494   b.ne     nterp_op_sput_char_slow_path
5495
5496.Lop_sput_char_resume:
5497   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5498   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5499   TEST_IF_MARKING .Lop_sput_char_read_barrier
5500.Lop_sput_char_resume_after_read_barrier:
5501   .if 0
5502   strh  x26, [x0, x1]
5503   .else
5504   POISON_HEAP_REF_IF_OBJECT 0, w26
5505   strh  w26, [x0, x1]
5506   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_char_skip_write_barrier
5507   .endif
5508   FETCH_ADVANCE_INST 2
5509   GET_INST_OPCODE ip
5510   GOTO_OPCODE ip
5511.Lop_sput_char_read_barrier:
5512   bl      art_quick_read_barrier_mark_reg00
5513   b       .Lop_sput_char_resume_after_read_barrier
5514
5515    NAME_END nterp_op_sput_char
5516    // Advance to the end of this handler. Causes error if we are past that point.
5517    .org nterp_op_sput_char + NTERP_HANDLER_SIZE  // op_sput_char handler is too big!
5518
5519/* ------------------------------ */
5520    .balign NTERP_HANDLER_SIZE
5521.L_op_sput_short: /* 0x6d */
5522    NAME_START nterp_op_sput_short
5523    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5524    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5525
5526   lsr     w2, wINST, #8               // w2 <- A
5527   .if 0
5528   GET_VREG_WIDE x26, w2               // x26 <- v[A]
5529   .else
5530   GET_VREG w26, w2                    // w26 <- v[A]
5531   .endif
5532   // Fast-path which gets the field from thread-local cache.
5533   // Fetch some information from the thread cache.
5534   // Uses ip and ip2 as temporaries.
5535   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5536   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5537   add      ip, ip, ip2, lsl #4            // entry address within the cache
5538   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5539   cmp      ip, xPC
5540   b.ne     nterp_op_sput_short_slow_path
5541
5542.Lop_sput_short_resume:
5543   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
5544   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
5545   TEST_IF_MARKING .Lop_sput_short_read_barrier
5546.Lop_sput_short_resume_after_read_barrier:
5547   .if 0
5548   strh  x26, [x0, x1]
5549   .else
5550   POISON_HEAP_REF_IF_OBJECT 0, w26
5551   strh  w26, [x0, x1]
5552   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_short_skip_write_barrier
5553   .endif
5554   FETCH_ADVANCE_INST 2
5555   GET_INST_OPCODE ip
5556   GOTO_OPCODE ip
5557.Lop_sput_short_read_barrier:
5558   bl      art_quick_read_barrier_mark_reg00
5559   b       .Lop_sput_short_resume_after_read_barrier
5560
5561    NAME_END nterp_op_sput_short
5562    // Advance to the end of this handler. Causes error if we are past that point.
5563    .org nterp_op_sput_short + NTERP_HANDLER_SIZE  // op_sput_short handler is too big!
5564
5565/* ------------------------------ */
5566    .balign NTERP_HANDLER_SIZE
5567.L_op_invoke_virtual: /* 0x6e */
5568    NAME_START nterp_op_invoke_virtual
5569    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5570    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5571
5572   EXPORT_PC
5573   // Fast-path which gets the method from thread-local cache.
5574   // Fetch some information from the thread cache.
5575   // Uses ip and ip2 as temporaries.
5576   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5577   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5578   add      ip, ip, ip2, lsl #4            // entry address within the cache
5579   ldp      ip, x2, [ip]          // entry key (pc) and value (offset)
5580   cmp      ip, xPC
5581   b.ne     2f
5582
55831:
5584   FETCH w1, 2
5585   .if !0
5586   and w1, w1, #0xf
5587   .endif
5588   GET_VREG w1, w1
5589   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
5590   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
5591   UNPOISON_HEAP_REF w0
5592   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
5593   ldr x0, [x0, w2, uxtw #3]
5594   b NterpCommonInvokeInstance
55952:
5596   mov x0, xSELF
5597   ldr x1, [sp]
5598   mov x2, xPC
5599   bl nterp_get_method
5600   mov x2, x0
5601   b 1b
5602
5603    NAME_END nterp_op_invoke_virtual
5604    // Advance to the end of this handler. Causes error if we are past that point.
5605    .org nterp_op_invoke_virtual + NTERP_HANDLER_SIZE  // op_invoke_virtual handler is too big!
5606
5607/* ------------------------------ */
5608    .balign NTERP_HANDLER_SIZE
5609.L_op_invoke_super: /* 0x6f */
5610    NAME_START nterp_op_invoke_super
5611    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5612    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5613
5614   EXPORT_PC
5615   // Fast-path which gets the method from thread-local cache.
5616   // Fetch some information from the thread cache.
5617   // Uses ip and ip2 as temporaries.
5618   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5619   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5620   add      ip, ip, ip2, lsl #4            // entry address within the cache
5621   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5622   cmp      ip, xPC
5623   b.ne     2f
5624
56251:
5626   // Load the first argument (the 'this' pointer).
5627   FETCH w1, 2
5628   .if !0
5629   and w1, w1, #0xf
5630   .endif
5631   GET_VREG w1, w1
5632   cbz w1, common_errNullObject    // bail if null
5633   b NterpCommonInvokeInstance
56342:
5635   mov x0, xSELF
5636   ldr x1, [sp]
5637   mov x2, xPC
5638   bl nterp_get_method
5639   .if 1
5640   b 1b
5641   .else
5642   tbz x0, #0, 1b
5643   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
5644   .if 0
5645   b NterpHandleStringInitRange
5646   .else
5647   b NterpHandleStringInit
5648   .endif
5649   .endif
5650
5651    NAME_END nterp_op_invoke_super
5652    // Advance to the end of this handler. Causes error if we are past that point.
5653    .org nterp_op_invoke_super + NTERP_HANDLER_SIZE  // op_invoke_super handler is too big!
5654
5655/* ------------------------------ */
5656    .balign NTERP_HANDLER_SIZE
5657.L_op_invoke_direct: /* 0x70 */
5658    NAME_START nterp_op_invoke_direct
5659    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5660    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5661
5662   EXPORT_PC
5663   // Fast-path which gets the method from thread-local cache.
5664   // Fetch some information from the thread cache.
5665   // Uses ip and ip2 as temporaries.
5666   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5667   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5668   add      ip, ip, ip2, lsl #4            // entry address within the cache
5669   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5670   cmp      ip, xPC
5671   b.ne     2f
5672
56731:
5674   // Load the first argument (the 'this' pointer).
5675   FETCH w1, 2
5676   .if !0
5677   and w1, w1, #0xf
5678   .endif
5679   GET_VREG w1, w1
5680   cbz w1, common_errNullObject    // bail if null
5681   b NterpCommonInvokeInstance
56822:
5683   mov x0, xSELF
5684   ldr x1, [sp]
5685   mov x2, xPC
5686   bl nterp_get_method
5687   .if 0
5688   b 1b
5689   .else
5690   tbz x0, #0, 1b
5691   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
5692   .if 0
5693   b NterpHandleStringInitRange
5694   .else
5695   b NterpHandleStringInit
5696   .endif
5697   .endif
5698
5699    NAME_END nterp_op_invoke_direct
5700    // Advance to the end of this handler. Causes error if we are past that point.
5701    .org nterp_op_invoke_direct + NTERP_HANDLER_SIZE  // op_invoke_direct handler is too big!
5702
5703/* ------------------------------ */
5704    .balign NTERP_HANDLER_SIZE
5705.L_op_invoke_static: /* 0x71 */
5706    NAME_START nterp_op_invoke_static
5707    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5708    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5709
5710   EXPORT_PC
5711   // Fast-path which gets the method from thread-local cache.
5712   // Fetch some information from the thread cache.
5713   // Uses ip and ip2 as temporaries.
5714   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5715   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5716   add      ip, ip, ip2, lsl #4            // entry address within the cache
5717   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5718   cmp      ip, xPC
5719   b.ne     1f
5720
5721   b NterpCommonInvokeStatic
57221:
5723   mov x0, xSELF
5724   ldr x1, [sp]
5725   mov x2, xPC
5726   bl nterp_get_method
5727   b NterpCommonInvokeStatic
5728
5729    NAME_END nterp_op_invoke_static
5730    // Advance to the end of this handler. Causes error if we are past that point.
5731    .org nterp_op_invoke_static + NTERP_HANDLER_SIZE  // op_invoke_static handler is too big!
5732
5733/* ------------------------------ */
5734    .balign NTERP_HANDLER_SIZE
5735.L_op_invoke_interface: /* 0x72 */
5736    NAME_START nterp_op_invoke_interface
5737    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5738    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5739
5740   EXPORT_PC
5741   // Fast-path which gets the method from thread-local cache.
5742   // Fetch some information from the thread cache.
5743   // Uses ip and ip2 as temporaries.
5744   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5745   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5746   add      ip, ip, ip2, lsl #4            // entry address within the cache
5747   ldp      ip, x26, [ip]          // entry key (pc) and value (offset)
5748   cmp      ip, xPC
5749   b.ne     nterp_op_invoke_interface_slow_path
5750
5751.Lop_invoke_interface_resume:
5752   // First argument is the 'this' pointer.
5753   FETCH w1, 2
5754   .if !0
5755   and w1, w1, #0xf
5756   .endif
5757   GET_VREG w1, w1
5758   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
5759   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
5760   UNPOISON_HEAP_REF w2
5761   // Test the first two bits of the fetched ArtMethod:
5762   // - If the first bit is set, this is a method on j.l.Object
5763   // - If the second bit is set, this is a default method.
5764   tst w26, #0x3
5765   b.ne 2f
5766   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
57671:
5768   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
5769   ldr x0, [x2, w3, uxtw #3]
5770   .if 0
5771   b NterpCommonInvokeInterfaceRange
5772   .else
5773   b NterpCommonInvokeInterface
5774   .endif
57752:
5776   tbnz w26, #0, 3f
5777   and x26, x26, #-4
5778   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
5779   and w3, w3, #ART_METHOD_IMT_MASK
5780   b 1b
57813:
5782   lsr w26, w26, #16
5783   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
5784   ldr x0, [x2, w26, uxtw #3]
5785   .if 0
5786   b NterpCommonInvokeInstanceRange
5787   .else
5788   b NterpCommonInvokeInstance
5789   .endif
5790
5791    NAME_END nterp_op_invoke_interface
5792    // Advance to the end of this handler. Causes error if we are past that point.
5793    .org nterp_op_invoke_interface + NTERP_HANDLER_SIZE  // op_invoke_interface handler is too big!
5794
5795/* ------------------------------ */
5796    .balign NTERP_HANDLER_SIZE
5797.L_op_unused_73: /* 0x73 */
5798    NAME_START nterp_op_unused_73
5799    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5800    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5801
5802    brk 42
5803
5804    NAME_END nterp_op_unused_73
5805    // Advance to the end of this handler. Causes error if we are past that point.
5806    .org nterp_op_unused_73 + NTERP_HANDLER_SIZE  // op_unused_73 handler is too big!
5807
5808/* ------------------------------ */
5809    .balign NTERP_HANDLER_SIZE
5810.L_op_invoke_virtual_range: /* 0x74 */
5811    NAME_START nterp_op_invoke_virtual_range
5812    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5813    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5814
5815   EXPORT_PC
5816   // Fast-path which gets the method from thread-local cache.
5817   // Fetch some information from the thread cache.
5818   // Uses ip and ip2 as temporaries.
5819   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5820   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5821   add      ip, ip, ip2, lsl #4            // entry address within the cache
5822   ldp      ip, x2, [ip]          // entry key (pc) and value (offset)
5823   cmp      ip, xPC
5824   b.ne     2f
5825
58261:
5827   FETCH w1, 2
5828   .if !1
5829   and w1, w1, #0xf
5830   .endif
5831   GET_VREG w1, w1
5832   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
5833   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
5834   UNPOISON_HEAP_REF w0
5835   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
5836   ldr x0, [x0, w2, uxtw #3]
5837   b NterpCommonInvokeInstanceRange
58382:
5839   mov x0, xSELF
5840   ldr x1, [sp]
5841   mov x2, xPC
5842   bl nterp_get_method
5843   mov x2, x0
5844   b 1b
5845
5846    NAME_END nterp_op_invoke_virtual_range
5847    // Advance to the end of this handler. Causes error if we are past that point.
5848    .org nterp_op_invoke_virtual_range + NTERP_HANDLER_SIZE  // op_invoke_virtual_range handler is too big!
5849
5850/* ------------------------------ */
5851    .balign NTERP_HANDLER_SIZE
5852.L_op_invoke_super_range: /* 0x75 */
5853    NAME_START nterp_op_invoke_super_range
5854    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5855    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5856
5857   EXPORT_PC
5858   // Fast-path which gets the method from thread-local cache.
5859   // Fetch some information from the thread cache.
5860   // Uses ip and ip2 as temporaries.
5861   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5862   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5863   add      ip, ip, ip2, lsl #4            // entry address within the cache
5864   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5865   cmp      ip, xPC
5866   b.ne     2f
5867
58681:
5869   // Load the first argument (the 'this' pointer).
5870   FETCH w1, 2
5871   .if !1
5872   and w1, w1, #0xf
5873   .endif
5874   GET_VREG w1, w1
5875   cbz w1, common_errNullObject    // bail if null
5876   b NterpCommonInvokeInstanceRange
58772:
5878   mov x0, xSELF
5879   ldr x1, [sp]
5880   mov x2, xPC
5881   bl nterp_get_method
5882   .if 1
5883   b 1b
5884   .else
5885   tbz x0, #0, 1b
5886   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
5887   .if 1
5888   b NterpHandleStringInitRange
5889   .else
5890   b NterpHandleStringInit
5891   .endif
5892   .endif
5893
5894    NAME_END nterp_op_invoke_super_range
5895    // Advance to the end of this handler. Causes error if we are past that point.
5896    .org nterp_op_invoke_super_range + NTERP_HANDLER_SIZE  // op_invoke_super_range handler is too big!
5897
5898/* ------------------------------ */
5899    .balign NTERP_HANDLER_SIZE
5900.L_op_invoke_direct_range: /* 0x76 */
5901    NAME_START nterp_op_invoke_direct_range
5902    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5903    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5904
5905   EXPORT_PC
5906   // Fast-path which gets the method from thread-local cache.
5907   // Fetch some information from the thread cache.
5908   // Uses ip and ip2 as temporaries.
5909   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5910   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5911   add      ip, ip, ip2, lsl #4            // entry address within the cache
5912   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5913   cmp      ip, xPC
5914   b.ne     2f
5915
59161:
5917   // Load the first argument (the 'this' pointer).
5918   FETCH w1, 2
5919   .if !1
5920   and w1, w1, #0xf
5921   .endif
5922   GET_VREG w1, w1
5923   cbz w1, common_errNullObject    // bail if null
5924   b NterpCommonInvokeInstanceRange
59252:
5926   mov x0, xSELF
5927   ldr x1, [sp]
5928   mov x2, xPC
5929   bl nterp_get_method
5930   .if 0
5931   b 1b
5932   .else
5933   tbz x0, #0, 1b
5934   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
5935   .if 1
5936   b NterpHandleStringInitRange
5937   .else
5938   b NterpHandleStringInit
5939   .endif
5940   .endif
5941
5942    NAME_END nterp_op_invoke_direct_range
5943    // Advance to the end of this handler. Causes error if we are past that point.
5944    .org nterp_op_invoke_direct_range + NTERP_HANDLER_SIZE  // op_invoke_direct_range handler is too big!
5945
5946/* ------------------------------ */
5947    .balign NTERP_HANDLER_SIZE
5948.L_op_invoke_static_range: /* 0x77 */
5949    NAME_START nterp_op_invoke_static_range
5950    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5951    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5952
5953   EXPORT_PC
5954   // Fast-path which gets the method from thread-local cache.
5955   // Fetch some information from the thread cache.
5956   // Uses ip and ip2 as temporaries.
5957   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5958   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5959   add      ip, ip, ip2, lsl #4            // entry address within the cache
5960   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
5961   cmp      ip, xPC
5962   b.ne     1f
5963
5964   b NterpCommonInvokeStaticRange
59651:
5966   mov x0, xSELF
5967   ldr x1, [sp]
5968   mov x2, xPC
5969   bl nterp_get_method
5970   b NterpCommonInvokeStaticRange
5971
5972    NAME_END nterp_op_invoke_static_range
5973    // Advance to the end of this handler. Causes error if we are past that point.
5974    .org nterp_op_invoke_static_range + NTERP_HANDLER_SIZE  // op_invoke_static_range handler is too big!
5975
5976/* ------------------------------ */
5977    .balign NTERP_HANDLER_SIZE
5978.L_op_invoke_interface_range: /* 0x78 */
5979    NAME_START nterp_op_invoke_interface_range
5980    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
5981    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
5982
5983   EXPORT_PC
5984   // Fast-path which gets the method from thread-local cache.
5985   // Fetch some information from the thread cache.
5986   // Uses ip and ip2 as temporaries.
5987   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
5988   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
5989   add      ip, ip, ip2, lsl #4            // entry address within the cache
5990   ldp      ip, x26, [ip]          // entry key (pc) and value (offset)
5991   cmp      ip, xPC
5992   b.ne     nterp_op_invoke_interface_range_slow_path
5993
5994.Lop_invoke_interface_range_resume:
5995   // First argument is the 'this' pointer.
5996   FETCH w1, 2
5997   .if !1
5998   and w1, w1, #0xf
5999   .endif
6000   GET_VREG w1, w1
6001   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
6002   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
6003   UNPOISON_HEAP_REF w2
6004   // Test the first two bits of the fetched ArtMethod:
6005   // - If the first bit is set, this is a method on j.l.Object
6006   // - If the second bit is set, this is a default method.
6007   tst w26, #0x3
6008   b.ne 2f
6009   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
60101:
6011   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
6012   ldr x0, [x2, w3, uxtw #3]
6013   .if 1
6014   b NterpCommonInvokeInterfaceRange
6015   .else
6016   b NterpCommonInvokeInterface
6017   .endif
60182:
6019   tbnz w26, #0, 3f
6020   and x26, x26, #-4
6021   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
6022   and w3, w3, #ART_METHOD_IMT_MASK
6023   b 1b
60243:
6025   lsr w26, w26, #16
6026   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
6027   ldr x0, [x2, w26, uxtw #3]
6028   .if 1
6029   b NterpCommonInvokeInstanceRange
6030   .else
6031   b NterpCommonInvokeInstance
6032   .endif
6033
6034    NAME_END nterp_op_invoke_interface_range
6035    // Advance to the end of this handler. Causes error if we are past that point.
6036    .org nterp_op_invoke_interface_range + NTERP_HANDLER_SIZE  // op_invoke_interface_range handler is too big!
6037
6038/* ------------------------------ */
6039    .balign NTERP_HANDLER_SIZE
6040.L_op_unused_79: /* 0x79 */
6041    NAME_START nterp_op_unused_79
6042    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6043    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6044
6045    brk 42
6046
6047    NAME_END nterp_op_unused_79
6048    // Advance to the end of this handler. Causes error if we are past that point.
6049    .org nterp_op_unused_79 + NTERP_HANDLER_SIZE  // op_unused_79 handler is too big!
6050
6051/* ------------------------------ */
6052    .balign NTERP_HANDLER_SIZE
6053.L_op_unused_7a: /* 0x7a */
6054    NAME_START nterp_op_unused_7a
6055    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6056    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6057
6058    brk 42
6059
6060    NAME_END nterp_op_unused_7a
6061    // Advance to the end of this handler. Causes error if we are past that point.
6062    .org nterp_op_unused_7a + NTERP_HANDLER_SIZE  // op_unused_7a handler is too big!
6063
6064/* ------------------------------ */
6065    .balign NTERP_HANDLER_SIZE
6066.L_op_neg_int: /* 0x7b */
6067    NAME_START nterp_op_neg_int
6068    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6069    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6070
6071    /*
6072     * Generic 32-bit unary operation.  Provide an "instr" line that
6073     * specifies an instruction that performs "result = op w0".
6074     * This could be an ARM instruction or a function call.
6075     *
6076     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6077     *      int-to-byte, int-to-char, int-to-short
6078     */
6079    /* unop vA, vB */
6080    lsr     w3, wINST, #12              // w3<- B
6081    GET_VREG w0, w3                     // w0<- vB
6082    ubfx    w9, wINST, #8, #4           // w9<- A
6083    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6084    sub     w0, wzr, w0                              // w0<- op, w0-w3 changed
6085    GET_INST_OPCODE ip                  // extract opcode from rINST
6086    SET_VREG w0, w9                     // vAA<- w0
6087    GOTO_OPCODE ip                      // jump to next instruction
6088    /* 8-9 instructions */
6089
6090    NAME_END nterp_op_neg_int
6091    // Advance to the end of this handler. Causes error if we are past that point.
6092    .org nterp_op_neg_int + NTERP_HANDLER_SIZE  // op_neg_int handler is too big!
6093
6094/* ------------------------------ */
6095    .balign NTERP_HANDLER_SIZE
6096.L_op_not_int: /* 0x7c */
6097    NAME_START nterp_op_not_int
6098    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6099    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6100
6101    /*
6102     * Generic 32-bit unary operation.  Provide an "instr" line that
6103     * specifies an instruction that performs "result = op w0".
6104     * This could be an ARM instruction or a function call.
6105     *
6106     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6107     *      int-to-byte, int-to-char, int-to-short
6108     */
6109    /* unop vA, vB */
6110    lsr     w3, wINST, #12              // w3<- B
6111    GET_VREG w0, w3                     // w0<- vB
6112    ubfx    w9, wINST, #8, #4           // w9<- A
6113    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6114    mvn     w0, w0                              // w0<- op, w0-w3 changed
6115    GET_INST_OPCODE ip                  // extract opcode from rINST
6116    SET_VREG w0, w9                     // vAA<- w0
6117    GOTO_OPCODE ip                      // jump to next instruction
6118    /* 8-9 instructions */
6119
6120    NAME_END nterp_op_not_int
6121    // Advance to the end of this handler. Causes error if we are past that point.
6122    .org nterp_op_not_int + NTERP_HANDLER_SIZE  // op_not_int handler is too big!
6123
6124/* ------------------------------ */
6125    .balign NTERP_HANDLER_SIZE
6126.L_op_neg_long: /* 0x7d */
6127    NAME_START nterp_op_neg_long
6128    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6129    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6130
6131    /*
6132     * Generic 64-bit unary operation.  Provide an "instr" line that
6133     * specifies an instruction that performs "result = op x0".
6134     *
6135     * For: neg-long, not-long
6136     */
6137    /* unop vA, vB */
6138    lsr     w3, wINST, #12              // w3<- B
6139    ubfx    w4, wINST, #8, #4           // w4<- A
6140    GET_VREG_WIDE x0, w3
6141    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6142    sub x0, xzr, x0
6143    GET_INST_OPCODE ip                  // extract opcode from wINST
6144    SET_VREG_WIDE x0, w4
6145    GOTO_OPCODE ip                      // jump to next instruction
6146    /* 10-11 instructions */
6147
6148    NAME_END nterp_op_neg_long
6149    // Advance to the end of this handler. Causes error if we are past that point.
6150    .org nterp_op_neg_long + NTERP_HANDLER_SIZE  // op_neg_long handler is too big!
6151
6152/* ------------------------------ */
6153    .balign NTERP_HANDLER_SIZE
6154.L_op_not_long: /* 0x7e */
6155    NAME_START nterp_op_not_long
6156    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6157    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6158
6159    /*
6160     * Generic 64-bit unary operation.  Provide an "instr" line that
6161     * specifies an instruction that performs "result = op x0".
6162     *
6163     * For: neg-long, not-long
6164     */
6165    /* unop vA, vB */
6166    lsr     w3, wINST, #12              // w3<- B
6167    ubfx    w4, wINST, #8, #4           // w4<- A
6168    GET_VREG_WIDE x0, w3
6169    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6170    mvn     x0, x0
6171    GET_INST_OPCODE ip                  // extract opcode from wINST
6172    SET_VREG_WIDE x0, w4
6173    GOTO_OPCODE ip                      // jump to next instruction
6174    /* 10-11 instructions */
6175
6176    NAME_END nterp_op_not_long
6177    // Advance to the end of this handler. Causes error if we are past that point.
6178    .org nterp_op_not_long + NTERP_HANDLER_SIZE  // op_not_long handler is too big!
6179
6180/* ------------------------------ */
6181    .balign NTERP_HANDLER_SIZE
6182.L_op_neg_float: /* 0x7f */
6183    NAME_START nterp_op_neg_float
6184    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6185    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6186
6187    /*
6188     * Generic 32-bit unary operation.  Provide an "instr" line that
6189     * specifies an instruction that performs "result = op w0".
6190     * This could be an ARM instruction or a function call.
6191     *
6192     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6193     *      int-to-byte, int-to-char, int-to-short
6194     */
6195    /* unop vA, vB */
6196    lsr     w3, wINST, #12              // w3<- B
6197    GET_VREG w0, w3                     // w0<- vB
6198    ubfx    w9, wINST, #8, #4           // w9<- A
6199    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6200    eor     w0, w0, #0x80000000                              // w0<- op, w0-w3 changed
6201    GET_INST_OPCODE ip                  // extract opcode from rINST
6202    SET_VREG w0, w9                     // vAA<- w0
6203    GOTO_OPCODE ip                      // jump to next instruction
6204    /* 8-9 instructions */
6205
6206    NAME_END nterp_op_neg_float
6207    // Advance to the end of this handler. Causes error if we are past that point.
6208    .org nterp_op_neg_float + NTERP_HANDLER_SIZE  // op_neg_float handler is too big!
6209
6210/* ------------------------------ */
6211    .balign NTERP_HANDLER_SIZE
6212.L_op_neg_double: /* 0x80 */
6213    NAME_START nterp_op_neg_double
6214    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6215    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6216
6217    /*
6218     * Generic 64-bit unary operation.  Provide an "instr" line that
6219     * specifies an instruction that performs "result = op x0".
6220     *
6221     * For: neg-long, not-long
6222     */
6223    /* unop vA, vB */
6224    lsr     w3, wINST, #12              // w3<- B
6225    ubfx    w4, wINST, #8, #4           // w4<- A
6226    GET_VREG_WIDE x0, w3
6227    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6228    eor     x0, x0, #0x8000000000000000
6229    GET_INST_OPCODE ip                  // extract opcode from wINST
6230    SET_VREG_WIDE x0, w4
6231    GOTO_OPCODE ip                      // jump to next instruction
6232    /* 10-11 instructions */
6233
6234    NAME_END nterp_op_neg_double
6235    // Advance to the end of this handler. Causes error if we are past that point.
6236    .org nterp_op_neg_double + NTERP_HANDLER_SIZE  // op_neg_double handler is too big!
6237
6238/* ------------------------------ */
6239    .balign NTERP_HANDLER_SIZE
6240.L_op_int_to_long: /* 0x81 */
6241    NAME_START nterp_op_int_to_long
6242    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6243    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6244
6245    /* int-to-long vA, vB */
6246    lsr     w3, wINST, #12              // w3<- B
6247    ubfx    w4, wINST, #8, #4           // w4<- A
6248    GET_VREG_S x0, w3                   // x0<- sign_extend(fp[B])
6249    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6250    GET_INST_OPCODE ip                  // extract opcode from wINST
6251    SET_VREG_WIDE x0, w4                // fp[A]<- x0
6252    GOTO_OPCODE ip                      // jump to next instruction
6253
6254    NAME_END nterp_op_int_to_long
6255    // Advance to the end of this handler. Causes error if we are past that point.
6256    .org nterp_op_int_to_long + NTERP_HANDLER_SIZE  // op_int_to_long handler is too big!
6257
6258/* ------------------------------ */
6259    .balign NTERP_HANDLER_SIZE
6260.L_op_int_to_float: /* 0x82 */
6261    NAME_START nterp_op_int_to_float
6262    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6263    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6264
6265    /*
6266     * Generic 32bit-to-32bit floating point unary operation.  Provide an
6267     * "instr" line that specifies an instruction that performs "s0 = op w0".
6268     *
6269     * For: int-to-float, float-to-int
6270     * TODO: refactor all of the conversions - parameterize width and use same template.
6271     */
6272    /* unop vA, vB */
6273    lsr     w3, wINST, #12              // w3<- B
6274    ubfx    w4, wINST, #8, #4           // w4<- A
6275    GET_VREG w0, w3
6276    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6277    scvtf s0, w0                              // d0<- op
6278    GET_INST_OPCODE ip                  // extract opcode from wINST
6279    SET_VREG_FLOAT s0, w4          // vA<- d0
6280    GOTO_OPCODE ip                      // jump to next instruction
6281
6282    NAME_END nterp_op_int_to_float
6283    // Advance to the end of this handler. Causes error if we are past that point.
6284    .org nterp_op_int_to_float + NTERP_HANDLER_SIZE  // op_int_to_float handler is too big!
6285
6286/* ------------------------------ */
6287    .balign NTERP_HANDLER_SIZE
6288.L_op_int_to_double: /* 0x83 */
6289    NAME_START nterp_op_int_to_double
6290    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6291    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6292
6293    /*
6294     * Generic 32bit-to-64bit floating point unary operation.  Provide an
6295     * "instr" line that specifies an instruction that performs "d0 = op w0".
6296     *
6297     * For: int-to-double, float-to-double, float-to-long
6298     */
6299    /* unop vA, vB */
6300    lsr     w3, wINST, #12              // w3<- B
6301    ubfx    w4, wINST, #8, #4           // w4<- A
6302    GET_VREG w0, w3
6303    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6304    scvtf d0, w0                              // d0<- op
6305    GET_INST_OPCODE ip                  // extract opcode from wINST
6306    SET_VREG_WIDE d0, w4           // vA<- d0
6307    GOTO_OPCODE ip                      // jump to next instruction
6308
6309    NAME_END nterp_op_int_to_double
6310    // Advance to the end of this handler. Causes error if we are past that point.
6311    .org nterp_op_int_to_double + NTERP_HANDLER_SIZE  // op_int_to_double handler is too big!
6312
6313/* ------------------------------ */
6314    .balign NTERP_HANDLER_SIZE
6315.L_op_long_to_int: /* 0x84 */
6316    NAME_START nterp_op_long_to_int
6317    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6318    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6319
6320/* we ignore the high word, making this equivalent to a 32-bit reg move */
6321    /* for move, move-object, long-to-int */
6322    /* op vA, vB */
6323    lsr     w1, wINST, #12              // x1<- B from 15:12
6324    ubfx    w0, wINST, #8, #4           // x0<- A from 11:8
6325    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6326    GET_VREG w2, w1                     // x2<- fp[B]
6327    GET_INST_OPCODE ip                  // ip<- opcode from wINST
6328    .if 0
6329    SET_VREG_OBJECT w2, w0              // fp[A]<- x2
6330    .else
6331    SET_VREG w2, w0                     // fp[A]<- x2
6332    .endif
6333    GOTO_OPCODE ip                      // execute next instruction
6334
6335    NAME_END nterp_op_long_to_int
6336    // Advance to the end of this handler. Causes error if we are past that point.
6337    .org nterp_op_long_to_int + NTERP_HANDLER_SIZE  // op_long_to_int handler is too big!
6338
6339/* ------------------------------ */
6340    .balign NTERP_HANDLER_SIZE
6341.L_op_long_to_float: /* 0x85 */
6342    NAME_START nterp_op_long_to_float
6343    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6344    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6345
6346    /*
6347     * Generic 64bit-to-32bit floating point unary operation.  Provide an
6348     * "instr" line that specifies an instruction that performs "s0 = op x0".
6349     *
6350     * For: int-to-double, float-to-double, float-to-long
6351     */
6352    /* unop vA, vB */
6353    lsr     w3, wINST, #12              // w3<- B
6354    ubfx    w4, wINST, #8, #4           // w4<- A
6355    GET_VREG_WIDE x0, w3
6356    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6357    scvtf s0, x0                              // d0<- op
6358    GET_INST_OPCODE ip                  // extract opcode from wINST
6359    SET_VREG_FLOAT s0, w4          // vA<- d0
6360    GOTO_OPCODE ip                      // jump to next instruction
6361
6362    NAME_END nterp_op_long_to_float
6363    // Advance to the end of this handler. Causes error if we are past that point.
6364    .org nterp_op_long_to_float + NTERP_HANDLER_SIZE  // op_long_to_float handler is too big!
6365
6366/* ------------------------------ */
6367    .balign NTERP_HANDLER_SIZE
6368.L_op_long_to_double: /* 0x86 */
6369    NAME_START nterp_op_long_to_double
6370    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6371    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6372
6373    /*
6374     * Generic 64bit-to-64bit floating point unary operation.  Provide an
6375     * "instr" line that specifies an instruction that performs "d0 = op x0".
6376     *
6377     * For: long-to-double, double-to-long
6378     */
6379    /* unop vA, vB */
6380    lsr     w3, wINST, #12              // w3<- B
6381    ubfx    w4, wINST, #8, #4           // w4<- A
6382    GET_VREG_WIDE x0, w3
6383    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6384    scvtf d0, x0                              // d0<- op
6385    GET_INST_OPCODE ip                  // extract opcode from wINST
6386    SET_VREG_DOUBLE d0, w4         // vA<- d0
6387    GOTO_OPCODE ip                      // jump to next instruction
6388
6389    NAME_END nterp_op_long_to_double
6390    // Advance to the end of this handler. Causes error if we are past that point.
6391    .org nterp_op_long_to_double + NTERP_HANDLER_SIZE  // op_long_to_double handler is too big!
6392
6393/* ------------------------------ */
6394    .balign NTERP_HANDLER_SIZE
6395.L_op_float_to_int: /* 0x87 */
6396    NAME_START nterp_op_float_to_int
6397    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6398    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6399
6400    /*
6401     * Generic 32bit-to-32bit floating point unary operation.  Provide an
6402     * "instr" line that specifies an instruction that performs "w0 = op s0".
6403     *
6404     * For: int-to-float, float-to-int
6405     * TODO: refactor all of the conversions - parameterize width and use same template.
6406     */
6407    /* unop vA, vB */
6408    lsr     w3, wINST, #12              // w3<- B
6409    ubfx    w4, wINST, #8, #4           // w4<- A
6410    GET_VREG s0, w3
6411    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6412    fcvtzs w0, s0                              // d0<- op
6413    GET_INST_OPCODE ip                  // extract opcode from wINST
6414    SET_VREG_FLOAT w0, w4          // vA<- d0
6415    GOTO_OPCODE ip                      // jump to next instruction
6416
6417    NAME_END nterp_op_float_to_int
6418    // Advance to the end of this handler. Causes error if we are past that point.
6419    .org nterp_op_float_to_int + NTERP_HANDLER_SIZE  // op_float_to_int handler is too big!
6420
6421/* ------------------------------ */
6422    .balign NTERP_HANDLER_SIZE
6423.L_op_float_to_long: /* 0x88 */
6424    NAME_START nterp_op_float_to_long
6425    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6426    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6427
6428    /*
6429     * Generic 32bit-to-64bit floating point unary operation.  Provide an
6430     * "instr" line that specifies an instruction that performs "x0 = op s0".
6431     *
6432     * For: int-to-double, float-to-double, float-to-long
6433     */
6434    /* unop vA, vB */
6435    lsr     w3, wINST, #12              // w3<- B
6436    ubfx    w4, wINST, #8, #4           // w4<- A
6437    GET_VREG s0, w3
6438    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6439    fcvtzs x0, s0                              // d0<- op
6440    GET_INST_OPCODE ip                  // extract opcode from wINST
6441    SET_VREG_WIDE x0, w4           // vA<- d0
6442    GOTO_OPCODE ip                      // jump to next instruction
6443
6444    NAME_END nterp_op_float_to_long
6445    // Advance to the end of this handler. Causes error if we are past that point.
6446    .org nterp_op_float_to_long + NTERP_HANDLER_SIZE  // op_float_to_long handler is too big!
6447
6448/* ------------------------------ */
6449    .balign NTERP_HANDLER_SIZE
6450.L_op_float_to_double: /* 0x89 */
6451    NAME_START nterp_op_float_to_double
6452    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6453    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6454
6455    /*
6456     * Generic 32bit-to-64bit floating point unary operation.  Provide an
6457     * "instr" line that specifies an instruction that performs "d0 = op s0".
6458     *
6459     * For: int-to-double, float-to-double, float-to-long
6460     */
6461    /* unop vA, vB */
6462    lsr     w3, wINST, #12              // w3<- B
6463    ubfx    w4, wINST, #8, #4           // w4<- A
6464    GET_VREG s0, w3
6465    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6466    fcvt  d0, s0                              // d0<- op
6467    GET_INST_OPCODE ip                  // extract opcode from wINST
6468    SET_VREG_WIDE d0, w4           // vA<- d0
6469    GOTO_OPCODE ip                      // jump to next instruction
6470
6471    NAME_END nterp_op_float_to_double
6472    // Advance to the end of this handler. Causes error if we are past that point.
6473    .org nterp_op_float_to_double + NTERP_HANDLER_SIZE  // op_float_to_double handler is too big!
6474
6475/* ------------------------------ */
6476    .balign NTERP_HANDLER_SIZE
6477.L_op_double_to_int: /* 0x8a */
6478    NAME_START nterp_op_double_to_int
6479    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6480    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6481
6482    /*
6483     * Generic 64bit-to-32bit floating point unary operation.  Provide an
6484     * "instr" line that specifies an instruction that performs "w0 = op d0".
6485     *
6486     * For: int-to-double, float-to-double, float-to-long
6487     */
6488    /* unop vA, vB */
6489    lsr     w3, wINST, #12              // w3<- B
6490    ubfx    w4, wINST, #8, #4           // w4<- A
6491    GET_VREG_DOUBLE d0, w3
6492    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6493    fcvtzs w0, d0                              // d0<- op
6494    GET_INST_OPCODE ip                  // extract opcode from wINST
6495    SET_VREG_FLOAT w0, w4          // vA<- d0
6496    GOTO_OPCODE ip                      // jump to next instruction
6497
6498    NAME_END nterp_op_double_to_int
6499    // Advance to the end of this handler. Causes error if we are past that point.
6500    .org nterp_op_double_to_int + NTERP_HANDLER_SIZE  // op_double_to_int handler is too big!
6501
6502/* ------------------------------ */
6503    .balign NTERP_HANDLER_SIZE
6504.L_op_double_to_long: /* 0x8b */
6505    NAME_START nterp_op_double_to_long
6506    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6507    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6508
6509    /*
6510     * Generic 64bit-to-64bit floating point unary operation.  Provide an
6511     * "instr" line that specifies an instruction that performs "x0 = op d0".
6512     *
6513     * For: long-to-double, double-to-long
6514     */
6515    /* unop vA, vB */
6516    lsr     w3, wINST, #12              // w3<- B
6517    ubfx    w4, wINST, #8, #4           // w4<- A
6518    GET_VREG_DOUBLE d0, w3
6519    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6520    fcvtzs x0, d0                              // d0<- op
6521    GET_INST_OPCODE ip                  // extract opcode from wINST
6522    SET_VREG_WIDE x0, w4           // vA<- d0
6523    GOTO_OPCODE ip                      // jump to next instruction
6524
6525    NAME_END nterp_op_double_to_long
6526    // Advance to the end of this handler. Causes error if we are past that point.
6527    .org nterp_op_double_to_long + NTERP_HANDLER_SIZE  // op_double_to_long handler is too big!
6528
6529/* ------------------------------ */
6530    .balign NTERP_HANDLER_SIZE
6531.L_op_double_to_float: /* 0x8c */
6532    NAME_START nterp_op_double_to_float
6533    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6534    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6535
6536    /*
6537     * Generic 64bit-to-32bit floating point unary operation.  Provide an
6538     * "instr" line that specifies an instruction that performs "s0 = op d0".
6539     *
6540     * For: int-to-double, float-to-double, float-to-long
6541     */
6542    /* unop vA, vB */
6543    lsr     w3, wINST, #12              // w3<- B
6544    ubfx    w4, wINST, #8, #4           // w4<- A
6545    GET_VREG_DOUBLE d0, w3
6546    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
6547    fcvt s0, d0                              // d0<- op
6548    GET_INST_OPCODE ip                  // extract opcode from wINST
6549    SET_VREG_FLOAT s0, w4          // vA<- d0
6550    GOTO_OPCODE ip                      // jump to next instruction
6551
6552    NAME_END nterp_op_double_to_float
6553    // Advance to the end of this handler. Causes error if we are past that point.
6554    .org nterp_op_double_to_float + NTERP_HANDLER_SIZE  // op_double_to_float handler is too big!
6555
6556/* ------------------------------ */
6557    .balign NTERP_HANDLER_SIZE
6558.L_op_int_to_byte: /* 0x8d */
6559    NAME_START nterp_op_int_to_byte
6560    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6561    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6562
6563    /*
6564     * Generic 32-bit unary operation.  Provide an "instr" line that
6565     * specifies an instruction that performs "result = op w0".
6566     * This could be an ARM instruction or a function call.
6567     *
6568     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6569     *      int-to-byte, int-to-char, int-to-short
6570     */
6571    /* unop vA, vB */
6572    lsr     w3, wINST, #12              // w3<- B
6573    GET_VREG w0, w3                     // w0<- vB
6574    ubfx    w9, wINST, #8, #4           // w9<- A
6575    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6576    sxtb    w0, w0                              // w0<- op, w0-w3 changed
6577    GET_INST_OPCODE ip                  // extract opcode from rINST
6578    SET_VREG w0, w9                     // vAA<- w0
6579    GOTO_OPCODE ip                      // jump to next instruction
6580    /* 8-9 instructions */
6581
6582    NAME_END nterp_op_int_to_byte
6583    // Advance to the end of this handler. Causes error if we are past that point.
6584    .org nterp_op_int_to_byte + NTERP_HANDLER_SIZE  // op_int_to_byte handler is too big!
6585
6586/* ------------------------------ */
6587    .balign NTERP_HANDLER_SIZE
6588.L_op_int_to_char: /* 0x8e */
6589    NAME_START nterp_op_int_to_char
6590    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6591    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6592
6593    /*
6594     * Generic 32-bit unary operation.  Provide an "instr" line that
6595     * specifies an instruction that performs "result = op w0".
6596     * This could be an ARM instruction or a function call.
6597     *
6598     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6599     *      int-to-byte, int-to-char, int-to-short
6600     */
6601    /* unop vA, vB */
6602    lsr     w3, wINST, #12              // w3<- B
6603    GET_VREG w0, w3                     // w0<- vB
6604    ubfx    w9, wINST, #8, #4           // w9<- A
6605    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6606    uxth    w0, w0                              // w0<- op, w0-w3 changed
6607    GET_INST_OPCODE ip                  // extract opcode from rINST
6608    SET_VREG w0, w9                     // vAA<- w0
6609    GOTO_OPCODE ip                      // jump to next instruction
6610    /* 8-9 instructions */
6611
6612    NAME_END nterp_op_int_to_char
6613    // Advance to the end of this handler. Causes error if we are past that point.
6614    .org nterp_op_int_to_char + NTERP_HANDLER_SIZE  // op_int_to_char handler is too big!
6615
6616/* ------------------------------ */
6617    .balign NTERP_HANDLER_SIZE
6618.L_op_int_to_short: /* 0x8f */
6619    NAME_START nterp_op_int_to_short
6620    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6621    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6622
6623    /*
6624     * Generic 32-bit unary operation.  Provide an "instr" line that
6625     * specifies an instruction that performs "result = op w0".
6626     * This could be an ARM instruction or a function call.
6627     *
6628     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
6629     *      int-to-byte, int-to-char, int-to-short
6630     */
6631    /* unop vA, vB */
6632    lsr     w3, wINST, #12              // w3<- B
6633    GET_VREG w0, w3                     // w0<- vB
6634    ubfx    w9, wINST, #8, #4           // w9<- A
6635    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
6636    sxth    w0, w0                              // w0<- op, w0-w3 changed
6637    GET_INST_OPCODE ip                  // extract opcode from rINST
6638    SET_VREG w0, w9                     // vAA<- w0
6639    GOTO_OPCODE ip                      // jump to next instruction
6640    /* 8-9 instructions */
6641
6642    NAME_END nterp_op_int_to_short
6643    // Advance to the end of this handler. Causes error if we are past that point.
6644    .org nterp_op_int_to_short + NTERP_HANDLER_SIZE  // op_int_to_short handler is too big!
6645
6646/* ------------------------------ */
6647    .balign NTERP_HANDLER_SIZE
6648.L_op_add_int: /* 0x90 */
6649    NAME_START nterp_op_add_int
6650    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6651    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6652
6653    /*
6654     * Generic 32-bit binary operation.  Provide an "instr" line that
6655     * specifies an instruction that performs "result = w0 op w1".
6656     * This could be an ARM instruction or a function call.  (If the result
6657     * comes back in a register other than w0, you can override "result".)
6658     *
6659     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6660     * vCC (w1).  Useful for integer division and modulus.  Note that we
6661     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6662     * handles it correctly.
6663     *
6664     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6665     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6666     *      mul-float, div-float, rem-float
6667     */
6668    /* binop vAA, vBB, vCC */
6669    FETCH w0, 1                         // w0<- CCBB
6670    lsr     w9, wINST, #8               // w9<- AA
6671    lsr     w3, w0, #8                  // w3<- CC
6672    and     w2, w0, #255                // w2<- BB
6673    GET_VREG w1, w3                     // w1<- vCC
6674    GET_VREG w0, w2                     // w0<- vBB
6675    .if 0
6676    cbz     w1, common_errDivideByZero  // is second operand zero?
6677    .endif
6678    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6679                               // optional op; may set condition codes
6680    add     w0, w0, w1                              // w0<- op, w0-w3 changed
6681    GET_INST_OPCODE ip                  // extract opcode from rINST
6682    SET_VREG w0, w9                // vAA<- w0
6683    GOTO_OPCODE ip                      // jump to next instruction
6684    /* 11-14 instructions */
6685
6686    NAME_END nterp_op_add_int
6687    // Advance to the end of this handler. Causes error if we are past that point.
6688    .org nterp_op_add_int + NTERP_HANDLER_SIZE  // op_add_int handler is too big!
6689
6690/* ------------------------------ */
6691    .balign NTERP_HANDLER_SIZE
6692.L_op_sub_int: /* 0x91 */
6693    NAME_START nterp_op_sub_int
6694    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6695    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6696
6697    /*
6698     * Generic 32-bit binary operation.  Provide an "instr" line that
6699     * specifies an instruction that performs "result = w0 op w1".
6700     * This could be an ARM instruction or a function call.  (If the result
6701     * comes back in a register other than w0, you can override "result".)
6702     *
6703     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6704     * vCC (w1).  Useful for integer division and modulus.  Note that we
6705     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6706     * handles it correctly.
6707     *
6708     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6709     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6710     *      mul-float, div-float, rem-float
6711     */
6712    /* binop vAA, vBB, vCC */
6713    FETCH w0, 1                         // w0<- CCBB
6714    lsr     w9, wINST, #8               // w9<- AA
6715    lsr     w3, w0, #8                  // w3<- CC
6716    and     w2, w0, #255                // w2<- BB
6717    GET_VREG w1, w3                     // w1<- vCC
6718    GET_VREG w0, w2                     // w0<- vBB
6719    .if 0
6720    cbz     w1, common_errDivideByZero  // is second operand zero?
6721    .endif
6722    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6723                               // optional op; may set condition codes
6724    sub     w0, w0, w1                              // w0<- op, w0-w3 changed
6725    GET_INST_OPCODE ip                  // extract opcode from rINST
6726    SET_VREG w0, w9                // vAA<- w0
6727    GOTO_OPCODE ip                      // jump to next instruction
6728    /* 11-14 instructions */
6729
6730    NAME_END nterp_op_sub_int
6731    // Advance to the end of this handler. Causes error if we are past that point.
6732    .org nterp_op_sub_int + NTERP_HANDLER_SIZE  // op_sub_int handler is too big!
6733
6734/* ------------------------------ */
6735    .balign NTERP_HANDLER_SIZE
6736.L_op_mul_int: /* 0x92 */
6737    NAME_START nterp_op_mul_int
6738    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6739    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6740
6741/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
6742    /*
6743     * Generic 32-bit binary operation.  Provide an "instr" line that
6744     * specifies an instruction that performs "result = w0 op w1".
6745     * This could be an ARM instruction or a function call.  (If the result
6746     * comes back in a register other than w0, you can override "result".)
6747     *
6748     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6749     * vCC (w1).  Useful for integer division and modulus.  Note that we
6750     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6751     * handles it correctly.
6752     *
6753     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6754     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6755     *      mul-float, div-float, rem-float
6756     */
6757    /* binop vAA, vBB, vCC */
6758    FETCH w0, 1                         // w0<- CCBB
6759    lsr     w9, wINST, #8               // w9<- AA
6760    lsr     w3, w0, #8                  // w3<- CC
6761    and     w2, w0, #255                // w2<- BB
6762    GET_VREG w1, w3                     // w1<- vCC
6763    GET_VREG w0, w2                     // w0<- vBB
6764    .if 0
6765    cbz     w1, common_errDivideByZero  // is second operand zero?
6766    .endif
6767    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6768                               // optional op; may set condition codes
6769    mul     w0, w1, w0                              // w0<- op, w0-w3 changed
6770    GET_INST_OPCODE ip                  // extract opcode from rINST
6771    SET_VREG w0, w9                // vAA<- w0
6772    GOTO_OPCODE ip                      // jump to next instruction
6773    /* 11-14 instructions */
6774
6775    NAME_END nterp_op_mul_int
6776    // Advance to the end of this handler. Causes error if we are past that point.
6777    .org nterp_op_mul_int + NTERP_HANDLER_SIZE  // op_mul_int handler is too big!
6778
6779/* ------------------------------ */
6780    .balign NTERP_HANDLER_SIZE
6781.L_op_div_int: /* 0x93 */
6782    NAME_START nterp_op_div_int
6783    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6784    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6785
6786    /*
6787     * Generic 32-bit binary operation.  Provide an "instr" line that
6788     * specifies an instruction that performs "result = w0 op w1".
6789     * This could be an ARM instruction or a function call.  (If the result
6790     * comes back in a register other than w0, you can override "result".)
6791     *
6792     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6793     * vCC (w1).  Useful for integer division and modulus.  Note that we
6794     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6795     * handles it correctly.
6796     *
6797     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6798     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6799     *      mul-float, div-float, rem-float
6800     */
6801    /* binop vAA, vBB, vCC */
6802    FETCH w0, 1                         // w0<- CCBB
6803    lsr     w9, wINST, #8               // w9<- AA
6804    lsr     w3, w0, #8                  // w3<- CC
6805    and     w2, w0, #255                // w2<- BB
6806    GET_VREG w1, w3                     // w1<- vCC
6807    GET_VREG w0, w2                     // w0<- vBB
6808    .if 1
6809    cbz     w1, common_errDivideByZero  // is second operand zero?
6810    .endif
6811    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6812                               // optional op; may set condition codes
6813    sdiv     w0, w0, w1                              // w0<- op, w0-w3 changed
6814    GET_INST_OPCODE ip                  // extract opcode from rINST
6815    SET_VREG w0, w9                // vAA<- w0
6816    GOTO_OPCODE ip                      // jump to next instruction
6817    /* 11-14 instructions */
6818
6819    NAME_END nterp_op_div_int
6820    // Advance to the end of this handler. Causes error if we are past that point.
6821    .org nterp_op_div_int + NTERP_HANDLER_SIZE  // op_div_int handler is too big!
6822
6823/* ------------------------------ */
6824    .balign NTERP_HANDLER_SIZE
6825.L_op_rem_int: /* 0x94 */
6826    NAME_START nterp_op_rem_int
6827    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6828    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6829
6830    /*
6831     * Generic 32-bit binary operation.  Provide an "instr" line that
6832     * specifies an instruction that performs "result = w0 op w1".
6833     * This could be an ARM instruction or a function call.  (If the result
6834     * comes back in a register other than w0, you can override "result".)
6835     *
6836     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6837     * vCC (w1).  Useful for integer division and modulus.  Note that we
6838     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6839     * handles it correctly.
6840     *
6841     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6842     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6843     *      mul-float, div-float, rem-float
6844     */
6845    /* binop vAA, vBB, vCC */
6846    FETCH w0, 1                         // w0<- CCBB
6847    lsr     w9, wINST, #8               // w9<- AA
6848    lsr     w3, w0, #8                  // w3<- CC
6849    and     w2, w0, #255                // w2<- BB
6850    GET_VREG w1, w3                     // w1<- vCC
6851    GET_VREG w0, w2                     // w0<- vBB
6852    .if 1
6853    cbz     w1, common_errDivideByZero  // is second operand zero?
6854    .endif
6855    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6856    sdiv     w2, w0, w1                           // optional op; may set condition codes
6857    msub w0, w2, w1, w0                              // w0<- op, w0-w3 changed
6858    GET_INST_OPCODE ip                  // extract opcode from rINST
6859    SET_VREG w0, w9                // vAA<- w0
6860    GOTO_OPCODE ip                      // jump to next instruction
6861    /* 11-14 instructions */
6862
6863    NAME_END nterp_op_rem_int
6864    // Advance to the end of this handler. Causes error if we are past that point.
6865    .org nterp_op_rem_int + NTERP_HANDLER_SIZE  // op_rem_int handler is too big!
6866
6867/* ------------------------------ */
6868    .balign NTERP_HANDLER_SIZE
6869.L_op_and_int: /* 0x95 */
6870    NAME_START nterp_op_and_int
6871    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6872    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6873
6874    /*
6875     * Generic 32-bit binary operation.  Provide an "instr" line that
6876     * specifies an instruction that performs "result = w0 op w1".
6877     * This could be an ARM instruction or a function call.  (If the result
6878     * comes back in a register other than w0, you can override "result".)
6879     *
6880     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6881     * vCC (w1).  Useful for integer division and modulus.  Note that we
6882     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6883     * handles it correctly.
6884     *
6885     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6886     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6887     *      mul-float, div-float, rem-float
6888     */
6889    /* binop vAA, vBB, vCC */
6890    FETCH w0, 1                         // w0<- CCBB
6891    lsr     w9, wINST, #8               // w9<- AA
6892    lsr     w3, w0, #8                  // w3<- CC
6893    and     w2, w0, #255                // w2<- BB
6894    GET_VREG w1, w3                     // w1<- vCC
6895    GET_VREG w0, w2                     // w0<- vBB
6896    .if 0
6897    cbz     w1, common_errDivideByZero  // is second operand zero?
6898    .endif
6899    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6900                               // optional op; may set condition codes
6901    and     w0, w0, w1                              // w0<- op, w0-w3 changed
6902    GET_INST_OPCODE ip                  // extract opcode from rINST
6903    SET_VREG w0, w9                // vAA<- w0
6904    GOTO_OPCODE ip                      // jump to next instruction
6905    /* 11-14 instructions */
6906
6907    NAME_END nterp_op_and_int
6908    // Advance to the end of this handler. Causes error if we are past that point.
6909    .org nterp_op_and_int + NTERP_HANDLER_SIZE  // op_and_int handler is too big!
6910
6911/* ------------------------------ */
6912    .balign NTERP_HANDLER_SIZE
6913.L_op_or_int: /* 0x96 */
6914    NAME_START nterp_op_or_int
6915    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6916    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6917
6918    /*
6919     * Generic 32-bit binary operation.  Provide an "instr" line that
6920     * specifies an instruction that performs "result = w0 op w1".
6921     * This could be an ARM instruction or a function call.  (If the result
6922     * comes back in a register other than w0, you can override "result".)
6923     *
6924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6925     * vCC (w1).  Useful for integer division and modulus.  Note that we
6926     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6927     * handles it correctly.
6928     *
6929     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6930     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6931     *      mul-float, div-float, rem-float
6932     */
6933    /* binop vAA, vBB, vCC */
6934    FETCH w0, 1                         // w0<- CCBB
6935    lsr     w9, wINST, #8               // w9<- AA
6936    lsr     w3, w0, #8                  // w3<- CC
6937    and     w2, w0, #255                // w2<- BB
6938    GET_VREG w1, w3                     // w1<- vCC
6939    GET_VREG w0, w2                     // w0<- vBB
6940    .if 0
6941    cbz     w1, common_errDivideByZero  // is second operand zero?
6942    .endif
6943    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6944                               // optional op; may set condition codes
6945    orr     w0, w0, w1                              // w0<- op, w0-w3 changed
6946    GET_INST_OPCODE ip                  // extract opcode from rINST
6947    SET_VREG w0, w9                // vAA<- w0
6948    GOTO_OPCODE ip                      // jump to next instruction
6949    /* 11-14 instructions */
6950
6951    NAME_END nterp_op_or_int
6952    // Advance to the end of this handler. Causes error if we are past that point.
6953    .org nterp_op_or_int + NTERP_HANDLER_SIZE  // op_or_int handler is too big!
6954
6955/* ------------------------------ */
6956    .balign NTERP_HANDLER_SIZE
6957.L_op_xor_int: /* 0x97 */
6958    NAME_START nterp_op_xor_int
6959    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
6960    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
6961
6962    /*
6963     * Generic 32-bit binary operation.  Provide an "instr" line that
6964     * specifies an instruction that performs "result = w0 op w1".
6965     * This could be an ARM instruction or a function call.  (If the result
6966     * comes back in a register other than w0, you can override "result".)
6967     *
6968     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6969     * vCC (w1).  Useful for integer division and modulus.  Note that we
6970     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
6971     * handles it correctly.
6972     *
6973     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
6974     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
6975     *      mul-float, div-float, rem-float
6976     */
6977    /* binop vAA, vBB, vCC */
6978    FETCH w0, 1                         // w0<- CCBB
6979    lsr     w9, wINST, #8               // w9<- AA
6980    lsr     w3, w0, #8                  // w3<- CC
6981    and     w2, w0, #255                // w2<- BB
6982    GET_VREG w1, w3                     // w1<- vCC
6983    GET_VREG w0, w2                     // w0<- vBB
6984    .if 0
6985    cbz     w1, common_errDivideByZero  // is second operand zero?
6986    .endif
6987    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
6988                               // optional op; may set condition codes
6989    eor     w0, w0, w1                              // w0<- op, w0-w3 changed
6990    GET_INST_OPCODE ip                  // extract opcode from rINST
6991    SET_VREG w0, w9                // vAA<- w0
6992    GOTO_OPCODE ip                      // jump to next instruction
6993    /* 11-14 instructions */
6994
6995    NAME_END nterp_op_xor_int
6996    // Advance to the end of this handler. Causes error if we are past that point.
6997    .org nterp_op_xor_int + NTERP_HANDLER_SIZE  // op_xor_int handler is too big!
6998
6999/* ------------------------------ */
7000    .balign NTERP_HANDLER_SIZE
7001.L_op_shl_int: /* 0x98 */
7002    NAME_START nterp_op_shl_int
7003    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7004    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7005
7006    /*
7007     * Generic 32-bit binary operation.  Provide an "instr" line that
7008     * specifies an instruction that performs "result = w0 op w1".
7009     * This could be an ARM instruction or a function call.  (If the result
7010     * comes back in a register other than w0, you can override "result".)
7011     *
7012     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7013     * vCC (w1).  Useful for integer division and modulus.  Note that we
7014     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
7015     * handles it correctly.
7016     *
7017     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
7018     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
7019     *      mul-float, div-float, rem-float
7020     */
7021    /* binop vAA, vBB, vCC */
7022    FETCH w0, 1                         // w0<- CCBB
7023    lsr     w9, wINST, #8               // w9<- AA
7024    lsr     w3, w0, #8                  // w3<- CC
7025    and     w2, w0, #255                // w2<- BB
7026    GET_VREG w1, w3                     // w1<- vCC
7027    GET_VREG w0, w2                     // w0<- vBB
7028    .if 0
7029    cbz     w1, common_errDivideByZero  // is second operand zero?
7030    .endif
7031    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7032                               // optional op; may set condition codes
7033    lsl     w0, w0, w1                              // w0<- op, w0-w3 changed
7034    GET_INST_OPCODE ip                  // extract opcode from rINST
7035    SET_VREG w0, w9                // vAA<- w0
7036    GOTO_OPCODE ip                      // jump to next instruction
7037    /* 11-14 instructions */
7038
7039    NAME_END nterp_op_shl_int
7040    // Advance to the end of this handler. Causes error if we are past that point.
7041    .org nterp_op_shl_int + NTERP_HANDLER_SIZE  // op_shl_int handler is too big!
7042
7043/* ------------------------------ */
7044    .balign NTERP_HANDLER_SIZE
7045.L_op_shr_int: /* 0x99 */
7046    NAME_START nterp_op_shr_int
7047    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7048    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7049
7050    /*
7051     * Generic 32-bit binary operation.  Provide an "instr" line that
7052     * specifies an instruction that performs "result = w0 op w1".
7053     * This could be an ARM instruction or a function call.  (If the result
7054     * comes back in a register other than w0, you can override "result".)
7055     *
7056     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7057     * vCC (w1).  Useful for integer division and modulus.  Note that we
7058     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
7059     * handles it correctly.
7060     *
7061     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
7062     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
7063     *      mul-float, div-float, rem-float
7064     */
7065    /* binop vAA, vBB, vCC */
7066    FETCH w0, 1                         // w0<- CCBB
7067    lsr     w9, wINST, #8               // w9<- AA
7068    lsr     w3, w0, #8                  // w3<- CC
7069    and     w2, w0, #255                // w2<- BB
7070    GET_VREG w1, w3                     // w1<- vCC
7071    GET_VREG w0, w2                     // w0<- vBB
7072    .if 0
7073    cbz     w1, common_errDivideByZero  // is second operand zero?
7074    .endif
7075    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7076                               // optional op; may set condition codes
7077    asr     w0, w0, w1                              // w0<- op, w0-w3 changed
7078    GET_INST_OPCODE ip                  // extract opcode from rINST
7079    SET_VREG w0, w9                // vAA<- w0
7080    GOTO_OPCODE ip                      // jump to next instruction
7081    /* 11-14 instructions */
7082
7083    NAME_END nterp_op_shr_int
7084    // Advance to the end of this handler. Causes error if we are past that point.
7085    .org nterp_op_shr_int + NTERP_HANDLER_SIZE  // op_shr_int handler is too big!
7086
7087/* ------------------------------ */
7088    .balign NTERP_HANDLER_SIZE
7089.L_op_ushr_int: /* 0x9a */
7090    NAME_START nterp_op_ushr_int
7091    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7092    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7093
7094    /*
7095     * Generic 32-bit binary operation.  Provide an "instr" line that
7096     * specifies an instruction that performs "result = w0 op w1".
7097     * This could be an ARM instruction or a function call.  (If the result
7098     * comes back in a register other than w0, you can override "result".)
7099     *
7100     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7101     * vCC (w1).  Useful for integer division and modulus.  Note that we
7102     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
7103     * handles it correctly.
7104     *
7105     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
7106     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
7107     *      mul-float, div-float, rem-float
7108     */
7109    /* binop vAA, vBB, vCC */
7110    FETCH w0, 1                         // w0<- CCBB
7111    lsr     w9, wINST, #8               // w9<- AA
7112    lsr     w3, w0, #8                  // w3<- CC
7113    and     w2, w0, #255                // w2<- BB
7114    GET_VREG w1, w3                     // w1<- vCC
7115    GET_VREG w0, w2                     // w0<- vBB
7116    .if 0
7117    cbz     w1, common_errDivideByZero  // is second operand zero?
7118    .endif
7119    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7120                               // optional op; may set condition codes
7121    lsr     w0, w0, w1                              // w0<- op, w0-w3 changed
7122    GET_INST_OPCODE ip                  // extract opcode from rINST
7123    SET_VREG w0, w9                // vAA<- w0
7124    GOTO_OPCODE ip                      // jump to next instruction
7125    /* 11-14 instructions */
7126
7127    NAME_END nterp_op_ushr_int
7128    // Advance to the end of this handler. Causes error if we are past that point.
7129    .org nterp_op_ushr_int + NTERP_HANDLER_SIZE  // op_ushr_int handler is too big!
7130
7131/* ------------------------------ */
7132    .balign NTERP_HANDLER_SIZE
7133.L_op_add_long: /* 0x9b */
7134    NAME_START nterp_op_add_long
7135    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7136    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7137
7138    /*
7139     * Generic 64-bit binary operation.  Provide an "instr" line that
7140     * specifies an instruction that performs "result = x1 op x2".
7141     * This could be an ARM instruction or a function call.  (If the result
7142     * comes back in a register other than x0, you can override "result".)
7143     *
7144     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7145     * vCC (w1).  Useful for integer division and modulus.
7146     *
7147     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7148     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7149     */
7150    /* binop vAA, vBB, vCC */
7151    FETCH w0, 1                           // w0<- CCBB
7152    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7153    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7154    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7155    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7156    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7157    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7158    .if 0
7159    cbz     x2, common_errDivideByZero   // is second operand zero?
7160    .endif
7161    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7162
7163    add x0, x1, x2                                // x0<- op, w0-w4 changed
7164    GET_INST_OPCODE ip                    // extract opcode from rINST
7165    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7166    GOTO_OPCODE ip                        // jump to next instruction
7167    /* 11-14 instructions */
7168
7169    NAME_END nterp_op_add_long
7170    // Advance to the end of this handler. Causes error if we are past that point.
7171    .org nterp_op_add_long + NTERP_HANDLER_SIZE  // op_add_long handler is too big!
7172
7173/* ------------------------------ */
7174    .balign NTERP_HANDLER_SIZE
7175.L_op_sub_long: /* 0x9c */
7176    NAME_START nterp_op_sub_long
7177    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7178    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7179
7180    /*
7181     * Generic 64-bit binary operation.  Provide an "instr" line that
7182     * specifies an instruction that performs "result = x1 op x2".
7183     * This could be an ARM instruction or a function call.  (If the result
7184     * comes back in a register other than x0, you can override "result".)
7185     *
7186     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7187     * vCC (w1).  Useful for integer division and modulus.
7188     *
7189     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7190     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7191     */
7192    /* binop vAA, vBB, vCC */
7193    FETCH w0, 1                           // w0<- CCBB
7194    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7195    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7196    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7197    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7198    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7199    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7200    .if 0
7201    cbz     x2, common_errDivideByZero   // is second operand zero?
7202    .endif
7203    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7204
7205    sub x0, x1, x2                                // x0<- op, w0-w4 changed
7206    GET_INST_OPCODE ip                    // extract opcode from rINST
7207    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7208    GOTO_OPCODE ip                        // jump to next instruction
7209    /* 11-14 instructions */
7210
7211    NAME_END nterp_op_sub_long
7212    // Advance to the end of this handler. Causes error if we are past that point.
7213    .org nterp_op_sub_long + NTERP_HANDLER_SIZE  // op_sub_long handler is too big!
7214
7215/* ------------------------------ */
7216    .balign NTERP_HANDLER_SIZE
7217.L_op_mul_long: /* 0x9d */
7218    NAME_START nterp_op_mul_long
7219    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7220    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7221
7222    /*
7223     * Generic 64-bit binary operation.  Provide an "instr" line that
7224     * specifies an instruction that performs "result = x1 op x2".
7225     * This could be an ARM instruction or a function call.  (If the result
7226     * comes back in a register other than x0, you can override "result".)
7227     *
7228     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7229     * vCC (w1).  Useful for integer division and modulus.
7230     *
7231     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7232     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7233     */
7234    /* binop vAA, vBB, vCC */
7235    FETCH w0, 1                           // w0<- CCBB
7236    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7237    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7238    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7239    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7240    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7241    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7242    .if 0
7243    cbz     x2, common_errDivideByZero   // is second operand zero?
7244    .endif
7245    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7246
7247    mul x0, x1, x2                                // x0<- op, w0-w4 changed
7248    GET_INST_OPCODE ip                    // extract opcode from rINST
7249    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7250    GOTO_OPCODE ip                        // jump to next instruction
7251    /* 11-14 instructions */
7252
7253    NAME_END nterp_op_mul_long
7254    // Advance to the end of this handler. Causes error if we are past that point.
7255    .org nterp_op_mul_long + NTERP_HANDLER_SIZE  // op_mul_long handler is too big!
7256
7257/* ------------------------------ */
7258    .balign NTERP_HANDLER_SIZE
7259.L_op_div_long: /* 0x9e */
7260    NAME_START nterp_op_div_long
7261    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7262    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7263
7264    /*
7265     * Generic 64-bit binary operation.  Provide an "instr" line that
7266     * specifies an instruction that performs "result = x1 op x2".
7267     * This could be an ARM instruction or a function call.  (If the result
7268     * comes back in a register other than x0, you can override "result".)
7269     *
7270     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7271     * vCC (w1).  Useful for integer division and modulus.
7272     *
7273     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7274     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7275     */
7276    /* binop vAA, vBB, vCC */
7277    FETCH w0, 1                           // w0<- CCBB
7278    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7279    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7280    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7281    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7282    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7283    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7284    .if 1
7285    cbz     x2, common_errDivideByZero   // is second operand zero?
7286    .endif
7287    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7288
7289    sdiv x0, x1, x2                                // x0<- op, w0-w4 changed
7290    GET_INST_OPCODE ip                    // extract opcode from rINST
7291    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7292    GOTO_OPCODE ip                        // jump to next instruction
7293    /* 11-14 instructions */
7294
7295    NAME_END nterp_op_div_long
7296    // Advance to the end of this handler. Causes error if we are past that point.
7297    .org nterp_op_div_long + NTERP_HANDLER_SIZE  // op_div_long handler is too big!
7298
7299/* ------------------------------ */
7300    .balign NTERP_HANDLER_SIZE
7301.L_op_rem_long: /* 0x9f */
7302    NAME_START nterp_op_rem_long
7303    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7304    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7305
7306    /*
7307     * Generic 64-bit binary operation.  Provide an "instr" line that
7308     * specifies an instruction that performs "result = x1 op x2".
7309     * This could be an ARM instruction or a function call.  (If the result
7310     * comes back in a register other than x0, you can override "result".)
7311     *
7312     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7313     * vCC (w1).  Useful for integer division and modulus.
7314     *
7315     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7316     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7317     */
7318    /* binop vAA, vBB, vCC */
7319    FETCH w0, 1                           // w0<- CCBB
7320    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7321    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7322    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7323    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7324    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7325    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7326    .if 1
7327    cbz     x2, common_errDivideByZero   // is second operand zero?
7328    .endif
7329    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7330    sdiv x3, x1, x2
7331    msub x0, x3, x2, x1                                // x0<- op, w0-w4 changed
7332    GET_INST_OPCODE ip                    // extract opcode from rINST
7333    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7334    GOTO_OPCODE ip                        // jump to next instruction
7335    /* 11-14 instructions */
7336
7337    NAME_END nterp_op_rem_long
7338    // Advance to the end of this handler. Causes error if we are past that point.
7339    .org nterp_op_rem_long + NTERP_HANDLER_SIZE  // op_rem_long handler is too big!
7340
7341/* ------------------------------ */
7342    .balign NTERP_HANDLER_SIZE
7343.L_op_and_long: /* 0xa0 */
7344    NAME_START nterp_op_and_long
7345    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7346    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7347
7348    /*
7349     * Generic 64-bit binary operation.  Provide an "instr" line that
7350     * specifies an instruction that performs "result = x1 op x2".
7351     * This could be an ARM instruction or a function call.  (If the result
7352     * comes back in a register other than x0, you can override "result".)
7353     *
7354     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7355     * vCC (w1).  Useful for integer division and modulus.
7356     *
7357     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7358     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7359     */
7360    /* binop vAA, vBB, vCC */
7361    FETCH w0, 1                           // w0<- CCBB
7362    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7363    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7364    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7365    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7366    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7367    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7368    .if 0
7369    cbz     x2, common_errDivideByZero   // is second operand zero?
7370    .endif
7371    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7372
7373    and x0, x1, x2                                // x0<- op, w0-w4 changed
7374    GET_INST_OPCODE ip                    // extract opcode from rINST
7375    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7376    GOTO_OPCODE ip                        // jump to next instruction
7377    /* 11-14 instructions */
7378
7379    NAME_END nterp_op_and_long
7380    // Advance to the end of this handler. Causes error if we are past that point.
7381    .org nterp_op_and_long + NTERP_HANDLER_SIZE  // op_and_long handler is too big!
7382
7383/* ------------------------------ */
7384    .balign NTERP_HANDLER_SIZE
7385.L_op_or_long: /* 0xa1 */
7386    NAME_START nterp_op_or_long
7387    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7388    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7389
7390    /*
7391     * Generic 64-bit binary operation.  Provide an "instr" line that
7392     * specifies an instruction that performs "result = x1 op x2".
7393     * This could be an ARM instruction or a function call.  (If the result
7394     * comes back in a register other than x0, you can override "result".)
7395     *
7396     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7397     * vCC (w1).  Useful for integer division and modulus.
7398     *
7399     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7400     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7401     */
7402    /* binop vAA, vBB, vCC */
7403    FETCH w0, 1                           // w0<- CCBB
7404    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7405    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7406    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7407    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7408    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7409    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7410    .if 0
7411    cbz     x2, common_errDivideByZero   // is second operand zero?
7412    .endif
7413    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7414
7415    orr x0, x1, x2                                // x0<- op, w0-w4 changed
7416    GET_INST_OPCODE ip                    // extract opcode from rINST
7417    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7418    GOTO_OPCODE ip                        // jump to next instruction
7419    /* 11-14 instructions */
7420
7421    NAME_END nterp_op_or_long
7422    // Advance to the end of this handler. Causes error if we are past that point.
7423    .org nterp_op_or_long + NTERP_HANDLER_SIZE  // op_or_long handler is too big!
7424
7425/* ------------------------------ */
7426    .balign NTERP_HANDLER_SIZE
7427.L_op_xor_long: /* 0xa2 */
7428    NAME_START nterp_op_xor_long
7429    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7430    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7431
7432    /*
7433     * Generic 64-bit binary operation.  Provide an "instr" line that
7434     * specifies an instruction that performs "result = x1 op x2".
7435     * This could be an ARM instruction or a function call.  (If the result
7436     * comes back in a register other than x0, you can override "result".)
7437     *
7438     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7439     * vCC (w1).  Useful for integer division and modulus.
7440     *
7441     * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
7442     *      xor-long, add-double, sub-double, mul-double, div-double, rem-double
7443     */
7444    /* binop vAA, vBB, vCC */
7445    FETCH w0, 1                           // w0<- CCBB
7446    LOAD_SCALED_VREG_MASK w5, 0xff        // w5<- ff * sizeof(vreg)
7447    EXTRACT_SCALED_VREG w4, w5, wINST, 8  // w4<- AA * sizeof(vreg)
7448    EXTRACT_SCALED_VREG w2, w5, w0, 8     // w2<- CC * sizeof(vreg)
7449    EXTRACT_SCALED_VREG w1, w5, w0, 0     // w1<- BB * sizeof(vreg)
7450    GET_VREG_WIDE_PRESCALED x2, w2       // w2<- vCC
7451    GET_VREG_WIDE_PRESCALED x1, w1       // w1<- vBB
7452    .if 0
7453    cbz     x2, common_errDivideByZero   // is second operand zero?
7454    .endif
7455    FETCH_ADVANCE_INST 2                  // advance rPC, load rINST
7456
7457    eor x0, x1, x2                                // x0<- op, w0-w4 changed
7458    GET_INST_OPCODE ip                    // extract opcode from rINST
7459    SET_VREG_WIDE_PRESCALED x0, w4   // vAA<- x0
7460    GOTO_OPCODE ip                        // jump to next instruction
7461    /* 11-14 instructions */
7462
7463    NAME_END nterp_op_xor_long
7464    // Advance to the end of this handler. Causes error if we are past that point.
7465    .org nterp_op_xor_long + NTERP_HANDLER_SIZE  // op_xor_long handler is too big!
7466
7467/* ------------------------------ */
7468    .balign NTERP_HANDLER_SIZE
7469.L_op_shl_long: /* 0xa3 */
7470    NAME_START nterp_op_shl_long
7471    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7472    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7473
7474    /*
7475     * 64-bit shift operation.
7476     *
7477     * For: shl-long, shr-long, ushr-long
7478     */
7479    /* binop vAA, vBB, vCC */
7480    FETCH w0, 1                         // w0<- CCBB
7481    lsr      w3, wINST, #8               // w3<- AA
7482    lsr      w2, w0, #8                  // w2<- CC
7483    GET_VREG w2, w2                     // w2<- vCC (shift count)
7484    and      w1, w0, #255                // w1<- BB
7485    GET_VREG_WIDE x1, w1                // x1<- vBB
7486    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7487    lsl  x0, x1, x2                 // Do the shift. Only low 6 bits of x2 are used.
7488    GET_INST_OPCODE ip                  // extract opcode from rINST
7489    SET_VREG_WIDE x0, w3                // vAA<- x0
7490    GOTO_OPCODE ip                      // jump to next instruction
7491    /* 11-14 instructions */
7492
7493    NAME_END nterp_op_shl_long
7494    // Advance to the end of this handler. Causes error if we are past that point.
7495    .org nterp_op_shl_long + NTERP_HANDLER_SIZE  // op_shl_long handler is too big!
7496
7497/* ------------------------------ */
7498    .balign NTERP_HANDLER_SIZE
7499.L_op_shr_long: /* 0xa4 */
7500    NAME_START nterp_op_shr_long
7501    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7502    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7503
7504    /*
7505     * 64-bit shift operation.
7506     *
7507     * For: shl-long, shr-long, ushr-long
7508     */
7509    /* binop vAA, vBB, vCC */
7510    FETCH w0, 1                         // w0<- CCBB
7511    lsr      w3, wINST, #8               // w3<- AA
7512    lsr      w2, w0, #8                  // w2<- CC
7513    GET_VREG w2, w2                     // w2<- vCC (shift count)
7514    and      w1, w0, #255                // w1<- BB
7515    GET_VREG_WIDE x1, w1                // x1<- vBB
7516    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7517    asr  x0, x1, x2                 // Do the shift. Only low 6 bits of x2 are used.
7518    GET_INST_OPCODE ip                  // extract opcode from rINST
7519    SET_VREG_WIDE x0, w3                // vAA<- x0
7520    GOTO_OPCODE ip                      // jump to next instruction
7521    /* 11-14 instructions */
7522
7523    NAME_END nterp_op_shr_long
7524    // Advance to the end of this handler. Causes error if we are past that point.
7525    .org nterp_op_shr_long + NTERP_HANDLER_SIZE  // op_shr_long handler is too big!
7526
7527/* ------------------------------ */
7528    .balign NTERP_HANDLER_SIZE
7529.L_op_ushr_long: /* 0xa5 */
7530    NAME_START nterp_op_ushr_long
7531    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7532    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7533
7534    /*
7535     * 64-bit shift operation.
7536     *
7537     * For: shl-long, shr-long, ushr-long
7538     */
7539    /* binop vAA, vBB, vCC */
7540    FETCH w0, 1                         // w0<- CCBB
7541    lsr      w3, wINST, #8               // w3<- AA
7542    lsr      w2, w0, #8                  // w2<- CC
7543    GET_VREG w2, w2                     // w2<- vCC (shift count)
7544    and      w1, w0, #255                // w1<- BB
7545    GET_VREG_WIDE x1, w1                // x1<- vBB
7546    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7547    lsr  x0, x1, x2                 // Do the shift. Only low 6 bits of x2 are used.
7548    GET_INST_OPCODE ip                  // extract opcode from rINST
7549    SET_VREG_WIDE x0, w3                // vAA<- x0
7550    GOTO_OPCODE ip                      // jump to next instruction
7551    /* 11-14 instructions */
7552
7553    NAME_END nterp_op_ushr_long
7554    // Advance to the end of this handler. Causes error if we are past that point.
7555    .org nterp_op_ushr_long + NTERP_HANDLER_SIZE  // op_ushr_long handler is too big!
7556
7557/* ------------------------------ */
7558    .balign NTERP_HANDLER_SIZE
7559.L_op_add_float: /* 0xa6 */
7560    NAME_START nterp_op_add_float
7561    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7562    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7563
7564    /*
7565     * Generic 32-bit floating-point operation.
7566     *
7567     * For: add-float, sub-float, mul-float, div-float
7568     * form: <op> s0, s0, s1
7569     */
7570    /* floatop vAA, vBB, vCC */
7571    FETCH w0, 1                         // r0<- CCBB
7572    lsr     w1, w0, #8                  // r2<- CC
7573    and     w0, w0, #255                // r1<- BB
7574    GET_VREG  s1, w1
7575    GET_VREG  s0, w0
7576    fadd   s0, s0, s1                              // s0<- op
7577    lsr     w1, wINST, #8               // r1<- AA
7578    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7579    GET_INST_OPCODE ip                  // extract opcode from rINST
7580    SET_VREG_FLOAT s0, w1
7581    GOTO_OPCODE ip                      // jump to next instruction
7582
7583    NAME_END nterp_op_add_float
7584    // Advance to the end of this handler. Causes error if we are past that point.
7585    .org nterp_op_add_float + NTERP_HANDLER_SIZE  // op_add_float handler is too big!
7586
7587/* ------------------------------ */
7588    .balign NTERP_HANDLER_SIZE
7589.L_op_sub_float: /* 0xa7 */
7590    NAME_START nterp_op_sub_float
7591    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7592    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7593
7594    /*
7595     * Generic 32-bit floating-point operation.
7596     *
7597     * For: add-float, sub-float, mul-float, div-float
7598     * form: <op> s0, s0, s1
7599     */
7600    /* floatop vAA, vBB, vCC */
7601    FETCH w0, 1                         // r0<- CCBB
7602    lsr     w1, w0, #8                  // r2<- CC
7603    and     w0, w0, #255                // r1<- BB
7604    GET_VREG  s1, w1
7605    GET_VREG  s0, w0
7606    fsub   s0, s0, s1                              // s0<- op
7607    lsr     w1, wINST, #8               // r1<- AA
7608    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7609    GET_INST_OPCODE ip                  // extract opcode from rINST
7610    SET_VREG_FLOAT s0, w1
7611    GOTO_OPCODE ip                      // jump to next instruction
7612
7613    NAME_END nterp_op_sub_float
7614    // Advance to the end of this handler. Causes error if we are past that point.
7615    .org nterp_op_sub_float + NTERP_HANDLER_SIZE  // op_sub_float handler is too big!
7616
7617/* ------------------------------ */
7618    .balign NTERP_HANDLER_SIZE
7619.L_op_mul_float: /* 0xa8 */
7620    NAME_START nterp_op_mul_float
7621    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7622    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7623
7624    /*
7625     * Generic 32-bit floating-point operation.
7626     *
7627     * For: add-float, sub-float, mul-float, div-float
7628     * form: <op> s0, s0, s1
7629     */
7630    /* floatop vAA, vBB, vCC */
7631    FETCH w0, 1                         // r0<- CCBB
7632    lsr     w1, w0, #8                  // r2<- CC
7633    and     w0, w0, #255                // r1<- BB
7634    GET_VREG  s1, w1
7635    GET_VREG  s0, w0
7636    fmul   s0, s0, s1                              // s0<- op
7637    lsr     w1, wINST, #8               // r1<- AA
7638    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7639    GET_INST_OPCODE ip                  // extract opcode from rINST
7640    SET_VREG_FLOAT s0, w1
7641    GOTO_OPCODE ip                      // jump to next instruction
7642
7643    NAME_END nterp_op_mul_float
7644    // Advance to the end of this handler. Causes error if we are past that point.
7645    .org nterp_op_mul_float + NTERP_HANDLER_SIZE  // op_mul_float handler is too big!
7646
7647/* ------------------------------ */
7648    .balign NTERP_HANDLER_SIZE
7649.L_op_div_float: /* 0xa9 */
7650    NAME_START nterp_op_div_float
7651    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7652    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7653
7654    /*
7655     * Generic 32-bit floating-point operation.
7656     *
7657     * For: add-float, sub-float, mul-float, div-float
7658     * form: <op> s0, s0, s1
7659     */
7660    /* floatop vAA, vBB, vCC */
7661    FETCH w0, 1                         // r0<- CCBB
7662    lsr     w1, w0, #8                  // r2<- CC
7663    and     w0, w0, #255                // r1<- BB
7664    GET_VREG  s1, w1
7665    GET_VREG  s0, w0
7666    fdiv   s0, s0, s1                              // s0<- op
7667    lsr     w1, wINST, #8               // r1<- AA
7668    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7669    GET_INST_OPCODE ip                  // extract opcode from rINST
7670    SET_VREG_FLOAT s0, w1
7671    GOTO_OPCODE ip                      // jump to next instruction
7672
7673    NAME_END nterp_op_div_float
7674    // Advance to the end of this handler. Causes error if we are past that point.
7675    .org nterp_op_div_float + NTERP_HANDLER_SIZE  // op_div_float handler is too big!
7676
7677/* ------------------------------ */
7678    .balign NTERP_HANDLER_SIZE
7679.L_op_rem_float: /* 0xaa */
7680    NAME_START nterp_op_rem_float
7681    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7682    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7683
7684/* EABI doesn't define a float remainder function, but libm does */
7685    /*
7686     * Generic 32-bit floating-point operation.
7687     *
7688     * For: add-float, sub-float, mul-float, div-float
7689     * form: <op> s0, s0, s1
7690     */
7691    /* floatop vAA, vBB, vCC */
7692    FETCH w0, 1                         // r0<- CCBB
7693    lsr     w1, w0, #8                  // r2<- CC
7694    and     w0, w0, #255                // r1<- BB
7695    GET_VREG  s1, w1
7696    GET_VREG  s0, w0
7697    bl      fmodf                              // s0<- op
7698    lsr     w1, wINST, #8               // r1<- AA
7699    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7700    GET_INST_OPCODE ip                  // extract opcode from rINST
7701    SET_VREG_FLOAT s0, w1
7702    GOTO_OPCODE ip                      // jump to next instruction
7703
7704    NAME_END nterp_op_rem_float
7705    // Advance to the end of this handler. Causes error if we are past that point.
7706    .org nterp_op_rem_float + NTERP_HANDLER_SIZE  // op_rem_float handler is too big!
7707
7708/* ------------------------------ */
7709    .balign NTERP_HANDLER_SIZE
7710.L_op_add_double: /* 0xab */
7711    NAME_START nterp_op_add_double
7712    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7713    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7714
7715    /*
7716     * Generic 64-bit floating-point operation.
7717     */
7718    /* binop vAA, vBB, vCC */
7719    FETCH w0, 1                         // w0<- CCBB
7720    lsr     w4, wINST, #8               // w4<- AA
7721    lsr     w2, w0, #8                  // w2<- CC
7722    and     w1, w0, #255                // w1<- BB
7723    GET_VREG_DOUBLE d2, w2             // w2<- vCC
7724    GET_VREG_DOUBLE d1, w1             // w1<- vBB
7725    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7726    fadd d0, d1, d2                              // d0<- op, w0-w4 changed
7727    GET_INST_OPCODE ip                  // extract opcode from rINST
7728    SET_VREG_DOUBLE d0, w4         // vAA<- d0
7729    GOTO_OPCODE ip                      // jump to next instruction
7730
7731    NAME_END nterp_op_add_double
7732    // Advance to the end of this handler. Causes error if we are past that point.
7733    .org nterp_op_add_double + NTERP_HANDLER_SIZE  // op_add_double handler is too big!
7734
7735/* ------------------------------ */
7736    .balign NTERP_HANDLER_SIZE
7737.L_op_sub_double: /* 0xac */
7738    NAME_START nterp_op_sub_double
7739    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7740    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7741
7742    /*
7743     * Generic 64-bit floating-point operation.
7744     */
7745    /* binop vAA, vBB, vCC */
7746    FETCH w0, 1                         // w0<- CCBB
7747    lsr     w4, wINST, #8               // w4<- AA
7748    lsr     w2, w0, #8                  // w2<- CC
7749    and     w1, w0, #255                // w1<- BB
7750    GET_VREG_DOUBLE d2, w2             // w2<- vCC
7751    GET_VREG_DOUBLE d1, w1             // w1<- vBB
7752    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7753    fsub d0, d1, d2                              // d0<- op, w0-w4 changed
7754    GET_INST_OPCODE ip                  // extract opcode from rINST
7755    SET_VREG_DOUBLE d0, w4         // vAA<- d0
7756    GOTO_OPCODE ip                      // jump to next instruction
7757
7758    NAME_END nterp_op_sub_double
7759    // Advance to the end of this handler. Causes error if we are past that point.
7760    .org nterp_op_sub_double + NTERP_HANDLER_SIZE  // op_sub_double handler is too big!
7761
7762/* ------------------------------ */
7763    .balign NTERP_HANDLER_SIZE
7764.L_op_mul_double: /* 0xad */
7765    NAME_START nterp_op_mul_double
7766    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7767    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7768
7769    /*
7770     * Generic 64-bit floating-point operation.
7771     */
7772    /* binop vAA, vBB, vCC */
7773    FETCH w0, 1                         // w0<- CCBB
7774    lsr     w4, wINST, #8               // w4<- AA
7775    lsr     w2, w0, #8                  // w2<- CC
7776    and     w1, w0, #255                // w1<- BB
7777    GET_VREG_DOUBLE d2, w2             // w2<- vCC
7778    GET_VREG_DOUBLE d1, w1             // w1<- vBB
7779    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7780    fmul d0, d1, d2                              // d0<- op, w0-w4 changed
7781    GET_INST_OPCODE ip                  // extract opcode from rINST
7782    SET_VREG_DOUBLE d0, w4         // vAA<- d0
7783    GOTO_OPCODE ip                      // jump to next instruction
7784
7785    NAME_END nterp_op_mul_double
7786    // Advance to the end of this handler. Causes error if we are past that point.
7787    .org nterp_op_mul_double + NTERP_HANDLER_SIZE  // op_mul_double handler is too big!
7788
7789/* ------------------------------ */
7790    .balign NTERP_HANDLER_SIZE
7791.L_op_div_double: /* 0xae */
7792    NAME_START nterp_op_div_double
7793    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7794    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7795
7796    /*
7797     * Generic 64-bit floating-point operation.
7798     */
7799    /* binop vAA, vBB, vCC */
7800    FETCH w0, 1                         // w0<- CCBB
7801    lsr     w4, wINST, #8               // w4<- AA
7802    lsr     w2, w0, #8                  // w2<- CC
7803    and     w1, w0, #255                // w1<- BB
7804    GET_VREG_DOUBLE d2, w2             // w2<- vCC
7805    GET_VREG_DOUBLE d1, w1             // w1<- vBB
7806    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7807    fdiv d0, d1, d2                              // d0<- op, w0-w4 changed
7808    GET_INST_OPCODE ip                  // extract opcode from rINST
7809    SET_VREG_DOUBLE d0, w4         // vAA<- d0
7810    GOTO_OPCODE ip                      // jump to next instruction
7811
7812    NAME_END nterp_op_div_double
7813    // Advance to the end of this handler. Causes error if we are past that point.
7814    .org nterp_op_div_double + NTERP_HANDLER_SIZE  // op_div_double handler is too big!
7815
7816/* ------------------------------ */
7817    .balign NTERP_HANDLER_SIZE
7818.L_op_rem_double: /* 0xaf */
7819    NAME_START nterp_op_rem_double
7820    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7821    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7822
7823    /* rem vAA, vBB, vCC */
7824    FETCH w0, 1                         // w0<- CCBB
7825    lsr     w2, w0, #8                  // w2<- CC
7826    and     w1, w0, #255                // w1<- BB
7827    GET_VREG_DOUBLE d1, w2              // d1<- vCC
7828    GET_VREG_DOUBLE d0, w1              // d0<- vBB
7829    bl  fmod
7830    lsr     w4, wINST, #8               // w4<- AA
7831    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
7832    GET_INST_OPCODE ip                  // extract opcode from rINST
7833    SET_VREG_WIDE d0, w4                // vAA<- result
7834    GOTO_OPCODE ip                      // jump to next instruction
7835    /* 11-14 instructions */
7836
7837    NAME_END nterp_op_rem_double
7838    // Advance to the end of this handler. Causes error if we are past that point.
7839    .org nterp_op_rem_double + NTERP_HANDLER_SIZE  // op_rem_double handler is too big!
7840
7841/* ------------------------------ */
7842    .balign NTERP_HANDLER_SIZE
7843.L_op_add_int_2addr: /* 0xb0 */
7844    NAME_START nterp_op_add_int_2addr
7845    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7846    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7847
7848    /*
7849     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
7850     * that specifies an instruction that performs "result = w0 op w1".
7851     * This could be an ARM instruction or a function call.  (If the result
7852     * comes back in a register other than w0, you can override "result".)
7853     *
7854     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7855     * vCC (w1).  Useful for integer division and modulus.
7856     *
7857     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
7858     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
7859     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
7860     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
7861     */
7862    /* binop/2addr vA, vB */
7863    lsr     w3, wINST, #12              // w3<- B
7864    ubfx    w9, wINST, #8, #4           // w9<- A
7865    GET_VREG w1, w3                     // w1<- vB
7866    GET_VREG w0, w9                     // w0<- vA
7867    .if 0
7868    cbz     w1, common_errDivideByZero
7869    .endif
7870    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
7871                               // optional op; may set condition codes
7872    add     w0, w0, w1                              // w0<- op, w0-w3 changed
7873    GET_INST_OPCODE ip                  // extract opcode from rINST
7874    SET_VREG w0, w9                // vAA<- w0
7875    GOTO_OPCODE ip                      // jump to next instruction
7876    /* 10-13 instructions */
7877
7878    NAME_END nterp_op_add_int_2addr
7879    // Advance to the end of this handler. Causes error if we are past that point.
7880    .org nterp_op_add_int_2addr + NTERP_HANDLER_SIZE  // op_add_int_2addr handler is too big!
7881
7882/* ------------------------------ */
7883    .balign NTERP_HANDLER_SIZE
7884.L_op_sub_int_2addr: /* 0xb1 */
7885    NAME_START nterp_op_sub_int_2addr
7886    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7887    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7888
7889    /*
7890     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
7891     * that specifies an instruction that performs "result = w0 op w1".
7892     * This could be an ARM instruction or a function call.  (If the result
7893     * comes back in a register other than w0, you can override "result".)
7894     *
7895     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7896     * vCC (w1).  Useful for integer division and modulus.
7897     *
7898     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
7899     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
7900     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
7901     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
7902     */
7903    /* binop/2addr vA, vB */
7904    lsr     w3, wINST, #12              // w3<- B
7905    ubfx    w9, wINST, #8, #4           // w9<- A
7906    GET_VREG w1, w3                     // w1<- vB
7907    GET_VREG w0, w9                     // w0<- vA
7908    .if 0
7909    cbz     w1, common_errDivideByZero
7910    .endif
7911    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
7912                               // optional op; may set condition codes
7913    sub     w0, w0, w1                              // w0<- op, w0-w3 changed
7914    GET_INST_OPCODE ip                  // extract opcode from rINST
7915    SET_VREG w0, w9                // vAA<- w0
7916    GOTO_OPCODE ip                      // jump to next instruction
7917    /* 10-13 instructions */
7918
7919    NAME_END nterp_op_sub_int_2addr
7920    // Advance to the end of this handler. Causes error if we are past that point.
7921    .org nterp_op_sub_int_2addr + NTERP_HANDLER_SIZE  // op_sub_int_2addr handler is too big!
7922
7923/* ------------------------------ */
7924    .balign NTERP_HANDLER_SIZE
7925.L_op_mul_int_2addr: /* 0xb2 */
7926    NAME_START nterp_op_mul_int_2addr
7927    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7928    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7929
7930/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
7931    /*
7932     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
7933     * that specifies an instruction that performs "result = w0 op w1".
7934     * This could be an ARM instruction or a function call.  (If the result
7935     * comes back in a register other than w0, you can override "result".)
7936     *
7937     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7938     * vCC (w1).  Useful for integer division and modulus.
7939     *
7940     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
7941     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
7942     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
7943     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
7944     */
7945    /* binop/2addr vA, vB */
7946    lsr     w3, wINST, #12              // w3<- B
7947    ubfx    w9, wINST, #8, #4           // w9<- A
7948    GET_VREG w1, w3                     // w1<- vB
7949    GET_VREG w0, w9                     // w0<- vA
7950    .if 0
7951    cbz     w1, common_errDivideByZero
7952    .endif
7953    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
7954                               // optional op; may set condition codes
7955    mul     w0, w1, w0                              // w0<- op, w0-w3 changed
7956    GET_INST_OPCODE ip                  // extract opcode from rINST
7957    SET_VREG w0, w9                // vAA<- w0
7958    GOTO_OPCODE ip                      // jump to next instruction
7959    /* 10-13 instructions */
7960
7961    NAME_END nterp_op_mul_int_2addr
7962    // Advance to the end of this handler. Causes error if we are past that point.
7963    .org nterp_op_mul_int_2addr + NTERP_HANDLER_SIZE  // op_mul_int_2addr handler is too big!
7964
7965/* ------------------------------ */
7966    .balign NTERP_HANDLER_SIZE
7967.L_op_div_int_2addr: /* 0xb3 */
7968    NAME_START nterp_op_div_int_2addr
7969    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
7970    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
7971
7972    /*
7973     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
7974     * that specifies an instruction that performs "result = w0 op w1".
7975     * This could be an ARM instruction or a function call.  (If the result
7976     * comes back in a register other than w0, you can override "result".)
7977     *
7978     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7979     * vCC (w1).  Useful for integer division and modulus.
7980     *
7981     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
7982     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
7983     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
7984     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
7985     */
7986    /* binop/2addr vA, vB */
7987    lsr     w3, wINST, #12              // w3<- B
7988    ubfx    w9, wINST, #8, #4           // w9<- A
7989    GET_VREG w1, w3                     // w1<- vB
7990    GET_VREG w0, w9                     // w0<- vA
7991    .if 1
7992    cbz     w1, common_errDivideByZero
7993    .endif
7994    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
7995                               // optional op; may set condition codes
7996    sdiv     w0, w0, w1                              // w0<- op, w0-w3 changed
7997    GET_INST_OPCODE ip                  // extract opcode from rINST
7998    SET_VREG w0, w9                // vAA<- w0
7999    GOTO_OPCODE ip                      // jump to next instruction
8000    /* 10-13 instructions */
8001
8002    NAME_END nterp_op_div_int_2addr
8003    // Advance to the end of this handler. Causes error if we are past that point.
8004    .org nterp_op_div_int_2addr + NTERP_HANDLER_SIZE  // op_div_int_2addr handler is too big!
8005
8006/* ------------------------------ */
8007    .balign NTERP_HANDLER_SIZE
8008.L_op_rem_int_2addr: /* 0xb4 */
8009    NAME_START nterp_op_rem_int_2addr
8010    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8011    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8012
8013    /*
8014     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8015     * that specifies an instruction that performs "result = w0 op w1".
8016     * This could be an ARM instruction or a function call.  (If the result
8017     * comes back in a register other than w0, you can override "result".)
8018     *
8019     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8020     * vCC (w1).  Useful for integer division and modulus.
8021     *
8022     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8023     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8024     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8025     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8026     */
8027    /* binop/2addr vA, vB */
8028    lsr     w3, wINST, #12              // w3<- B
8029    ubfx    w9, wINST, #8, #4           // w9<- A
8030    GET_VREG w1, w3                     // w1<- vB
8031    GET_VREG w0, w9                     // w0<- vA
8032    .if 1
8033    cbz     w1, common_errDivideByZero
8034    .endif
8035    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8036    sdiv     w2, w0, w1                           // optional op; may set condition codes
8037    msub w0, w2, w1, w0                              // w0<- op, w0-w3 changed
8038    GET_INST_OPCODE ip                  // extract opcode from rINST
8039    SET_VREG w0, w9                // vAA<- w0
8040    GOTO_OPCODE ip                      // jump to next instruction
8041    /* 10-13 instructions */
8042
8043    NAME_END nterp_op_rem_int_2addr
8044    // Advance to the end of this handler. Causes error if we are past that point.
8045    .org nterp_op_rem_int_2addr + NTERP_HANDLER_SIZE  // op_rem_int_2addr handler is too big!
8046
8047/* ------------------------------ */
8048    .balign NTERP_HANDLER_SIZE
8049.L_op_and_int_2addr: /* 0xb5 */
8050    NAME_START nterp_op_and_int_2addr
8051    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8052    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8053
8054    /*
8055     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8056     * that specifies an instruction that performs "result = w0 op w1".
8057     * This could be an ARM instruction or a function call.  (If the result
8058     * comes back in a register other than w0, you can override "result".)
8059     *
8060     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8061     * vCC (w1).  Useful for integer division and modulus.
8062     *
8063     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8064     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8065     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8066     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8067     */
8068    /* binop/2addr vA, vB */
8069    lsr     w3, wINST, #12              // w3<- B
8070    ubfx    w9, wINST, #8, #4           // w9<- A
8071    GET_VREG w1, w3                     // w1<- vB
8072    GET_VREG w0, w9                     // w0<- vA
8073    .if 0
8074    cbz     w1, common_errDivideByZero
8075    .endif
8076    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8077                               // optional op; may set condition codes
8078    and     w0, w0, w1                              // w0<- op, w0-w3 changed
8079    GET_INST_OPCODE ip                  // extract opcode from rINST
8080    SET_VREG w0, w9                // vAA<- w0
8081    GOTO_OPCODE ip                      // jump to next instruction
8082    /* 10-13 instructions */
8083
8084    NAME_END nterp_op_and_int_2addr
8085    // Advance to the end of this handler. Causes error if we are past that point.
8086    .org nterp_op_and_int_2addr + NTERP_HANDLER_SIZE  // op_and_int_2addr handler is too big!
8087
8088/* ------------------------------ */
8089    .balign NTERP_HANDLER_SIZE
8090.L_op_or_int_2addr: /* 0xb6 */
8091    NAME_START nterp_op_or_int_2addr
8092    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8093    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8094
8095    /*
8096     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8097     * that specifies an instruction that performs "result = w0 op w1".
8098     * This could be an ARM instruction or a function call.  (If the result
8099     * comes back in a register other than w0, you can override "result".)
8100     *
8101     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8102     * vCC (w1).  Useful for integer division and modulus.
8103     *
8104     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8105     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8106     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8107     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8108     */
8109    /* binop/2addr vA, vB */
8110    lsr     w3, wINST, #12              // w3<- B
8111    ubfx    w9, wINST, #8, #4           // w9<- A
8112    GET_VREG w1, w3                     // w1<- vB
8113    GET_VREG w0, w9                     // w0<- vA
8114    .if 0
8115    cbz     w1, common_errDivideByZero
8116    .endif
8117    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8118                               // optional op; may set condition codes
8119    orr     w0, w0, w1                              // w0<- op, w0-w3 changed
8120    GET_INST_OPCODE ip                  // extract opcode from rINST
8121    SET_VREG w0, w9                // vAA<- w0
8122    GOTO_OPCODE ip                      // jump to next instruction
8123    /* 10-13 instructions */
8124
8125    NAME_END nterp_op_or_int_2addr
8126    // Advance to the end of this handler. Causes error if we are past that point.
8127    .org nterp_op_or_int_2addr + NTERP_HANDLER_SIZE  // op_or_int_2addr handler is too big!
8128
8129/* ------------------------------ */
8130    .balign NTERP_HANDLER_SIZE
8131.L_op_xor_int_2addr: /* 0xb7 */
8132    NAME_START nterp_op_xor_int_2addr
8133    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8134    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8135
8136    /*
8137     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8138     * that specifies an instruction that performs "result = w0 op w1".
8139     * This could be an ARM instruction or a function call.  (If the result
8140     * comes back in a register other than w0, you can override "result".)
8141     *
8142     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8143     * vCC (w1).  Useful for integer division and modulus.
8144     *
8145     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8146     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8147     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8148     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8149     */
8150    /* binop/2addr vA, vB */
8151    lsr     w3, wINST, #12              // w3<- B
8152    ubfx    w9, wINST, #8, #4           // w9<- A
8153    GET_VREG w1, w3                     // w1<- vB
8154    GET_VREG w0, w9                     // w0<- vA
8155    .if 0
8156    cbz     w1, common_errDivideByZero
8157    .endif
8158    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8159                               // optional op; may set condition codes
8160    eor     w0, w0, w1                              // w0<- op, w0-w3 changed
8161    GET_INST_OPCODE ip                  // extract opcode from rINST
8162    SET_VREG w0, w9                // vAA<- w0
8163    GOTO_OPCODE ip                      // jump to next instruction
8164    /* 10-13 instructions */
8165
8166    NAME_END nterp_op_xor_int_2addr
8167    // Advance to the end of this handler. Causes error if we are past that point.
8168    .org nterp_op_xor_int_2addr + NTERP_HANDLER_SIZE  // op_xor_int_2addr handler is too big!
8169
8170/* ------------------------------ */
8171    .balign NTERP_HANDLER_SIZE
8172.L_op_shl_int_2addr: /* 0xb8 */
8173    NAME_START nterp_op_shl_int_2addr
8174    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8175    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8176
8177    /*
8178     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8179     * that specifies an instruction that performs "result = w0 op w1".
8180     * This could be an ARM instruction or a function call.  (If the result
8181     * comes back in a register other than w0, you can override "result".)
8182     *
8183     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8184     * vCC (w1).  Useful for integer division and modulus.
8185     *
8186     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8187     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8188     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8189     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8190     */
8191    /* binop/2addr vA, vB */
8192    lsr     w3, wINST, #12              // w3<- B
8193    ubfx    w9, wINST, #8, #4           // w9<- A
8194    GET_VREG w1, w3                     // w1<- vB
8195    GET_VREG w0, w9                     // w0<- vA
8196    .if 0
8197    cbz     w1, common_errDivideByZero
8198    .endif
8199    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8200                               // optional op; may set condition codes
8201    lsl     w0, w0, w1                              // w0<- op, w0-w3 changed
8202    GET_INST_OPCODE ip                  // extract opcode from rINST
8203    SET_VREG w0, w9                // vAA<- w0
8204    GOTO_OPCODE ip                      // jump to next instruction
8205    /* 10-13 instructions */
8206
8207    NAME_END nterp_op_shl_int_2addr
8208    // Advance to the end of this handler. Causes error if we are past that point.
8209    .org nterp_op_shl_int_2addr + NTERP_HANDLER_SIZE  // op_shl_int_2addr handler is too big!
8210
8211/* ------------------------------ */
8212    .balign NTERP_HANDLER_SIZE
8213.L_op_shr_int_2addr: /* 0xb9 */
8214    NAME_START nterp_op_shr_int_2addr
8215    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8216    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8217
8218    /*
8219     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8220     * that specifies an instruction that performs "result = w0 op w1".
8221     * This could be an ARM instruction or a function call.  (If the result
8222     * comes back in a register other than w0, you can override "result".)
8223     *
8224     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8225     * vCC (w1).  Useful for integer division and modulus.
8226     *
8227     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8228     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8229     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8230     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8231     */
8232    /* binop/2addr vA, vB */
8233    lsr     w3, wINST, #12              // w3<- B
8234    ubfx    w9, wINST, #8, #4           // w9<- A
8235    GET_VREG w1, w3                     // w1<- vB
8236    GET_VREG w0, w9                     // w0<- vA
8237    .if 0
8238    cbz     w1, common_errDivideByZero
8239    .endif
8240    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8241                               // optional op; may set condition codes
8242    asr     w0, w0, w1                              // w0<- op, w0-w3 changed
8243    GET_INST_OPCODE ip                  // extract opcode from rINST
8244    SET_VREG w0, w9                // vAA<- w0
8245    GOTO_OPCODE ip                      // jump to next instruction
8246    /* 10-13 instructions */
8247
8248    NAME_END nterp_op_shr_int_2addr
8249    // Advance to the end of this handler. Causes error if we are past that point.
8250    .org nterp_op_shr_int_2addr + NTERP_HANDLER_SIZE  // op_shr_int_2addr handler is too big!
8251
8252/* ------------------------------ */
8253    .balign NTERP_HANDLER_SIZE
8254.L_op_ushr_int_2addr: /* 0xba */
8255    NAME_START nterp_op_ushr_int_2addr
8256    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8257    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8258
8259    /*
8260     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
8261     * that specifies an instruction that performs "result = w0 op w1".
8262     * This could be an ARM instruction or a function call.  (If the result
8263     * comes back in a register other than w0, you can override "result".)
8264     *
8265     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8266     * vCC (w1).  Useful for integer division and modulus.
8267     *
8268     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
8269     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
8270     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
8271     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
8272     */
8273    /* binop/2addr vA, vB */
8274    lsr     w3, wINST, #12              // w3<- B
8275    ubfx    w9, wINST, #8, #4           // w9<- A
8276    GET_VREG w1, w3                     // w1<- vB
8277    GET_VREG w0, w9                     // w0<- vA
8278    .if 0
8279    cbz     w1, common_errDivideByZero
8280    .endif
8281    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8282                               // optional op; may set condition codes
8283    lsr     w0, w0, w1                              // w0<- op, w0-w3 changed
8284    GET_INST_OPCODE ip                  // extract opcode from rINST
8285    SET_VREG w0, w9                // vAA<- w0
8286    GOTO_OPCODE ip                      // jump to next instruction
8287    /* 10-13 instructions */
8288
8289    NAME_END nterp_op_ushr_int_2addr
8290    // Advance to the end of this handler. Causes error if we are past that point.
8291    .org nterp_op_ushr_int_2addr + NTERP_HANDLER_SIZE  // op_ushr_int_2addr handler is too big!
8292
8293/* ------------------------------ */
8294    .balign NTERP_HANDLER_SIZE
8295.L_op_add_long_2addr: /* 0xbb */
8296    NAME_START nterp_op_add_long_2addr
8297    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8298    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8299
8300    /*
8301     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8302     * that specifies an instruction that performs "x0 = x0 op x1".
8303     * This must not be a function call, as we keep w2 live across it.
8304     *
8305     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8306     * vCC (w1).  Useful for integer division and modulus.
8307     *
8308     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8309     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8310     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8311     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8312     */
8313    /* binop/2addr vA, vB */
8314    lsr     w1, wINST, #12              // w1<- B
8315    ubfx    w2, wINST, #8, #4           // w2<- A
8316    GET_VREG_WIDE x1, w1               // x1<- vB
8317    GET_VREG_WIDE x0, w2               // x0<- vA
8318    .if 0
8319    cbz     x1, common_errDivideByZero
8320    .endif
8321    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8322
8323    add     x0, x0, x1                              // result<- op
8324    GET_INST_OPCODE ip                  // extract opcode from rINST
8325    SET_VREG_WIDE x0, w2               // vAA<- result
8326    GOTO_OPCODE ip                      // jump to next instruction
8327    /* 10-13 instructions */
8328
8329    NAME_END nterp_op_add_long_2addr
8330    // Advance to the end of this handler. Causes error if we are past that point.
8331    .org nterp_op_add_long_2addr + NTERP_HANDLER_SIZE  // op_add_long_2addr handler is too big!
8332
8333/* ------------------------------ */
8334    .balign NTERP_HANDLER_SIZE
8335.L_op_sub_long_2addr: /* 0xbc */
8336    NAME_START nterp_op_sub_long_2addr
8337    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8338    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8339
8340    /*
8341     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8342     * that specifies an instruction that performs "x0 = x0 op x1".
8343     * This must not be a function call, as we keep w2 live across it.
8344     *
8345     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8346     * vCC (w1).  Useful for integer division and modulus.
8347     *
8348     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8349     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8350     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8351     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8352     */
8353    /* binop/2addr vA, vB */
8354    lsr     w1, wINST, #12              // w1<- B
8355    ubfx    w2, wINST, #8, #4           // w2<- A
8356    GET_VREG_WIDE x1, w1               // x1<- vB
8357    GET_VREG_WIDE x0, w2               // x0<- vA
8358    .if 0
8359    cbz     x1, common_errDivideByZero
8360    .endif
8361    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8362
8363    sub     x0, x0, x1                              // result<- op
8364    GET_INST_OPCODE ip                  // extract opcode from rINST
8365    SET_VREG_WIDE x0, w2               // vAA<- result
8366    GOTO_OPCODE ip                      // jump to next instruction
8367    /* 10-13 instructions */
8368
8369    NAME_END nterp_op_sub_long_2addr
8370    // Advance to the end of this handler. Causes error if we are past that point.
8371    .org nterp_op_sub_long_2addr + NTERP_HANDLER_SIZE  // op_sub_long_2addr handler is too big!
8372
8373/* ------------------------------ */
8374    .balign NTERP_HANDLER_SIZE
8375.L_op_mul_long_2addr: /* 0xbd */
8376    NAME_START nterp_op_mul_long_2addr
8377    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8378    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8379
8380    /*
8381     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8382     * that specifies an instruction that performs "x0 = x0 op x1".
8383     * This must not be a function call, as we keep w2 live across it.
8384     *
8385     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8386     * vCC (w1).  Useful for integer division and modulus.
8387     *
8388     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8389     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8390     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8391     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8392     */
8393    /* binop/2addr vA, vB */
8394    lsr     w1, wINST, #12              // w1<- B
8395    ubfx    w2, wINST, #8, #4           // w2<- A
8396    GET_VREG_WIDE x1, w1               // x1<- vB
8397    GET_VREG_WIDE x0, w2               // x0<- vA
8398    .if 0
8399    cbz     x1, common_errDivideByZero
8400    .endif
8401    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8402
8403    mul     x0, x0, x1                              // result<- op
8404    GET_INST_OPCODE ip                  // extract opcode from rINST
8405    SET_VREG_WIDE x0, w2               // vAA<- result
8406    GOTO_OPCODE ip                      // jump to next instruction
8407    /* 10-13 instructions */
8408
8409    NAME_END nterp_op_mul_long_2addr
8410    // Advance to the end of this handler. Causes error if we are past that point.
8411    .org nterp_op_mul_long_2addr + NTERP_HANDLER_SIZE  // op_mul_long_2addr handler is too big!
8412
8413/* ------------------------------ */
8414    .balign NTERP_HANDLER_SIZE
8415.L_op_div_long_2addr: /* 0xbe */
8416    NAME_START nterp_op_div_long_2addr
8417    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8418    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8419
8420    /*
8421     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8422     * that specifies an instruction that performs "x0 = x0 op x1".
8423     * This must not be a function call, as we keep w2 live across it.
8424     *
8425     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8426     * vCC (w1).  Useful for integer division and modulus.
8427     *
8428     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8429     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8430     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8431     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8432     */
8433    /* binop/2addr vA, vB */
8434    lsr     w1, wINST, #12              // w1<- B
8435    ubfx    w2, wINST, #8, #4           // w2<- A
8436    GET_VREG_WIDE x1, w1               // x1<- vB
8437    GET_VREG_WIDE x0, w2               // x0<- vA
8438    .if 1
8439    cbz     x1, common_errDivideByZero
8440    .endif
8441    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8442
8443    sdiv     x0, x0, x1                              // result<- op
8444    GET_INST_OPCODE ip                  // extract opcode from rINST
8445    SET_VREG_WIDE x0, w2               // vAA<- result
8446    GOTO_OPCODE ip                      // jump to next instruction
8447    /* 10-13 instructions */
8448
8449    NAME_END nterp_op_div_long_2addr
8450    // Advance to the end of this handler. Causes error if we are past that point.
8451    .org nterp_op_div_long_2addr + NTERP_HANDLER_SIZE  // op_div_long_2addr handler is too big!
8452
8453/* ------------------------------ */
8454    .balign NTERP_HANDLER_SIZE
8455.L_op_rem_long_2addr: /* 0xbf */
8456    NAME_START nterp_op_rem_long_2addr
8457    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8458    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8459
8460    /*
8461     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8462     * that specifies an instruction that performs "x0 = x0 op x1".
8463     * This must not be a function call, as we keep w2 live across it.
8464     *
8465     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8466     * vCC (w1).  Useful for integer division and modulus.
8467     *
8468     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8469     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8470     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8471     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8472     */
8473    /* binop/2addr vA, vB */
8474    lsr     w1, wINST, #12              // w1<- B
8475    ubfx    w2, wINST, #8, #4           // w2<- A
8476    GET_VREG_WIDE x1, w1               // x1<- vB
8477    GET_VREG_WIDE x0, w2               // x0<- vA
8478    .if 1
8479    cbz     x1, common_errDivideByZero
8480    .endif
8481    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8482    sdiv x3, x0, x1
8483    msub x0, x3, x1, x0                              // result<- op
8484    GET_INST_OPCODE ip                  // extract opcode from rINST
8485    SET_VREG_WIDE x0, w2               // vAA<- result
8486    GOTO_OPCODE ip                      // jump to next instruction
8487    /* 10-13 instructions */
8488
8489    NAME_END nterp_op_rem_long_2addr
8490    // Advance to the end of this handler. Causes error if we are past that point.
8491    .org nterp_op_rem_long_2addr + NTERP_HANDLER_SIZE  // op_rem_long_2addr handler is too big!
8492
8493/* ------------------------------ */
8494    .balign NTERP_HANDLER_SIZE
8495.L_op_and_long_2addr: /* 0xc0 */
8496    NAME_START nterp_op_and_long_2addr
8497    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8498    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8499
8500    /*
8501     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8502     * that specifies an instruction that performs "x0 = x0 op x1".
8503     * This must not be a function call, as we keep w2 live across it.
8504     *
8505     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8506     * vCC (w1).  Useful for integer division and modulus.
8507     *
8508     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8509     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8510     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8511     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8512     */
8513    /* binop/2addr vA, vB */
8514    lsr     w1, wINST, #12              // w1<- B
8515    ubfx    w2, wINST, #8, #4           // w2<- A
8516    GET_VREG_WIDE x1, w1               // x1<- vB
8517    GET_VREG_WIDE x0, w2               // x0<- vA
8518    .if 0
8519    cbz     x1, common_errDivideByZero
8520    .endif
8521    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8522
8523    and     x0, x0, x1                              // result<- op
8524    GET_INST_OPCODE ip                  // extract opcode from rINST
8525    SET_VREG_WIDE x0, w2               // vAA<- result
8526    GOTO_OPCODE ip                      // jump to next instruction
8527    /* 10-13 instructions */
8528
8529    NAME_END nterp_op_and_long_2addr
8530    // Advance to the end of this handler. Causes error if we are past that point.
8531    .org nterp_op_and_long_2addr + NTERP_HANDLER_SIZE  // op_and_long_2addr handler is too big!
8532
8533/* ------------------------------ */
8534    .balign NTERP_HANDLER_SIZE
8535.L_op_or_long_2addr: /* 0xc1 */
8536    NAME_START nterp_op_or_long_2addr
8537    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8538    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8539
8540    /*
8541     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8542     * that specifies an instruction that performs "x0 = x0 op x1".
8543     * This must not be a function call, as we keep w2 live across it.
8544     *
8545     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8546     * vCC (w1).  Useful for integer division and modulus.
8547     *
8548     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8549     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8550     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8551     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8552     */
8553    /* binop/2addr vA, vB */
8554    lsr     w1, wINST, #12              // w1<- B
8555    ubfx    w2, wINST, #8, #4           // w2<- A
8556    GET_VREG_WIDE x1, w1               // x1<- vB
8557    GET_VREG_WIDE x0, w2               // x0<- vA
8558    .if 0
8559    cbz     x1, common_errDivideByZero
8560    .endif
8561    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8562
8563    orr     x0, x0, x1                              // result<- op
8564    GET_INST_OPCODE ip                  // extract opcode from rINST
8565    SET_VREG_WIDE x0, w2               // vAA<- result
8566    GOTO_OPCODE ip                      // jump to next instruction
8567    /* 10-13 instructions */
8568
8569    NAME_END nterp_op_or_long_2addr
8570    // Advance to the end of this handler. Causes error if we are past that point.
8571    .org nterp_op_or_long_2addr + NTERP_HANDLER_SIZE  // op_or_long_2addr handler is too big!
8572
8573/* ------------------------------ */
8574    .balign NTERP_HANDLER_SIZE
8575.L_op_xor_long_2addr: /* 0xc2 */
8576    NAME_START nterp_op_xor_long_2addr
8577    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8578    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8579
8580    /*
8581     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
8582     * that specifies an instruction that performs "x0 = x0 op x1".
8583     * This must not be a function call, as we keep w2 live across it.
8584     *
8585     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8586     * vCC (w1).  Useful for integer division and modulus.
8587     *
8588     * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
8589     *      and-long/2addr, or-long/2addr, xor-long/2addr,
8590     *      shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr,
8591     *      sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr
8592     */
8593    /* binop/2addr vA, vB */
8594    lsr     w1, wINST, #12              // w1<- B
8595    ubfx    w2, wINST, #8, #4           // w2<- A
8596    GET_VREG_WIDE x1, w1               // x1<- vB
8597    GET_VREG_WIDE x0, w2               // x0<- vA
8598    .if 0
8599    cbz     x1, common_errDivideByZero
8600    .endif
8601    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8602
8603    eor     x0, x0, x1                              // result<- op
8604    GET_INST_OPCODE ip                  // extract opcode from rINST
8605    SET_VREG_WIDE x0, w2               // vAA<- result
8606    GOTO_OPCODE ip                      // jump to next instruction
8607    /* 10-13 instructions */
8608
8609    NAME_END nterp_op_xor_long_2addr
8610    // Advance to the end of this handler. Causes error if we are past that point.
8611    .org nterp_op_xor_long_2addr + NTERP_HANDLER_SIZE  // op_xor_long_2addr handler is too big!
8612
8613/* ------------------------------ */
8614    .balign NTERP_HANDLER_SIZE
8615.L_op_shl_long_2addr: /* 0xc3 */
8616    NAME_START nterp_op_shl_long_2addr
8617    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8618    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8619
8620    /*
8621     * Generic 64-bit shift operation.
8622     */
8623    /* binop/2addr vA, vB */
8624    lsr     w1, wINST, #12              // w1<- B
8625    ubfx    w2, wINST, #8, #4           // w2<- A
8626    GET_VREG w1, w1                     // x1<- vB
8627    GET_VREG_WIDE x0, w2                // x0<- vA
8628    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8629    lsl x0, x0, x1                  // Do the shift. Only low 6 bits of x1 are used.
8630    GET_INST_OPCODE ip                  // extract opcode from rINST
8631    SET_VREG_WIDE x0, w2               // vAA<- result
8632    GOTO_OPCODE ip                      // jump to next instruction
8633    /* 10-13 instructions */
8634
8635    NAME_END nterp_op_shl_long_2addr
8636    // Advance to the end of this handler. Causes error if we are past that point.
8637    .org nterp_op_shl_long_2addr + NTERP_HANDLER_SIZE  // op_shl_long_2addr handler is too big!
8638
8639/* ------------------------------ */
8640    .balign NTERP_HANDLER_SIZE
8641.L_op_shr_long_2addr: /* 0xc4 */
8642    NAME_START nterp_op_shr_long_2addr
8643    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8644    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8645
8646    /*
8647     * Generic 64-bit shift operation.
8648     */
8649    /* binop/2addr vA, vB */
8650    lsr     w1, wINST, #12              // w1<- B
8651    ubfx    w2, wINST, #8, #4           // w2<- A
8652    GET_VREG w1, w1                     // x1<- vB
8653    GET_VREG_WIDE x0, w2                // x0<- vA
8654    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8655    asr x0, x0, x1                  // Do the shift. Only low 6 bits of x1 are used.
8656    GET_INST_OPCODE ip                  // extract opcode from rINST
8657    SET_VREG_WIDE x0, w2               // vAA<- result
8658    GOTO_OPCODE ip                      // jump to next instruction
8659    /* 10-13 instructions */
8660
8661    NAME_END nterp_op_shr_long_2addr
8662    // Advance to the end of this handler. Causes error if we are past that point.
8663    .org nterp_op_shr_long_2addr + NTERP_HANDLER_SIZE  // op_shr_long_2addr handler is too big!
8664
8665/* ------------------------------ */
8666    .balign NTERP_HANDLER_SIZE
8667.L_op_ushr_long_2addr: /* 0xc5 */
8668    NAME_START nterp_op_ushr_long_2addr
8669    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8670    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8671
8672    /*
8673     * Generic 64-bit shift operation.
8674     */
8675    /* binop/2addr vA, vB */
8676    lsr     w1, wINST, #12              // w1<- B
8677    ubfx    w2, wINST, #8, #4           // w2<- A
8678    GET_VREG w1, w1                     // x1<- vB
8679    GET_VREG_WIDE x0, w2                // x0<- vA
8680    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8681    lsr x0, x0, x1                  // Do the shift. Only low 6 bits of x1 are used.
8682    GET_INST_OPCODE ip                  // extract opcode from rINST
8683    SET_VREG_WIDE x0, w2               // vAA<- result
8684    GOTO_OPCODE ip                      // jump to next instruction
8685    /* 10-13 instructions */
8686
8687    NAME_END nterp_op_ushr_long_2addr
8688    // Advance to the end of this handler. Causes error if we are past that point.
8689    .org nterp_op_ushr_long_2addr + NTERP_HANDLER_SIZE  // op_ushr_long_2addr handler is too big!
8690
8691/* ------------------------------ */
8692    .balign NTERP_HANDLER_SIZE
8693.L_op_add_float_2addr: /* 0xc6 */
8694    NAME_START nterp_op_add_float_2addr
8695    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8696    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8697
8698    /*
8699     * Generic 32-bit floating point "/2addr" binary operation.  Provide
8700     * an "instr" line that specifies an instruction that performs
8701     * "s2 = s0 op s1".
8702     *
8703     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
8704     */
8705    /* binop/2addr vA, vB */
8706    lsr     w3, wINST, #12              // w3<- B
8707    ubfx    w9, wINST, #8, #4           // w9<- A
8708    GET_VREG s1, w3
8709    GET_VREG s0, w9
8710    fadd   s2, s0, s1                              // s2<- op
8711    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8712    GET_INST_OPCODE ip                  // extract opcode from rINST
8713    SET_VREG_FLOAT s2, w9
8714    GOTO_OPCODE ip                      // jump to next instruction
8715
8716    NAME_END nterp_op_add_float_2addr
8717    // Advance to the end of this handler. Causes error if we are past that point.
8718    .org nterp_op_add_float_2addr + NTERP_HANDLER_SIZE  // op_add_float_2addr handler is too big!
8719
8720/* ------------------------------ */
8721    .balign NTERP_HANDLER_SIZE
8722.L_op_sub_float_2addr: /* 0xc7 */
8723    NAME_START nterp_op_sub_float_2addr
8724    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8725    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8726
8727    /*
8728     * Generic 32-bit floating point "/2addr" binary operation.  Provide
8729     * an "instr" line that specifies an instruction that performs
8730     * "s2 = s0 op s1".
8731     *
8732     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
8733     */
8734    /* binop/2addr vA, vB */
8735    lsr     w3, wINST, #12              // w3<- B
8736    ubfx    w9, wINST, #8, #4           // w9<- A
8737    GET_VREG s1, w3
8738    GET_VREG s0, w9
8739    fsub   s2, s0, s1                              // s2<- op
8740    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8741    GET_INST_OPCODE ip                  // extract opcode from rINST
8742    SET_VREG_FLOAT s2, w9
8743    GOTO_OPCODE ip                      // jump to next instruction
8744
8745    NAME_END nterp_op_sub_float_2addr
8746    // Advance to the end of this handler. Causes error if we are past that point.
8747    .org nterp_op_sub_float_2addr + NTERP_HANDLER_SIZE  // op_sub_float_2addr handler is too big!
8748
8749/* ------------------------------ */
8750    .balign NTERP_HANDLER_SIZE
8751.L_op_mul_float_2addr: /* 0xc8 */
8752    NAME_START nterp_op_mul_float_2addr
8753    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8754    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8755
8756    /*
8757     * Generic 32-bit floating point "/2addr" binary operation.  Provide
8758     * an "instr" line that specifies an instruction that performs
8759     * "s2 = s0 op s1".
8760     *
8761     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
8762     */
8763    /* binop/2addr vA, vB */
8764    lsr     w3, wINST, #12              // w3<- B
8765    ubfx    w9, wINST, #8, #4           // w9<- A
8766    GET_VREG s1, w3
8767    GET_VREG s0, w9
8768    fmul   s2, s0, s1                              // s2<- op
8769    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8770    GET_INST_OPCODE ip                  // extract opcode from rINST
8771    SET_VREG_FLOAT s2, w9
8772    GOTO_OPCODE ip                      // jump to next instruction
8773
8774    NAME_END nterp_op_mul_float_2addr
8775    // Advance to the end of this handler. Causes error if we are past that point.
8776    .org nterp_op_mul_float_2addr + NTERP_HANDLER_SIZE  // op_mul_float_2addr handler is too big!
8777
8778/* ------------------------------ */
8779    .balign NTERP_HANDLER_SIZE
8780.L_op_div_float_2addr: /* 0xc9 */
8781    NAME_START nterp_op_div_float_2addr
8782    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8783    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8784
8785    /*
8786     * Generic 32-bit floating point "/2addr" binary operation.  Provide
8787     * an "instr" line that specifies an instruction that performs
8788     * "s2 = s0 op s1".
8789     *
8790     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
8791     */
8792    /* binop/2addr vA, vB */
8793    lsr     w3, wINST, #12              // w3<- B
8794    ubfx    w9, wINST, #8, #4           // w9<- A
8795    GET_VREG s1, w3
8796    GET_VREG s0, w9
8797    fdiv   s2, s0, s1                              // s2<- op
8798    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8799    GET_INST_OPCODE ip                  // extract opcode from rINST
8800    SET_VREG_FLOAT s2, w9
8801    GOTO_OPCODE ip                      // jump to next instruction
8802
8803    NAME_END nterp_op_div_float_2addr
8804    // Advance to the end of this handler. Causes error if we are past that point.
8805    .org nterp_op_div_float_2addr + NTERP_HANDLER_SIZE  // op_div_float_2addr handler is too big!
8806
8807/* ------------------------------ */
8808    .balign NTERP_HANDLER_SIZE
8809.L_op_rem_float_2addr: /* 0xca */
8810    NAME_START nterp_op_rem_float_2addr
8811    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8812    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8813
8814    /* rem vA, vB */
8815    lsr     w3, wINST, #12              // w3<- B
8816    ubfx    w9, wINST, #8, #4           // w9<- A
8817    GET_VREG s1, w3
8818    GET_VREG s0, w9
8819    bl  fmodf
8820    ubfx    w9, wINST, #8, #4           // w9<- A
8821    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8822    GET_INST_OPCODE ip                  // extract opcode from rINST
8823    SET_VREG_FLOAT s0, w9
8824    GOTO_OPCODE ip                      // jump to next instruction
8825
8826    NAME_END nterp_op_rem_float_2addr
8827    // Advance to the end of this handler. Causes error if we are past that point.
8828    .org nterp_op_rem_float_2addr + NTERP_HANDLER_SIZE  // op_rem_float_2addr handler is too big!
8829
8830/* ------------------------------ */
8831    .balign NTERP_HANDLER_SIZE
8832.L_op_add_double_2addr: /* 0xcb */
8833    NAME_START nterp_op_add_double_2addr
8834    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8835    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8836
8837    /*
8838     * Generic 64-bit floating point "/2addr" binary operation.
8839     */
8840    /* binop/2addr vA, vB */
8841    lsr     w1, wINST, #12              // w1<- B
8842    ubfx    w2, wINST, #8, #4           // w2<- A
8843    GET_VREG_DOUBLE d1, w1             // x1<- vB
8844    GET_VREG_DOUBLE d0, w2             // x0<- vA
8845    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8846    fadd     d0, d0, d1                              // result<- op
8847    GET_INST_OPCODE ip                  // extract opcode from rINST
8848    SET_VREG_DOUBLE d0, w2             // vAA<- result
8849    GOTO_OPCODE ip                      // jump to next instruction
8850
8851    NAME_END nterp_op_add_double_2addr
8852    // Advance to the end of this handler. Causes error if we are past that point.
8853    .org nterp_op_add_double_2addr + NTERP_HANDLER_SIZE  // op_add_double_2addr handler is too big!
8854
8855/* ------------------------------ */
8856    .balign NTERP_HANDLER_SIZE
8857.L_op_sub_double_2addr: /* 0xcc */
8858    NAME_START nterp_op_sub_double_2addr
8859    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8860    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8861
8862    /*
8863     * Generic 64-bit floating point "/2addr" binary operation.
8864     */
8865    /* binop/2addr vA, vB */
8866    lsr     w1, wINST, #12              // w1<- B
8867    ubfx    w2, wINST, #8, #4           // w2<- A
8868    GET_VREG_DOUBLE d1, w1             // x1<- vB
8869    GET_VREG_DOUBLE d0, w2             // x0<- vA
8870    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8871    fsub     d0, d0, d1                              // result<- op
8872    GET_INST_OPCODE ip                  // extract opcode from rINST
8873    SET_VREG_DOUBLE d0, w2             // vAA<- result
8874    GOTO_OPCODE ip                      // jump to next instruction
8875
8876    NAME_END nterp_op_sub_double_2addr
8877    // Advance to the end of this handler. Causes error if we are past that point.
8878    .org nterp_op_sub_double_2addr + NTERP_HANDLER_SIZE  // op_sub_double_2addr handler is too big!
8879
8880/* ------------------------------ */
8881    .balign NTERP_HANDLER_SIZE
8882.L_op_mul_double_2addr: /* 0xcd */
8883    NAME_START nterp_op_mul_double_2addr
8884    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8885    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8886
8887    /*
8888     * Generic 64-bit floating point "/2addr" binary operation.
8889     */
8890    /* binop/2addr vA, vB */
8891    lsr     w1, wINST, #12              // w1<- B
8892    ubfx    w2, wINST, #8, #4           // w2<- A
8893    GET_VREG_DOUBLE d1, w1             // x1<- vB
8894    GET_VREG_DOUBLE d0, w2             // x0<- vA
8895    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8896    fmul     d0, d0, d1                              // result<- op
8897    GET_INST_OPCODE ip                  // extract opcode from rINST
8898    SET_VREG_DOUBLE d0, w2             // vAA<- result
8899    GOTO_OPCODE ip                      // jump to next instruction
8900
8901    NAME_END nterp_op_mul_double_2addr
8902    // Advance to the end of this handler. Causes error if we are past that point.
8903    .org nterp_op_mul_double_2addr + NTERP_HANDLER_SIZE  // op_mul_double_2addr handler is too big!
8904
8905/* ------------------------------ */
8906    .balign NTERP_HANDLER_SIZE
8907.L_op_div_double_2addr: /* 0xce */
8908    NAME_START nterp_op_div_double_2addr
8909    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8910    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8911
8912    /*
8913     * Generic 64-bit floating point "/2addr" binary operation.
8914     */
8915    /* binop/2addr vA, vB */
8916    lsr     w1, wINST, #12              // w1<- B
8917    ubfx    w2, wINST, #8, #4           // w2<- A
8918    GET_VREG_DOUBLE d1, w1             // x1<- vB
8919    GET_VREG_DOUBLE d0, w2             // x0<- vA
8920    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8921    fdiv     d0, d0, d1                              // result<- op
8922    GET_INST_OPCODE ip                  // extract opcode from rINST
8923    SET_VREG_DOUBLE d0, w2             // vAA<- result
8924    GOTO_OPCODE ip                      // jump to next instruction
8925
8926    NAME_END nterp_op_div_double_2addr
8927    // Advance to the end of this handler. Causes error if we are past that point.
8928    .org nterp_op_div_double_2addr + NTERP_HANDLER_SIZE  // op_div_double_2addr handler is too big!
8929
8930/* ------------------------------ */
8931    .balign NTERP_HANDLER_SIZE
8932.L_op_rem_double_2addr: /* 0xcf */
8933    NAME_START nterp_op_rem_double_2addr
8934    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8935    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8936
8937    /* rem vA, vB */
8938    lsr     w1, wINST, #12              // w1<- B
8939    ubfx    w2, wINST, #8, #4           // w2<- A
8940    GET_VREG_DOUBLE d1, w1              // d1<- vB
8941    GET_VREG_DOUBLE d0, w2              // d0<- vA
8942    bl fmod
8943    ubfx    w2, wINST, #8, #4           // w2<- A (need to reload - killed across call)
8944    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
8945    GET_INST_OPCODE ip                  // extract opcode from rINST
8946    SET_VREG_WIDE d0, w2                // vAA<- result
8947    GOTO_OPCODE ip                      // jump to next instruction
8948    /* 10-13 instructions */
8949
8950    NAME_END nterp_op_rem_double_2addr
8951    // Advance to the end of this handler. Causes error if we are past that point.
8952    .org nterp_op_rem_double_2addr + NTERP_HANDLER_SIZE  // op_rem_double_2addr handler is too big!
8953
8954/* ------------------------------ */
8955    .balign NTERP_HANDLER_SIZE
8956.L_op_add_int_lit16: /* 0xd0 */
8957    NAME_START nterp_op_add_int_lit16
8958    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8959    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8960
8961    /*
8962     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
8963     * that specifies an instruction that performs "result = w0 op w1".
8964     * This could be an ARM instruction or a function call.  (If the result
8965     * comes back in a register other than w0, you can override "result".)
8966     *
8967     * If "chkzero" is set to 1, we perform a divide-by-zero check on
8968     * vCC (w1).  Useful for integer division and modulus.
8969     *
8970     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
8971     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
8972     */
8973    /* binop/lit16 vA, vB, #+CCCC */
8974    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
8975    lsr     w2, wINST, #12              // w2<- B
8976    ubfx    w9, wINST, #8, #4           // w9<- A
8977    GET_VREG w0, w2                     // w0<- vB
8978    .if 0
8979    cbz     w1, common_errDivideByZero
8980    .endif
8981    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
8982
8983    add     w0, w0, w1                              // w0<- op, w0-w3 changed
8984    GET_INST_OPCODE ip                  // extract opcode from rINST
8985    SET_VREG w0, w9                // vAA<- w0
8986    GOTO_OPCODE ip                      // jump to next instruction
8987    /* 10-13 instructions */
8988
8989    NAME_END nterp_op_add_int_lit16
8990    // Advance to the end of this handler. Causes error if we are past that point.
8991    .org nterp_op_add_int_lit16 + NTERP_HANDLER_SIZE  // op_add_int_lit16 handler is too big!
8992
8993/* ------------------------------ */
8994    .balign NTERP_HANDLER_SIZE
8995.L_op_rsub_int: /* 0xd1 */
8996    NAME_START nterp_op_rsub_int
8997    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
8998    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
8999
9000/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
9001    /*
9002     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9003     * that specifies an instruction that performs "result = w0 op w1".
9004     * This could be an ARM instruction or a function call.  (If the result
9005     * comes back in a register other than w0, you can override "result".)
9006     *
9007     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9008     * vCC (w1).  Useful for integer division and modulus.
9009     *
9010     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9011     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9012     */
9013    /* binop/lit16 vA, vB, #+CCCC */
9014    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9015    lsr     w2, wINST, #12              // w2<- B
9016    ubfx    w9, wINST, #8, #4           // w9<- A
9017    GET_VREG w0, w2                     // w0<- vB
9018    .if 0
9019    cbz     w1, common_errDivideByZero
9020    .endif
9021    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9022
9023    sub     w0, w1, w0                              // w0<- op, w0-w3 changed
9024    GET_INST_OPCODE ip                  // extract opcode from rINST
9025    SET_VREG w0, w9                // vAA<- w0
9026    GOTO_OPCODE ip                      // jump to next instruction
9027    /* 10-13 instructions */
9028
9029    NAME_END nterp_op_rsub_int
9030    // Advance to the end of this handler. Causes error if we are past that point.
9031    .org nterp_op_rsub_int + NTERP_HANDLER_SIZE  // op_rsub_int handler is too big!
9032
9033/* ------------------------------ */
9034    .balign NTERP_HANDLER_SIZE
9035.L_op_mul_int_lit16: /* 0xd2 */
9036    NAME_START nterp_op_mul_int_lit16
9037    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9038    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9039
9040/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
9041    /*
9042     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9043     * that specifies an instruction that performs "result = w0 op w1".
9044     * This could be an ARM instruction or a function call.  (If the result
9045     * comes back in a register other than w0, you can override "result".)
9046     *
9047     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9048     * vCC (w1).  Useful for integer division and modulus.
9049     *
9050     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9051     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9052     */
9053    /* binop/lit16 vA, vB, #+CCCC */
9054    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9055    lsr     w2, wINST, #12              // w2<- B
9056    ubfx    w9, wINST, #8, #4           // w9<- A
9057    GET_VREG w0, w2                     // w0<- vB
9058    .if 0
9059    cbz     w1, common_errDivideByZero
9060    .endif
9061    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9062
9063    mul     w0, w1, w0                              // w0<- op, w0-w3 changed
9064    GET_INST_OPCODE ip                  // extract opcode from rINST
9065    SET_VREG w0, w9                // vAA<- w0
9066    GOTO_OPCODE ip                      // jump to next instruction
9067    /* 10-13 instructions */
9068
9069    NAME_END nterp_op_mul_int_lit16
9070    // Advance to the end of this handler. Causes error if we are past that point.
9071    .org nterp_op_mul_int_lit16 + NTERP_HANDLER_SIZE  // op_mul_int_lit16 handler is too big!
9072
9073/* ------------------------------ */
9074    .balign NTERP_HANDLER_SIZE
9075.L_op_div_int_lit16: /* 0xd3 */
9076    NAME_START nterp_op_div_int_lit16
9077    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9078    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9079
9080    /*
9081     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9082     * that specifies an instruction that performs "result = w0 op w1".
9083     * This could be an ARM instruction or a function call.  (If the result
9084     * comes back in a register other than w0, you can override "result".)
9085     *
9086     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9087     * vCC (w1).  Useful for integer division and modulus.
9088     *
9089     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9090     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9091     */
9092    /* binop/lit16 vA, vB, #+CCCC */
9093    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9094    lsr     w2, wINST, #12              // w2<- B
9095    ubfx    w9, wINST, #8, #4           // w9<- A
9096    GET_VREG w0, w2                     // w0<- vB
9097    .if 1
9098    cbz     w1, common_errDivideByZero
9099    .endif
9100    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9101
9102    sdiv w0, w0, w1                              // w0<- op, w0-w3 changed
9103    GET_INST_OPCODE ip                  // extract opcode from rINST
9104    SET_VREG w0, w9                // vAA<- w0
9105    GOTO_OPCODE ip                      // jump to next instruction
9106    /* 10-13 instructions */
9107
9108    NAME_END nterp_op_div_int_lit16
9109    // Advance to the end of this handler. Causes error if we are past that point.
9110    .org nterp_op_div_int_lit16 + NTERP_HANDLER_SIZE  // op_div_int_lit16 handler is too big!
9111
9112/* ------------------------------ */
9113    .balign NTERP_HANDLER_SIZE
9114.L_op_rem_int_lit16: /* 0xd4 */
9115    NAME_START nterp_op_rem_int_lit16
9116    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9117    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9118
9119    /*
9120     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9121     * that specifies an instruction that performs "result = w0 op w1".
9122     * This could be an ARM instruction or a function call.  (If the result
9123     * comes back in a register other than w0, you can override "result".)
9124     *
9125     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9126     * vCC (w1).  Useful for integer division and modulus.
9127     *
9128     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9129     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9130     */
9131    /* binop/lit16 vA, vB, #+CCCC */
9132    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9133    lsr     w2, wINST, #12              // w2<- B
9134    ubfx    w9, wINST, #8, #4           // w9<- A
9135    GET_VREG w0, w2                     // w0<- vB
9136    .if 1
9137    cbz     w1, common_errDivideByZero
9138    .endif
9139    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9140    sdiv w3, w0, w1
9141    msub w0, w3, w1, w0                              // w0<- op, w0-w3 changed
9142    GET_INST_OPCODE ip                  // extract opcode from rINST
9143    SET_VREG w0, w9                // vAA<- w0
9144    GOTO_OPCODE ip                      // jump to next instruction
9145    /* 10-13 instructions */
9146
9147    NAME_END nterp_op_rem_int_lit16
9148    // Advance to the end of this handler. Causes error if we are past that point.
9149    .org nterp_op_rem_int_lit16 + NTERP_HANDLER_SIZE  // op_rem_int_lit16 handler is too big!
9150
9151/* ------------------------------ */
9152    .balign NTERP_HANDLER_SIZE
9153.L_op_and_int_lit16: /* 0xd5 */
9154    NAME_START nterp_op_and_int_lit16
9155    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9156    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9157
9158    /*
9159     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9160     * that specifies an instruction that performs "result = w0 op w1".
9161     * This could be an ARM instruction or a function call.  (If the result
9162     * comes back in a register other than w0, you can override "result".)
9163     *
9164     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9165     * vCC (w1).  Useful for integer division and modulus.
9166     *
9167     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9168     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9169     */
9170    /* binop/lit16 vA, vB, #+CCCC */
9171    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9172    lsr     w2, wINST, #12              // w2<- B
9173    ubfx    w9, wINST, #8, #4           // w9<- A
9174    GET_VREG w0, w2                     // w0<- vB
9175    .if 0
9176    cbz     w1, common_errDivideByZero
9177    .endif
9178    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9179
9180    and     w0, w0, w1                              // w0<- op, w0-w3 changed
9181    GET_INST_OPCODE ip                  // extract opcode from rINST
9182    SET_VREG w0, w9                // vAA<- w0
9183    GOTO_OPCODE ip                      // jump to next instruction
9184    /* 10-13 instructions */
9185
9186    NAME_END nterp_op_and_int_lit16
9187    // Advance to the end of this handler. Causes error if we are past that point.
9188    .org nterp_op_and_int_lit16 + NTERP_HANDLER_SIZE  // op_and_int_lit16 handler is too big!
9189
9190/* ------------------------------ */
9191    .balign NTERP_HANDLER_SIZE
9192.L_op_or_int_lit16: /* 0xd6 */
9193    NAME_START nterp_op_or_int_lit16
9194    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9195    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9196
9197    /*
9198     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9199     * that specifies an instruction that performs "result = w0 op w1".
9200     * This could be an ARM instruction or a function call.  (If the result
9201     * comes back in a register other than w0, you can override "result".)
9202     *
9203     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9204     * vCC (w1).  Useful for integer division and modulus.
9205     *
9206     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9207     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9208     */
9209    /* binop/lit16 vA, vB, #+CCCC */
9210    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9211    lsr     w2, wINST, #12              // w2<- B
9212    ubfx    w9, wINST, #8, #4           // w9<- A
9213    GET_VREG w0, w2                     // w0<- vB
9214    .if 0
9215    cbz     w1, common_errDivideByZero
9216    .endif
9217    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9218
9219    orr     w0, w0, w1                              // w0<- op, w0-w3 changed
9220    GET_INST_OPCODE ip                  // extract opcode from rINST
9221    SET_VREG w0, w9                // vAA<- w0
9222    GOTO_OPCODE ip                      // jump to next instruction
9223    /* 10-13 instructions */
9224
9225    NAME_END nterp_op_or_int_lit16
9226    // Advance to the end of this handler. Causes error if we are past that point.
9227    .org nterp_op_or_int_lit16 + NTERP_HANDLER_SIZE  // op_or_int_lit16 handler is too big!
9228
9229/* ------------------------------ */
9230    .balign NTERP_HANDLER_SIZE
9231.L_op_xor_int_lit16: /* 0xd7 */
9232    NAME_START nterp_op_xor_int_lit16
9233    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9234    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9235
9236    /*
9237     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
9238     * that specifies an instruction that performs "result = w0 op w1".
9239     * This could be an ARM instruction or a function call.  (If the result
9240     * comes back in a register other than w0, you can override "result".)
9241     *
9242     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9243     * vCC (w1).  Useful for integer division and modulus.
9244     *
9245     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
9246     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
9247     */
9248    /* binop/lit16 vA, vB, #+CCCC */
9249    FETCH_S w1, 1                       // w1<- ssssCCCC (sign-extended)
9250    lsr     w2, wINST, #12              // w2<- B
9251    ubfx    w9, wINST, #8, #4           // w9<- A
9252    GET_VREG w0, w2                     // w0<- vB
9253    .if 0
9254    cbz     w1, common_errDivideByZero
9255    .endif
9256    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9257
9258    eor     w0, w0, w1                              // w0<- op, w0-w3 changed
9259    GET_INST_OPCODE ip                  // extract opcode from rINST
9260    SET_VREG w0, w9                // vAA<- w0
9261    GOTO_OPCODE ip                      // jump to next instruction
9262    /* 10-13 instructions */
9263
9264    NAME_END nterp_op_xor_int_lit16
9265    // Advance to the end of this handler. Causes error if we are past that point.
9266    .org nterp_op_xor_int_lit16 + NTERP_HANDLER_SIZE  // op_xor_int_lit16 handler is too big!
9267
9268/* ------------------------------ */
9269    .balign NTERP_HANDLER_SIZE
9270.L_op_add_int_lit8: /* 0xd8 */
9271    NAME_START nterp_op_add_int_lit8
9272    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9273    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9274
9275    /*
9276     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9277     * that specifies an instruction that performs "result = w0 op w1".
9278     * This could be an ARM instruction or a function call.  (If the result
9279     * comes back in a register other than w0, you can override "result".)
9280     *
9281     * You can override "extract" if the extraction of the literal value
9282     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9283     * can be omitted completely if the shift is embedded in "instr".
9284     *
9285     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9286     * vCC (w1).  Useful for integer division and modulus.
9287     *
9288     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9289     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9290     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9291     */
9292    /* binop/lit8 vAA, vBB, #+CC */
9293    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9294    lsr     w9, wINST, #8               // w9<- AA
9295    and     w2, w3, #255                // w2<- BB
9296    GET_VREG w0, w2                     // w0<- vBB
9297                                // optional; typically w1<- ssssssCC (sign extended)
9298    .if 0
9299    cbz     w1, common_errDivideByZero
9300    .endif
9301    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9302                               // optional op; may set condition codes
9303    add     w0, w0, w3, asr #8                              // w0<- op, w0-w3 changed
9304    GET_INST_OPCODE ip                  // extract opcode from rINST
9305    SET_VREG w0, w9                // vAA<- w0
9306    GOTO_OPCODE ip                      // jump to next instruction
9307    /* 10-12 instructions */
9308
9309    NAME_END nterp_op_add_int_lit8
9310    // Advance to the end of this handler. Causes error if we are past that point.
9311    .org nterp_op_add_int_lit8 + NTERP_HANDLER_SIZE  // op_add_int_lit8 handler is too big!
9312
9313/* ------------------------------ */
9314    .balign NTERP_HANDLER_SIZE
9315.L_op_rsub_int_lit8: /* 0xd9 */
9316    NAME_START nterp_op_rsub_int_lit8
9317    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9318    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9319
9320    /*
9321     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9322     * that specifies an instruction that performs "result = w0 op w1".
9323     * This could be an ARM instruction or a function call.  (If the result
9324     * comes back in a register other than w0, you can override "result".)
9325     *
9326     * You can override "extract" if the extraction of the literal value
9327     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9328     * can be omitted completely if the shift is embedded in "instr".
9329     *
9330     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9331     * vCC (w1).  Useful for integer division and modulus.
9332     *
9333     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9334     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9335     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9336     */
9337    /* binop/lit8 vAA, vBB, #+CC */
9338    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9339    lsr     w9, wINST, #8               // w9<- AA
9340    and     w2, w3, #255                // w2<- BB
9341    GET_VREG w0, w2                     // w0<- vBB
9342    asr     w1, w3, #8                            // optional; typically w1<- ssssssCC (sign extended)
9343    .if 0
9344    cbz     w1, common_errDivideByZero
9345    .endif
9346    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9347                               // optional op; may set condition codes
9348    sub     w0, w1, w0                              // w0<- op, w0-w3 changed
9349    GET_INST_OPCODE ip                  // extract opcode from rINST
9350    SET_VREG w0, w9                // vAA<- w0
9351    GOTO_OPCODE ip                      // jump to next instruction
9352    /* 10-12 instructions */
9353
9354    NAME_END nterp_op_rsub_int_lit8
9355    // Advance to the end of this handler. Causes error if we are past that point.
9356    .org nterp_op_rsub_int_lit8 + NTERP_HANDLER_SIZE  // op_rsub_int_lit8 handler is too big!
9357
9358/* ------------------------------ */
9359    .balign NTERP_HANDLER_SIZE
9360.L_op_mul_int_lit8: /* 0xda */
9361    NAME_START nterp_op_mul_int_lit8
9362    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9363    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9364
9365/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
9366    /*
9367     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9368     * that specifies an instruction that performs "result = w0 op w1".
9369     * This could be an ARM instruction or a function call.  (If the result
9370     * comes back in a register other than w0, you can override "result".)
9371     *
9372     * You can override "extract" if the extraction of the literal value
9373     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9374     * can be omitted completely if the shift is embedded in "instr".
9375     *
9376     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9377     * vCC (w1).  Useful for integer division and modulus.
9378     *
9379     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9380     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9381     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9382     */
9383    /* binop/lit8 vAA, vBB, #+CC */
9384    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9385    lsr     w9, wINST, #8               // w9<- AA
9386    and     w2, w3, #255                // w2<- BB
9387    GET_VREG w0, w2                     // w0<- vBB
9388    asr     w1, w3, #8                            // optional; typically w1<- ssssssCC (sign extended)
9389    .if 0
9390    cbz     w1, common_errDivideByZero
9391    .endif
9392    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9393                               // optional op; may set condition codes
9394    mul     w0, w1, w0                              // w0<- op, w0-w3 changed
9395    GET_INST_OPCODE ip                  // extract opcode from rINST
9396    SET_VREG w0, w9                // vAA<- w0
9397    GOTO_OPCODE ip                      // jump to next instruction
9398    /* 10-12 instructions */
9399
9400    NAME_END nterp_op_mul_int_lit8
9401    // Advance to the end of this handler. Causes error if we are past that point.
9402    .org nterp_op_mul_int_lit8 + NTERP_HANDLER_SIZE  // op_mul_int_lit8 handler is too big!
9403
9404/* ------------------------------ */
9405    .balign NTERP_HANDLER_SIZE
9406.L_op_div_int_lit8: /* 0xdb */
9407    NAME_START nterp_op_div_int_lit8
9408    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9409    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9410
9411    /*
9412     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9413     * that specifies an instruction that performs "result = w0 op w1".
9414     * This could be an ARM instruction or a function call.  (If the result
9415     * comes back in a register other than w0, you can override "result".)
9416     *
9417     * You can override "extract" if the extraction of the literal value
9418     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9419     * can be omitted completely if the shift is embedded in "instr".
9420     *
9421     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9422     * vCC (w1).  Useful for integer division and modulus.
9423     *
9424     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9425     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9426     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9427     */
9428    /* binop/lit8 vAA, vBB, #+CC */
9429    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9430    lsr     w9, wINST, #8               // w9<- AA
9431    and     w2, w3, #255                // w2<- BB
9432    GET_VREG w0, w2                     // w0<- vBB
9433    asr     w1, w3, #8                            // optional; typically w1<- ssssssCC (sign extended)
9434    .if 1
9435    cbz     w1, common_errDivideByZero
9436    .endif
9437    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9438                               // optional op; may set condition codes
9439    sdiv     w0, w0, w1                              // w0<- op, w0-w3 changed
9440    GET_INST_OPCODE ip                  // extract opcode from rINST
9441    SET_VREG w0, w9                // vAA<- w0
9442    GOTO_OPCODE ip                      // jump to next instruction
9443    /* 10-12 instructions */
9444
9445    NAME_END nterp_op_div_int_lit8
9446    // Advance to the end of this handler. Causes error if we are past that point.
9447    .org nterp_op_div_int_lit8 + NTERP_HANDLER_SIZE  // op_div_int_lit8 handler is too big!
9448
9449/* ------------------------------ */
9450    .balign NTERP_HANDLER_SIZE
9451.L_op_rem_int_lit8: /* 0xdc */
9452    NAME_START nterp_op_rem_int_lit8
9453    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9454    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9455
9456    /*
9457     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9458     * that specifies an instruction that performs "result = w0 op w1".
9459     * This could be an ARM instruction or a function call.  (If the result
9460     * comes back in a register other than w0, you can override "result".)
9461     *
9462     * You can override "extract" if the extraction of the literal value
9463     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9464     * can be omitted completely if the shift is embedded in "instr".
9465     *
9466     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9467     * vCC (w1).  Useful for integer division and modulus.
9468     *
9469     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9470     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9471     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9472     */
9473    /* binop/lit8 vAA, vBB, #+CC */
9474    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9475    lsr     w9, wINST, #8               // w9<- AA
9476    and     w2, w3, #255                // w2<- BB
9477    GET_VREG w0, w2                     // w0<- vBB
9478    asr     w1, w3, #8                            // optional; typically w1<- ssssssCC (sign extended)
9479    .if 1
9480    cbz     w1, common_errDivideByZero
9481    .endif
9482    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9483    sdiv w3, w0, w1                           // optional op; may set condition codes
9484    msub w0, w3, w1, w0                              // w0<- op, w0-w3 changed
9485    GET_INST_OPCODE ip                  // extract opcode from rINST
9486    SET_VREG w0, w9                // vAA<- w0
9487    GOTO_OPCODE ip                      // jump to next instruction
9488    /* 10-12 instructions */
9489
9490    NAME_END nterp_op_rem_int_lit8
9491    // Advance to the end of this handler. Causes error if we are past that point.
9492    .org nterp_op_rem_int_lit8 + NTERP_HANDLER_SIZE  // op_rem_int_lit8 handler is too big!
9493
9494/* ------------------------------ */
9495    .balign NTERP_HANDLER_SIZE
9496.L_op_and_int_lit8: /* 0xdd */
9497    NAME_START nterp_op_and_int_lit8
9498    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9499    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9500
9501    /*
9502     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9503     * that specifies an instruction that performs "result = w0 op w1".
9504     * This could be an ARM instruction or a function call.  (If the result
9505     * comes back in a register other than w0, you can override "result".)
9506     *
9507     * You can override "extract" if the extraction of the literal value
9508     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9509     * can be omitted completely if the shift is embedded in "instr".
9510     *
9511     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9512     * vCC (w1).  Useful for integer division and modulus.
9513     *
9514     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9515     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9516     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9517     */
9518    /* binop/lit8 vAA, vBB, #+CC */
9519    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9520    lsr     w9, wINST, #8               // w9<- AA
9521    and     w2, w3, #255                // w2<- BB
9522    GET_VREG w0, w2                     // w0<- vBB
9523                                // optional; typically w1<- ssssssCC (sign extended)
9524    .if 0
9525    cbz     w1, common_errDivideByZero
9526    .endif
9527    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9528                               // optional op; may set condition codes
9529    and     w0, w0, w3, asr #8                              // w0<- op, w0-w3 changed
9530    GET_INST_OPCODE ip                  // extract opcode from rINST
9531    SET_VREG w0, w9                // vAA<- w0
9532    GOTO_OPCODE ip                      // jump to next instruction
9533    /* 10-12 instructions */
9534
9535    NAME_END nterp_op_and_int_lit8
9536    // Advance to the end of this handler. Causes error if we are past that point.
9537    .org nterp_op_and_int_lit8 + NTERP_HANDLER_SIZE  // op_and_int_lit8 handler is too big!
9538
9539/* ------------------------------ */
9540    .balign NTERP_HANDLER_SIZE
9541.L_op_or_int_lit8: /* 0xde */
9542    NAME_START nterp_op_or_int_lit8
9543    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9544    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9545
9546    /*
9547     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9548     * that specifies an instruction that performs "result = w0 op w1".
9549     * This could be an ARM instruction or a function call.  (If the result
9550     * comes back in a register other than w0, you can override "result".)
9551     *
9552     * You can override "extract" if the extraction of the literal value
9553     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9554     * can be omitted completely if the shift is embedded in "instr".
9555     *
9556     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9557     * vCC (w1).  Useful for integer division and modulus.
9558     *
9559     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9560     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9561     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9562     */
9563    /* binop/lit8 vAA, vBB, #+CC */
9564    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9565    lsr     w9, wINST, #8               // w9<- AA
9566    and     w2, w3, #255                // w2<- BB
9567    GET_VREG w0, w2                     // w0<- vBB
9568                                // optional; typically w1<- ssssssCC (sign extended)
9569    .if 0
9570    cbz     w1, common_errDivideByZero
9571    .endif
9572    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9573                               // optional op; may set condition codes
9574    orr     w0, w0, w3, asr #8                              // w0<- op, w0-w3 changed
9575    GET_INST_OPCODE ip                  // extract opcode from rINST
9576    SET_VREG w0, w9                // vAA<- w0
9577    GOTO_OPCODE ip                      // jump to next instruction
9578    /* 10-12 instructions */
9579
9580    NAME_END nterp_op_or_int_lit8
9581    // Advance to the end of this handler. Causes error if we are past that point.
9582    .org nterp_op_or_int_lit8 + NTERP_HANDLER_SIZE  // op_or_int_lit8 handler is too big!
9583
9584/* ------------------------------ */
9585    .balign NTERP_HANDLER_SIZE
9586.L_op_xor_int_lit8: /* 0xdf */
9587    NAME_START nterp_op_xor_int_lit8
9588    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9589    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9590
9591    /*
9592     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9593     * that specifies an instruction that performs "result = w0 op w1".
9594     * This could be an ARM instruction or a function call.  (If the result
9595     * comes back in a register other than w0, you can override "result".)
9596     *
9597     * You can override "extract" if the extraction of the literal value
9598     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9599     * can be omitted completely if the shift is embedded in "instr".
9600     *
9601     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9602     * vCC (w1).  Useful for integer division and modulus.
9603     *
9604     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9605     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9606     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9607     */
9608    /* binop/lit8 vAA, vBB, #+CC */
9609    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9610    lsr     w9, wINST, #8               // w9<- AA
9611    and     w2, w3, #255                // w2<- BB
9612    GET_VREG w0, w2                     // w0<- vBB
9613                                // optional; typically w1<- ssssssCC (sign extended)
9614    .if 0
9615    cbz     w1, common_errDivideByZero
9616    .endif
9617    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9618                               // optional op; may set condition codes
9619    eor     w0, w0, w3, asr #8                              // w0<- op, w0-w3 changed
9620    GET_INST_OPCODE ip                  // extract opcode from rINST
9621    SET_VREG w0, w9                // vAA<- w0
9622    GOTO_OPCODE ip                      // jump to next instruction
9623    /* 10-12 instructions */
9624
9625    NAME_END nterp_op_xor_int_lit8
9626    // Advance to the end of this handler. Causes error if we are past that point.
9627    .org nterp_op_xor_int_lit8 + NTERP_HANDLER_SIZE  // op_xor_int_lit8 handler is too big!
9628
9629/* ------------------------------ */
9630    .balign NTERP_HANDLER_SIZE
9631.L_op_shl_int_lit8: /* 0xe0 */
9632    NAME_START nterp_op_shl_int_lit8
9633    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9634    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9635
9636    /*
9637     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9638     * that specifies an instruction that performs "result = w0 op w1".
9639     * This could be an ARM instruction or a function call.  (If the result
9640     * comes back in a register other than w0, you can override "result".)
9641     *
9642     * You can override "extract" if the extraction of the literal value
9643     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9644     * can be omitted completely if the shift is embedded in "instr".
9645     *
9646     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9647     * vCC (w1).  Useful for integer division and modulus.
9648     *
9649     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9650     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9651     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9652     */
9653    /* binop/lit8 vAA, vBB, #+CC */
9654    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9655    lsr     w9, wINST, #8               // w9<- AA
9656    and     w2, w3, #255                // w2<- BB
9657    GET_VREG w0, w2                     // w0<- vBB
9658    ubfx    w1, w3, #8, #5                            // optional; typically w1<- ssssssCC (sign extended)
9659    .if 0
9660    cbz     w1, common_errDivideByZero
9661    .endif
9662    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9663                               // optional op; may set condition codes
9664    lsl     w0, w0, w1                              // w0<- op, w0-w3 changed
9665    GET_INST_OPCODE ip                  // extract opcode from rINST
9666    SET_VREG w0, w9                // vAA<- w0
9667    GOTO_OPCODE ip                      // jump to next instruction
9668    /* 10-12 instructions */
9669
9670    NAME_END nterp_op_shl_int_lit8
9671    // Advance to the end of this handler. Causes error if we are past that point.
9672    .org nterp_op_shl_int_lit8 + NTERP_HANDLER_SIZE  // op_shl_int_lit8 handler is too big!
9673
9674/* ------------------------------ */
9675    .balign NTERP_HANDLER_SIZE
9676.L_op_shr_int_lit8: /* 0xe1 */
9677    NAME_START nterp_op_shr_int_lit8
9678    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9679    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9680
9681    /*
9682     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9683     * that specifies an instruction that performs "result = w0 op w1".
9684     * This could be an ARM instruction or a function call.  (If the result
9685     * comes back in a register other than w0, you can override "result".)
9686     *
9687     * You can override "extract" if the extraction of the literal value
9688     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9689     * can be omitted completely if the shift is embedded in "instr".
9690     *
9691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9692     * vCC (w1).  Useful for integer division and modulus.
9693     *
9694     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9695     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9696     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9697     */
9698    /* binop/lit8 vAA, vBB, #+CC */
9699    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9700    lsr     w9, wINST, #8               // w9<- AA
9701    and     w2, w3, #255                // w2<- BB
9702    GET_VREG w0, w2                     // w0<- vBB
9703    ubfx    w1, w3, #8, #5                            // optional; typically w1<- ssssssCC (sign extended)
9704    .if 0
9705    cbz     w1, common_errDivideByZero
9706    .endif
9707    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9708                               // optional op; may set condition codes
9709    asr     w0, w0, w1                              // w0<- op, w0-w3 changed
9710    GET_INST_OPCODE ip                  // extract opcode from rINST
9711    SET_VREG w0, w9                // vAA<- w0
9712    GOTO_OPCODE ip                      // jump to next instruction
9713    /* 10-12 instructions */
9714
9715    NAME_END nterp_op_shr_int_lit8
9716    // Advance to the end of this handler. Causes error if we are past that point.
9717    .org nterp_op_shr_int_lit8 + NTERP_HANDLER_SIZE  // op_shr_int_lit8 handler is too big!
9718
9719/* ------------------------------ */
9720    .balign NTERP_HANDLER_SIZE
9721.L_op_ushr_int_lit8: /* 0xe2 */
9722    NAME_START nterp_op_ushr_int_lit8
9723    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9724    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9725
9726    /*
9727     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
9728     * that specifies an instruction that performs "result = w0 op w1".
9729     * This could be an ARM instruction or a function call.  (If the result
9730     * comes back in a register other than w0, you can override "result".)
9731     *
9732     * You can override "extract" if the extraction of the literal value
9733     * from w3 to w1 is not the default "asr w1, w3, #8". The extraction
9734     * can be omitted completely if the shift is embedded in "instr".
9735     *
9736     * If "chkzero" is set to 1, we perform a divide-by-zero check on
9737     * vCC (w1).  Useful for integer division and modulus.
9738     *
9739     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
9740     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
9741     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
9742     */
9743    /* binop/lit8 vAA, vBB, #+CC */
9744    FETCH_S w3, 1                       // w3<- ssssCCBB (sign-extended for CC)
9745    lsr     w9, wINST, #8               // w9<- AA
9746    and     w2, w3, #255                // w2<- BB
9747    GET_VREG w0, w2                     // w0<- vBB
9748    ubfx    w1, w3, #8, #5                            // optional; typically w1<- ssssssCC (sign extended)
9749    .if 0
9750    cbz     w1, common_errDivideByZero
9751    .endif
9752    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
9753                               // optional op; may set condition codes
9754    lsr     w0, w0, w1                              // w0<- op, w0-w3 changed
9755    GET_INST_OPCODE ip                  // extract opcode from rINST
9756    SET_VREG w0, w9                // vAA<- w0
9757    GOTO_OPCODE ip                      // jump to next instruction
9758    /* 10-12 instructions */
9759
9760    NAME_END nterp_op_ushr_int_lit8
9761    // Advance to the end of this handler. Causes error if we are past that point.
9762    .org nterp_op_ushr_int_lit8 + NTERP_HANDLER_SIZE  // op_ushr_int_lit8 handler is too big!
9763
9764/* ------------------------------ */
9765    .balign NTERP_HANDLER_SIZE
9766.L_op_unused_e3: /* 0xe3 */
9767    NAME_START nterp_op_unused_e3
9768    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9769    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9770
9771    brk 42
9772
9773    NAME_END nterp_op_unused_e3
9774    // Advance to the end of this handler. Causes error if we are past that point.
9775    .org nterp_op_unused_e3 + NTERP_HANDLER_SIZE  // op_unused_e3 handler is too big!
9776
9777/* ------------------------------ */
9778    .balign NTERP_HANDLER_SIZE
9779.L_op_unused_e4: /* 0xe4 */
9780    NAME_START nterp_op_unused_e4
9781    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9782    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9783
9784    brk 42
9785
9786    NAME_END nterp_op_unused_e4
9787    // Advance to the end of this handler. Causes error if we are past that point.
9788    .org nterp_op_unused_e4 + NTERP_HANDLER_SIZE  // op_unused_e4 handler is too big!
9789
9790/* ------------------------------ */
9791    .balign NTERP_HANDLER_SIZE
9792.L_op_unused_e5: /* 0xe5 */
9793    NAME_START nterp_op_unused_e5
9794    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9795    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9796
9797    brk 42
9798
9799    NAME_END nterp_op_unused_e5
9800    // Advance to the end of this handler. Causes error if we are past that point.
9801    .org nterp_op_unused_e5 + NTERP_HANDLER_SIZE  // op_unused_e5 handler is too big!
9802
9803/* ------------------------------ */
9804    .balign NTERP_HANDLER_SIZE
9805.L_op_unused_e6: /* 0xe6 */
9806    NAME_START nterp_op_unused_e6
9807    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9808    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9809
9810    brk 42
9811
9812    NAME_END nterp_op_unused_e6
9813    // Advance to the end of this handler. Causes error if we are past that point.
9814    .org nterp_op_unused_e6 + NTERP_HANDLER_SIZE  // op_unused_e6 handler is too big!
9815
9816/* ------------------------------ */
9817    .balign NTERP_HANDLER_SIZE
9818.L_op_unused_e7: /* 0xe7 */
9819    NAME_START nterp_op_unused_e7
9820    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9821    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9822
9823    brk 42
9824
9825    NAME_END nterp_op_unused_e7
9826    // Advance to the end of this handler. Causes error if we are past that point.
9827    .org nterp_op_unused_e7 + NTERP_HANDLER_SIZE  // op_unused_e7 handler is too big!
9828
9829/* ------------------------------ */
9830    .balign NTERP_HANDLER_SIZE
9831.L_op_unused_e8: /* 0xe8 */
9832    NAME_START nterp_op_unused_e8
9833    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9834    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9835
9836    brk 42
9837
9838    NAME_END nterp_op_unused_e8
9839    // Advance to the end of this handler. Causes error if we are past that point.
9840    .org nterp_op_unused_e8 + NTERP_HANDLER_SIZE  // op_unused_e8 handler is too big!
9841
9842/* ------------------------------ */
9843    .balign NTERP_HANDLER_SIZE
9844.L_op_unused_e9: /* 0xe9 */
9845    NAME_START nterp_op_unused_e9
9846    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9847    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9848
9849    brk 42
9850
9851    NAME_END nterp_op_unused_e9
9852    // Advance to the end of this handler. Causes error if we are past that point.
9853    .org nterp_op_unused_e9 + NTERP_HANDLER_SIZE  // op_unused_e9 handler is too big!
9854
9855/* ------------------------------ */
9856    .balign NTERP_HANDLER_SIZE
9857.L_op_unused_ea: /* 0xea */
9858    NAME_START nterp_op_unused_ea
9859    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9860    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9861
9862    brk 42
9863
9864    NAME_END nterp_op_unused_ea
9865    // Advance to the end of this handler. Causes error if we are past that point.
9866    .org nterp_op_unused_ea + NTERP_HANDLER_SIZE  // op_unused_ea handler is too big!
9867
9868/* ------------------------------ */
9869    .balign NTERP_HANDLER_SIZE
9870.L_op_unused_eb: /* 0xeb */
9871    NAME_START nterp_op_unused_eb
9872    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9873    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9874
9875    brk 42
9876
9877    NAME_END nterp_op_unused_eb
9878    // Advance to the end of this handler. Causes error if we are past that point.
9879    .org nterp_op_unused_eb + NTERP_HANDLER_SIZE  // op_unused_eb handler is too big!
9880
9881/* ------------------------------ */
9882    .balign NTERP_HANDLER_SIZE
9883.L_op_unused_ec: /* 0xec */
9884    NAME_START nterp_op_unused_ec
9885    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9886    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9887
9888    brk 42
9889
9890    NAME_END nterp_op_unused_ec
9891    // Advance to the end of this handler. Causes error if we are past that point.
9892    .org nterp_op_unused_ec + NTERP_HANDLER_SIZE  // op_unused_ec handler is too big!
9893
9894/* ------------------------------ */
9895    .balign NTERP_HANDLER_SIZE
9896.L_op_unused_ed: /* 0xed */
9897    NAME_START nterp_op_unused_ed
9898    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9899    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9900
9901    brk 42
9902
9903    NAME_END nterp_op_unused_ed
9904    // Advance to the end of this handler. Causes error if we are past that point.
9905    .org nterp_op_unused_ed + NTERP_HANDLER_SIZE  // op_unused_ed handler is too big!
9906
9907/* ------------------------------ */
9908    .balign NTERP_HANDLER_SIZE
9909.L_op_unused_ee: /* 0xee */
9910    NAME_START nterp_op_unused_ee
9911    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9912    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9913
9914    brk 42
9915
9916    NAME_END nterp_op_unused_ee
9917    // Advance to the end of this handler. Causes error if we are past that point.
9918    .org nterp_op_unused_ee + NTERP_HANDLER_SIZE  // op_unused_ee handler is too big!
9919
9920/* ------------------------------ */
9921    .balign NTERP_HANDLER_SIZE
9922.L_op_unused_ef: /* 0xef */
9923    NAME_START nterp_op_unused_ef
9924    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9925    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9926
9927    brk 42
9928
9929    NAME_END nterp_op_unused_ef
9930    // Advance to the end of this handler. Causes error if we are past that point.
9931    .org nterp_op_unused_ef + NTERP_HANDLER_SIZE  // op_unused_ef handler is too big!
9932
9933/* ------------------------------ */
9934    .balign NTERP_HANDLER_SIZE
9935.L_op_unused_f0: /* 0xf0 */
9936    NAME_START nterp_op_unused_f0
9937    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9938    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9939
9940    brk 42
9941
9942    NAME_END nterp_op_unused_f0
9943    // Advance to the end of this handler. Causes error if we are past that point.
9944    .org nterp_op_unused_f0 + NTERP_HANDLER_SIZE  // op_unused_f0 handler is too big!
9945
9946/* ------------------------------ */
9947    .balign NTERP_HANDLER_SIZE
9948.L_op_unused_f1: /* 0xf1 */
9949    NAME_START nterp_op_unused_f1
9950    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9951    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9952
9953    brk 42
9954
9955    NAME_END nterp_op_unused_f1
9956    // Advance to the end of this handler. Causes error if we are past that point.
9957    .org nterp_op_unused_f1 + NTERP_HANDLER_SIZE  // op_unused_f1 handler is too big!
9958
9959/* ------------------------------ */
9960    .balign NTERP_HANDLER_SIZE
9961.L_op_unused_f2: /* 0xf2 */
9962    NAME_START nterp_op_unused_f2
9963    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9964    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9965
9966    brk 42
9967
9968    NAME_END nterp_op_unused_f2
9969    // Advance to the end of this handler. Causes error if we are past that point.
9970    .org nterp_op_unused_f2 + NTERP_HANDLER_SIZE  // op_unused_f2 handler is too big!
9971
9972/* ------------------------------ */
9973    .balign NTERP_HANDLER_SIZE
9974.L_op_unused_f3: /* 0xf3 */
9975    NAME_START nterp_op_unused_f3
9976    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9977    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9978
9979    brk 42
9980
9981    NAME_END nterp_op_unused_f3
9982    // Advance to the end of this handler. Causes error if we are past that point.
9983    .org nterp_op_unused_f3 + NTERP_HANDLER_SIZE  // op_unused_f3 handler is too big!
9984
9985/* ------------------------------ */
9986    .balign NTERP_HANDLER_SIZE
9987.L_op_unused_f4: /* 0xf4 */
9988    NAME_START nterp_op_unused_f4
9989    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
9990    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
9991
9992    brk 42
9993
9994    NAME_END nterp_op_unused_f4
9995    // Advance to the end of this handler. Causes error if we are past that point.
9996    .org nterp_op_unused_f4 + NTERP_HANDLER_SIZE  // op_unused_f4 handler is too big!
9997
9998/* ------------------------------ */
9999    .balign NTERP_HANDLER_SIZE
10000.L_op_unused_f5: /* 0xf5 */
10001    NAME_START nterp_op_unused_f5
10002    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10003    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10004
10005    brk 42
10006
10007    NAME_END nterp_op_unused_f5
10008    // Advance to the end of this handler. Causes error if we are past that point.
10009    .org nterp_op_unused_f5 + NTERP_HANDLER_SIZE  // op_unused_f5 handler is too big!
10010
10011/* ------------------------------ */
10012    .balign NTERP_HANDLER_SIZE
10013.L_op_unused_f6: /* 0xf6 */
10014    NAME_START nterp_op_unused_f6
10015    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10016    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10017
10018    brk 42
10019
10020    NAME_END nterp_op_unused_f6
10021    // Advance to the end of this handler. Causes error if we are past that point.
10022    .org nterp_op_unused_f6 + NTERP_HANDLER_SIZE  // op_unused_f6 handler is too big!
10023
10024/* ------------------------------ */
10025    .balign NTERP_HANDLER_SIZE
10026.L_op_unused_f7: /* 0xf7 */
10027    NAME_START nterp_op_unused_f7
10028    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10029    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10030
10031    brk 42
10032
10033    NAME_END nterp_op_unused_f7
10034    // Advance to the end of this handler. Causes error if we are past that point.
10035    .org nterp_op_unused_f7 + NTERP_HANDLER_SIZE  // op_unused_f7 handler is too big!
10036
10037/* ------------------------------ */
10038    .balign NTERP_HANDLER_SIZE
10039.L_op_unused_f8: /* 0xf8 */
10040    NAME_START nterp_op_unused_f8
10041    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10042    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10043
10044    brk 42
10045
10046    NAME_END nterp_op_unused_f8
10047    // Advance to the end of this handler. Causes error if we are past that point.
10048    .org nterp_op_unused_f8 + NTERP_HANDLER_SIZE  // op_unused_f8 handler is too big!
10049
10050/* ------------------------------ */
10051    .balign NTERP_HANDLER_SIZE
10052.L_op_unused_f9: /* 0xf9 */
10053    NAME_START nterp_op_unused_f9
10054    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10055    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10056
10057    brk 42
10058
10059    NAME_END nterp_op_unused_f9
10060    // Advance to the end of this handler. Causes error if we are past that point.
10061    .org nterp_op_unused_f9 + NTERP_HANDLER_SIZE  // op_unused_f9 handler is too big!
10062
10063/* ------------------------------ */
10064    .balign NTERP_HANDLER_SIZE
10065.L_op_invoke_polymorphic: /* 0xfa */
10066    NAME_START nterp_op_invoke_polymorphic
10067    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10068    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10069
10070   EXPORT_PC
10071   // No need to fetch the target method.
10072   // Load the first argument (the 'this' pointer).
10073   FETCH w1, 2
10074   and w1, w1, #0xf
10075   GET_VREG w1, w1
10076   cbz w1, common_errNullObject    // bail if null
10077   b NterpCommonInvokePolymorphic
10078
10079    NAME_END nterp_op_invoke_polymorphic
10080    // Advance to the end of this handler. Causes error if we are past that point.
10081    .org nterp_op_invoke_polymorphic + NTERP_HANDLER_SIZE  // op_invoke_polymorphic handler is too big!
10082
10083/* ------------------------------ */
10084    .balign NTERP_HANDLER_SIZE
10085.L_op_invoke_polymorphic_range: /* 0xfb */
10086    NAME_START nterp_op_invoke_polymorphic_range
10087    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10088    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10089
10090   EXPORT_PC
10091   // No need to fetch the target method.
10092   // Load the first argument (the 'this' pointer).
10093   FETCH w1, 2
10094   GET_VREG w1, w1
10095   cbz w1, common_errNullObject    // bail if null
10096   b NterpCommonInvokePolymorphicRange
10097
10098    NAME_END nterp_op_invoke_polymorphic_range
10099    // Advance to the end of this handler. Causes error if we are past that point.
10100    .org nterp_op_invoke_polymorphic_range + NTERP_HANDLER_SIZE  // op_invoke_polymorphic_range handler is too big!
10101
10102/* ------------------------------ */
10103    .balign NTERP_HANDLER_SIZE
10104.L_op_invoke_custom: /* 0xfc */
10105    NAME_START nterp_op_invoke_custom
10106    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10107    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10108
10109   EXPORT_PC
10110   FETCH w0, 1 // call_site index, first argument of runtime call.
10111   b NterpCommonInvokeCustom
10112
10113    NAME_END nterp_op_invoke_custom
10114    // Advance to the end of this handler. Causes error if we are past that point.
10115    .org nterp_op_invoke_custom + NTERP_HANDLER_SIZE  // op_invoke_custom handler is too big!
10116
10117/* ------------------------------ */
10118    .balign NTERP_HANDLER_SIZE
10119.L_op_invoke_custom_range: /* 0xfd */
10120    NAME_START nterp_op_invoke_custom_range
10121    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10122    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10123
10124   EXPORT_PC
10125   FETCH w0, 1 // call_site index, first argument of runtime call.
10126   b NterpCommonInvokeCustomRange
10127
10128    NAME_END nterp_op_invoke_custom_range
10129    // Advance to the end of this handler. Causes error if we are past that point.
10130    .org nterp_op_invoke_custom_range + NTERP_HANDLER_SIZE  // op_invoke_custom_range handler is too big!
10131
10132/* ------------------------------ */
10133    .balign NTERP_HANDLER_SIZE
10134.L_op_const_method_handle: /* 0xfe */
10135    NAME_START nterp_op_const_method_handle
10136    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10137    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10138
10139   // Fast-path which gets the object from thread-local cache.
10140   // Fetch some information from the thread cache.
10141   // Uses ip and ip2 as temporaries.
10142   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
10143   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
10144   add      ip, ip, ip2, lsl #4            // entry address within the cache
10145   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
10146   cmp      ip, xPC
10147   b.ne     2f
10148
10149   TEST_IF_MARKING 3f
101501:
10151   lsr     w1, wINST, #8               // w1<- AA
10152   .if 0
10153   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
10154   .else
10155   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
10156   .endif
10157   GET_INST_OPCODE ip                  // extract opcode from wINST
10158   SET_VREG_OBJECT w0, w1              // vAA <- value
10159   GOTO_OPCODE ip                      // jump to next instruction
101602:
10161   EXPORT_PC
10162   mov x0, xSELF
10163   ldr x1, [sp]
10164   mov x2, xPC
10165   bl nterp_load_object
10166   b 1b
101673:
10168   bl art_quick_read_barrier_mark_reg00
10169   b 1b
10170
10171    NAME_END nterp_op_const_method_handle
10172    // Advance to the end of this handler. Causes error if we are past that point.
10173    .org nterp_op_const_method_handle + NTERP_HANDLER_SIZE  // op_const_method_handle handler is too big!
10174
10175/* ------------------------------ */
10176    .balign NTERP_HANDLER_SIZE
10177.L_op_const_method_type: /* 0xff */
10178    NAME_START nterp_op_const_method_type
10179    # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*).
10180    CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE
10181
10182   // Fast-path which gets the object from thread-local cache.
10183   // Fetch some information from the thread cache.
10184   // Uses ip and ip2 as temporaries.
10185   add      ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET       // cache address
10186   ubfx     ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2  // entry index
10187   add      ip, ip, ip2, lsl #4            // entry address within the cache
10188   ldp      ip, x0, [ip]          // entry key (pc) and value (offset)
10189   cmp      ip, xPC
10190   b.ne     2f
10191
10192   TEST_IF_MARKING 3f
101931:
10194   lsr     w1, wINST, #8               // w1<- AA
10195   .if 0
10196   FETCH_ADVANCE_INST 3                // advance rPC, load wINST
10197   .else
10198   FETCH_ADVANCE_INST 2                // advance rPC, load wINST
10199   .endif
10200   GET_INST_OPCODE ip                  // extract opcode from wINST
10201   SET_VREG_OBJECT w0, w1              // vAA <- value
10202   GOTO_OPCODE ip                      // jump to next instruction
102032:
10204   EXPORT_PC
10205   mov x0, xSELF
10206   ldr x1, [sp]
10207   mov x2, xPC
10208   bl nterp_load_object
10209   b 1b
102103:
10211   bl art_quick_read_barrier_mark_reg00
10212   b 1b
10213
10214    NAME_END nterp_op_const_method_type
10215    // Advance to the end of this handler. Causes error if we are past that point.
10216    .org nterp_op_const_method_type + NTERP_HANDLER_SIZE  // op_const_method_type handler is too big!
10217
10218    .balign NTERP_HANDLER_SIZE
10219
10220    .type artNterpAsmInstructionEnd, #function
10221    .hidden artNterpAsmInstructionEnd
10222    .global artNterpAsmInstructionEnd
10223artNterpAsmInstructionEnd:
10224    // artNterpAsmInstructionEnd is used as landing pad for exception handling.
10225    FETCH_INST
10226    GET_INST_OPCODE ip
10227    GOTO_OPCODE ip
10228
10229    NAME_START nterp_op_check_cast_slow_path
10230   // We don't do read barriers for simplicity. However, this means that x1
10231   // (and all other fetched objects) may be a from-space reference. Tthat's OK as
10232   // we only fetch constant information from the references.
10233   // This also means that some of the comparisons below may lead to false negative,
10234   // but it will eventually be handled in the runtime.
10235   ldr     w3, [x1, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET]
10236   tbnz    w3, #MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, 2f
10237   ldr     w3, [x1, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET]
10238   UNPOISON_HEAP_REF w3
10239   cbnz    w3, 5f
102401:
10241   ldr     w2, [x2, #MIRROR_CLASS_SUPER_CLASS_OFFSET]
10242   UNPOISON_HEAP_REF w2
10243   cmp     w1, w2
10244   beq     .Lop_check_cast_resume
10245   cbnz    w2, 1b
102462:
10247   TEST_IF_MARKING 4f
102483:
10249   EXPORT_PC
10250   bl      art_quick_check_instance_of
10251   b       .Lop_check_cast_resume
102524:
10253   bl      art_quick_read_barrier_mark_reg01
10254   b       3b
102555:
10256   // Class in w1 is an array, w3 is the component type.
10257   ldr     w2, [x2, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET]
10258   UNPOISON_HEAP_REF w2
10259   // Check if object is an array.
10260   cbz     w2, 2b
10261   ldr     w4, [x3, #MIRROR_CLASS_SUPER_CLASS_OFFSET]
10262   UNPOISON_HEAP_REF w4
10263   // If the super class of the component type is not null, go slow path.
10264   cbnz    w4, 2b
10265   ldrh    w3, [x3, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET]
10266   // If the component type is primitive, go slow path.
10267   cbnz    w3, 2b
10268   // Check if the object is a primitive array.
10269   ldrh    w2, [x2, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET]
10270   cbz     w2, .Lop_check_cast_resume
10271   // Go slow path for throwing the exception.
10272   b 2b
10273
10274    NAME_END nterp_op_check_cast_slow_path
10275    NAME_START nterp_op_iget_boolean_slow_path
10276   mov     x0, xSELF
10277   ldr     x1, [sp]
10278   mov     x2, xPC
10279   mov     x3, #0
10280   EXPORT_PC
10281   bl      nterp_get_instance_field_offset
10282   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10283   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10284   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10285   mov     w0, w0
10286   tbz     w0, #31, .Lop_iget_boolean_resume
10287   CLEAR_INSTANCE_VOLATILE_MARKER w0
10288   lsr     w2, wINST, #12              // w2<- B
10289   GET_VREG w3, w2                     // w3<- object we're operating on
10290   ubfx    w2, wINST, #8, #4           // w2<- A
10291   cbz     w3, common_errNullObject    // object was null
10292   add     x3, x3, x0
10293   .if 0
10294   ldarb x0, [x3]
10295   SET_VREG_WIDE x0, w2                // fp[A] <- value
10296   .elseif 0
10297   ldarb w0, [x3]
10298   UNPOISON_HEAP_REF w0
10299   TEST_IF_MARKING .Lop_iget_boolean_read_barrier
10300   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10301   .else
10302   ldarb w0, [x3]
10303
10304   SET_VREG w0, w2                     // fp[A] <- value
10305   .endif
10306   FETCH_ADVANCE_INST 2
10307   GET_INST_OPCODE ip
10308   GOTO_OPCODE ip
10309
10310    NAME_END nterp_op_iget_boolean_slow_path
10311    NAME_START nterp_op_iget_byte_slow_path
10312   mov     x0, xSELF
10313   ldr     x1, [sp]
10314   mov     x2, xPC
10315   mov     x3, #0
10316   EXPORT_PC
10317   bl      nterp_get_instance_field_offset
10318   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10319   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10320   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10321   mov     w0, w0
10322   tbz     w0, #31, .Lop_iget_byte_resume
10323   CLEAR_INSTANCE_VOLATILE_MARKER w0
10324   lsr     w2, wINST, #12              // w2<- B
10325   GET_VREG w3, w2                     // w3<- object we're operating on
10326   ubfx    w2, wINST, #8, #4           // w2<- A
10327   cbz     w3, common_errNullObject    // object was null
10328   add     x3, x3, x0
10329   .if 0
10330   ldarb x0, [x3]
10331   SET_VREG_WIDE x0, w2                // fp[A] <- value
10332   .elseif 0
10333   ldarb w0, [x3]
10334   UNPOISON_HEAP_REF w0
10335   TEST_IF_MARKING .Lop_iget_byte_read_barrier
10336   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10337   .else
10338   ldarb w0, [x3]
10339   sxtb w0, w0
10340   SET_VREG w0, w2                     // fp[A] <- value
10341   .endif
10342   FETCH_ADVANCE_INST 2
10343   GET_INST_OPCODE ip
10344   GOTO_OPCODE ip
10345
10346    NAME_END nterp_op_iget_byte_slow_path
10347    NAME_START nterp_op_iget_char_slow_path
10348   mov     x0, xSELF
10349   ldr     x1, [sp]
10350   mov     x2, xPC
10351   mov     x3, #0
10352   EXPORT_PC
10353   bl      nterp_get_instance_field_offset
10354   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10355   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10356   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10357   mov     w0, w0
10358   tbz     w0, #31, .Lop_iget_char_resume
10359   CLEAR_INSTANCE_VOLATILE_MARKER w0
10360   lsr     w2, wINST, #12              // w2<- B
10361   GET_VREG w3, w2                     // w3<- object we're operating on
10362   ubfx    w2, wINST, #8, #4           // w2<- A
10363   cbz     w3, common_errNullObject    // object was null
10364   add     x3, x3, x0
10365   .if 0
10366   ldarh x0, [x3]
10367   SET_VREG_WIDE x0, w2                // fp[A] <- value
10368   .elseif 0
10369   ldarh w0, [x3]
10370   UNPOISON_HEAP_REF w0
10371   TEST_IF_MARKING .Lop_iget_char_read_barrier
10372   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10373   .else
10374   ldarh w0, [x3]
10375
10376   SET_VREG w0, w2                     // fp[A] <- value
10377   .endif
10378   FETCH_ADVANCE_INST 2
10379   GET_INST_OPCODE ip
10380   GOTO_OPCODE ip
10381
10382    NAME_END nterp_op_iget_char_slow_path
10383    NAME_START nterp_op_iget_object_slow_path
10384   mov     x0, xSELF
10385   ldr     x1, [sp]
10386   mov     x2, xPC
10387   mov     x3, #0
10388   EXPORT_PC
10389   bl      nterp_get_instance_field_offset
10390   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10391   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10392   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10393   mov     w0, w0
10394   tbz     w0, #31, .Lop_iget_object_resume
10395   CLEAR_INSTANCE_VOLATILE_MARKER w0
10396   lsr     w2, wINST, #12              // w2<- B
10397   GET_VREG w3, w2                     // w3<- object we're operating on
10398   ubfx    w2, wINST, #8, #4           // w2<- A
10399   cbz     w3, common_errNullObject    // object was null
10400   add     x3, x3, x0
10401   .if 0
10402   ldar x0, [x3]
10403   SET_VREG_WIDE x0, w2                // fp[A] <- value
10404   .elseif 1
10405   ldar w0, [x3]
10406   UNPOISON_HEAP_REF w0
10407   TEST_IF_MARKING .Lop_iget_object_read_barrier
10408   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10409   .else
10410   ldar w0, [x3]
10411
10412   SET_VREG w0, w2                     // fp[A] <- value
10413   .endif
10414   FETCH_ADVANCE_INST 2
10415   GET_INST_OPCODE ip
10416   GOTO_OPCODE ip
10417
10418    NAME_END nterp_op_iget_object_slow_path
10419    NAME_START nterp_op_iget_short_slow_path
10420   mov     x0, xSELF
10421   ldr     x1, [sp]
10422   mov     x2, xPC
10423   mov     x3, #0
10424   EXPORT_PC
10425   bl      nterp_get_instance_field_offset
10426   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10427   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10428   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10429   mov     w0, w0
10430   tbz     w0, #31, .Lop_iget_short_resume
10431   CLEAR_INSTANCE_VOLATILE_MARKER w0
10432   lsr     w2, wINST, #12              // w2<- B
10433   GET_VREG w3, w2                     // w3<- object we're operating on
10434   ubfx    w2, wINST, #8, #4           // w2<- A
10435   cbz     w3, common_errNullObject    // object was null
10436   add     x3, x3, x0
10437   .if 0
10438   ldarh x0, [x3]
10439   SET_VREG_WIDE x0, w2                // fp[A] <- value
10440   .elseif 0
10441   ldarh w0, [x3]
10442   UNPOISON_HEAP_REF w0
10443   TEST_IF_MARKING .Lop_iget_short_read_barrier
10444   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10445   .else
10446   ldarh w0, [x3]
10447   sxth w0, w0
10448   SET_VREG w0, w2                     // fp[A] <- value
10449   .endif
10450   FETCH_ADVANCE_INST 2
10451   GET_INST_OPCODE ip
10452   GOTO_OPCODE ip
10453
10454    NAME_END nterp_op_iget_short_slow_path
10455    NAME_START nterp_op_iget_slow_path
10456   mov     x0, xSELF
10457   ldr     x1, [sp]
10458   mov     x2, xPC
10459   mov     x3, #0
10460   EXPORT_PC
10461   bl      nterp_get_instance_field_offset
10462   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10463   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10464   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10465   mov     w0, w0
10466   tbz     w0, #31, .Lop_iget_resume
10467   CLEAR_INSTANCE_VOLATILE_MARKER w0
10468   lsr     w2, wINST, #12              // w2<- B
10469   GET_VREG w3, w2                     // w3<- object we're operating on
10470   ubfx    w2, wINST, #8, #4           // w2<- A
10471   cbz     w3, common_errNullObject    // object was null
10472   add     x3, x3, x0
10473   .if 0
10474   ldar x0, [x3]
10475   SET_VREG_WIDE x0, w2                // fp[A] <- value
10476   .elseif 0
10477   ldar w0, [x3]
10478   UNPOISON_HEAP_REF w0
10479   TEST_IF_MARKING .Lop_iget_read_barrier
10480   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10481   .else
10482   ldar w0, [x3]
10483
10484   SET_VREG w0, w2                     // fp[A] <- value
10485   .endif
10486   FETCH_ADVANCE_INST 2
10487   GET_INST_OPCODE ip
10488   GOTO_OPCODE ip
10489
10490    NAME_END nterp_op_iget_slow_path
10491    NAME_START nterp_op_iget_wide_slow_path
10492   mov     x0, xSELF
10493   ldr     x1, [sp]
10494   mov     x2, xPC
10495   mov     x3, #0
10496   EXPORT_PC
10497   bl      nterp_get_instance_field_offset
10498   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10499   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10500   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10501   mov     w0, w0
10502   tbz     w0, #31, .Lop_iget_wide_resume
10503   CLEAR_INSTANCE_VOLATILE_MARKER w0
10504   lsr     w2, wINST, #12              // w2<- B
10505   GET_VREG w3, w2                     // w3<- object we're operating on
10506   ubfx    w2, wINST, #8, #4           // w2<- A
10507   cbz     w3, common_errNullObject    // object was null
10508   add     x3, x3, x0
10509   .if 1
10510   ldar x0, [x3]
10511   SET_VREG_WIDE x0, w2                // fp[A] <- value
10512   .elseif 0
10513   ldar w0, [x3]
10514   UNPOISON_HEAP_REF w0
10515   TEST_IF_MARKING .Lop_iget_wide_read_barrier
10516   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10517   .else
10518   ldar w0, [x3]
10519
10520   SET_VREG w0, w2                     // fp[A] <- value
10521   .endif
10522   FETCH_ADVANCE_INST 2
10523   GET_INST_OPCODE ip
10524   GOTO_OPCODE ip
10525
10526    NAME_END nterp_op_iget_wide_slow_path
10527    NAME_START nterp_op_instance_of_slow_path
10528   // Go slow path if we are marking. Checking now allows
10529   // not going to slow path if the super class hierarchy check fails.
10530   TEST_IF_MARKING 4f
10531   ldr     w3, [x1, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET]
10532   tbnz    w3, #MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, 5f
10533   ldr     w3, [x1, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET]
10534   UNPOISON_HEAP_REF w3
10535   cbnz    w3, 3f
105361:
10537   ldr     w2, [x2, #MIRROR_CLASS_SUPER_CLASS_OFFSET]
10538   UNPOISON_HEAP_REF w2
10539   cmp     w1, w2
10540   beq     .Lop_instance_of_set_one
10541   cbnz    w2, 1b
105422:
10543   mov     w0, #0
10544   b       .Lop_instance_of_resume
105453:
10546   // Class in x1 is an array, x3 is the component type of x1, and x2 is the class of the object.
10547   ldr     w2, [x2, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET]
10548   UNPOISON_HEAP_REF w2
10549   // Check if object is an array.
10550   cbz     w2, 2b
10551   // Check of x1 is Object[]
10552   ldr     w4, [x3, #MIRROR_CLASS_SUPER_CLASS_OFFSET]
10553   UNPOISON_HEAP_REF w4
10554   // If the super class is not Object, go to slow path.
10555   cbnz    w4, 5f
10556   // Super class is null, this could either be a primitive array or Object[].
10557   ldrh    w3, [x3, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET]
10558   // If x1 is a primitive array class, we know the check is false.
10559   cbnz    w3, 2b
10560   // Check if x2 is a primitive array class.
10561   ldrh    w2, [x2, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET]
10562   cmp     w2, #0
10563   cset    w0, eq
10564   b       .Lop_instance_of_resume
105654:
10566   bl      art_quick_read_barrier_mark_reg01
105675:
10568   EXPORT_PC
10569   bl      artInstanceOfFromCode
10570   b       .Lop_instance_of_resume
10571
10572    NAME_END nterp_op_instance_of_slow_path
10573    NAME_START nterp_op_invoke_interface_range_slow_path
10574   mov x0, xSELF
10575   ldr x1, [sp]
10576   mov x2, xPC
10577   bl nterp_get_method
10578   mov x26, x0
10579   b .Lop_invoke_interface_range_resume
10580
10581    NAME_END nterp_op_invoke_interface_range_slow_path
10582    NAME_START nterp_op_invoke_interface_slow_path
10583   mov x0, xSELF
10584   ldr x1, [sp]
10585   mov x2, xPC
10586   bl nterp_get_method
10587   mov x26, x0
10588   b .Lop_invoke_interface_resume
10589
10590    NAME_END nterp_op_invoke_interface_slow_path
10591    NAME_START nterp_op_iput_boolean_slow_path
10592   mov     x0, xSELF
10593   ldr     x1, [sp]
10594   mov     x2, xPC
10595   .if 0
10596   mov     x3, x26
10597   .else
10598   mov     x3, #0
10599   .endif
10600   EXPORT_PC
10601   bl      nterp_get_instance_field_offset
10602   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10603   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10604   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10605   mov     w0, w0
10606   .if 0
10607   // Reload the value as it may have moved.
10608   ubfx    w1, wINST, #8, #4           // w1<- A
10609   GET_VREG w26, w1                    // w26 <- v[A]
10610   .endif
10611   tbz     w0, #31, .Lop_iput_boolean_resume
10612   CLEAR_INSTANCE_VOLATILE_MARKER w0
10613   lsr     w2, wINST, #12              // w2<- B
10614   GET_VREG w2, w2                     // vB (object we're operating on)
10615   cbz     w2, common_errNullObject
10616   add     x3, x2, x0
10617   .if 0
10618   stlrb x26, [x3]
10619   .else
10620   POISON_HEAP_REF_IF_OBJECT 0, w26
10621   stlrb w26, [x3]
10622   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_boolean_slow_path_skip_write_barrier
10623   .endif
10624   FETCH_ADVANCE_INST 2
10625   GET_INST_OPCODE ip
10626   GOTO_OPCODE ip
10627
10628    NAME_END nterp_op_iput_boolean_slow_path
10629    NAME_START nterp_op_iput_byte_slow_path
10630   mov     x0, xSELF
10631   ldr     x1, [sp]
10632   mov     x2, xPC
10633   .if 0
10634   mov     x3, x26
10635   .else
10636   mov     x3, #0
10637   .endif
10638   EXPORT_PC
10639   bl      nterp_get_instance_field_offset
10640   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10641   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10642   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10643   mov     w0, w0
10644   .if 0
10645   // Reload the value as it may have moved.
10646   ubfx    w1, wINST, #8, #4           // w1<- A
10647   GET_VREG w26, w1                    // w26 <- v[A]
10648   .endif
10649   tbz     w0, #31, .Lop_iput_byte_resume
10650   CLEAR_INSTANCE_VOLATILE_MARKER w0
10651   lsr     w2, wINST, #12              // w2<- B
10652   GET_VREG w2, w2                     // vB (object we're operating on)
10653   cbz     w2, common_errNullObject
10654   add     x3, x2, x0
10655   .if 0
10656   stlrb x26, [x3]
10657   .else
10658   POISON_HEAP_REF_IF_OBJECT 0, w26
10659   stlrb w26, [x3]
10660   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_byte_slow_path_skip_write_barrier
10661   .endif
10662   FETCH_ADVANCE_INST 2
10663   GET_INST_OPCODE ip
10664   GOTO_OPCODE ip
10665
10666    NAME_END nterp_op_iput_byte_slow_path
10667    NAME_START nterp_op_iput_char_slow_path
10668   mov     x0, xSELF
10669   ldr     x1, [sp]
10670   mov     x2, xPC
10671   .if 0
10672   mov     x3, x26
10673   .else
10674   mov     x3, #0
10675   .endif
10676   EXPORT_PC
10677   bl      nterp_get_instance_field_offset
10678   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10679   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10680   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10681   mov     w0, w0
10682   .if 0
10683   // Reload the value as it may have moved.
10684   ubfx    w1, wINST, #8, #4           // w1<- A
10685   GET_VREG w26, w1                    // w26 <- v[A]
10686   .endif
10687   tbz     w0, #31, .Lop_iput_char_resume
10688   CLEAR_INSTANCE_VOLATILE_MARKER w0
10689   lsr     w2, wINST, #12              // w2<- B
10690   GET_VREG w2, w2                     // vB (object we're operating on)
10691   cbz     w2, common_errNullObject
10692   add     x3, x2, x0
10693   .if 0
10694   stlrh x26, [x3]
10695   .else
10696   POISON_HEAP_REF_IF_OBJECT 0, w26
10697   stlrh w26, [x3]
10698   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_char_slow_path_skip_write_barrier
10699   .endif
10700   FETCH_ADVANCE_INST 2
10701   GET_INST_OPCODE ip
10702   GOTO_OPCODE ip
10703
10704    NAME_END nterp_op_iput_char_slow_path
10705    NAME_START nterp_op_iput_object_slow_path
10706   mov     x0, xSELF
10707   ldr     x1, [sp]
10708   mov     x2, xPC
10709   .if 1
10710   mov     x3, x26
10711   .else
10712   mov     x3, #0
10713   .endif
10714   EXPORT_PC
10715   bl      nterp_get_instance_field_offset
10716   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10717   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10718   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10719   mov     w0, w0
10720   .if 1
10721   // Reload the value as it may have moved.
10722   ubfx    w1, wINST, #8, #4           // w1<- A
10723   GET_VREG w26, w1                    // w26 <- v[A]
10724   .endif
10725   tbz     w0, #31, .Lop_iput_object_resume
10726   CLEAR_INSTANCE_VOLATILE_MARKER w0
10727   lsr     w2, wINST, #12              // w2<- B
10728   GET_VREG w2, w2                     // vB (object we're operating on)
10729   cbz     w2, common_errNullObject
10730   add     x3, x2, x0
10731   .if 0
10732   stlr x26, [x3]
10733   .else
10734   POISON_HEAP_REF_IF_OBJECT 1, w26
10735   stlr w26, [x3]
10736   WRITE_BARRIER_IF_OBJECT 1, w26, w2, .Lop_iput_object_slow_path_skip_write_barrier
10737   .endif
10738   FETCH_ADVANCE_INST 2
10739   GET_INST_OPCODE ip
10740   GOTO_OPCODE ip
10741
10742    NAME_END nterp_op_iput_object_slow_path
10743    NAME_START nterp_op_iput_short_slow_path
10744   mov     x0, xSELF
10745   ldr     x1, [sp]
10746   mov     x2, xPC
10747   .if 0
10748   mov     x3, x26
10749   .else
10750   mov     x3, #0
10751   .endif
10752   EXPORT_PC
10753   bl      nterp_get_instance_field_offset
10754   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10755   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10756   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10757   mov     w0, w0
10758   .if 0
10759   // Reload the value as it may have moved.
10760   ubfx    w1, wINST, #8, #4           // w1<- A
10761   GET_VREG w26, w1                    // w26 <- v[A]
10762   .endif
10763   tbz     w0, #31, .Lop_iput_short_resume
10764   CLEAR_INSTANCE_VOLATILE_MARKER w0
10765   lsr     w2, wINST, #12              // w2<- B
10766   GET_VREG w2, w2                     // vB (object we're operating on)
10767   cbz     w2, common_errNullObject
10768   add     x3, x2, x0
10769   .if 0
10770   stlrh x26, [x3]
10771   .else
10772   POISON_HEAP_REF_IF_OBJECT 0, w26
10773   stlrh w26, [x3]
10774   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_short_slow_path_skip_write_barrier
10775   .endif
10776   FETCH_ADVANCE_INST 2
10777   GET_INST_OPCODE ip
10778   GOTO_OPCODE ip
10779
10780    NAME_END nterp_op_iput_short_slow_path
10781    NAME_START nterp_op_iput_slow_path
10782   mov     x0, xSELF
10783   ldr     x1, [sp]
10784   mov     x2, xPC
10785   .if 0
10786   mov     x3, x26
10787   .else
10788   mov     x3, #0
10789   .endif
10790   EXPORT_PC
10791   bl      nterp_get_instance_field_offset
10792   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10793   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10794   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10795   mov     w0, w0
10796   .if 0
10797   // Reload the value as it may have moved.
10798   ubfx    w1, wINST, #8, #4           // w1<- A
10799   GET_VREG w26, w1                    // w26 <- v[A]
10800   .endif
10801   tbz     w0, #31, .Lop_iput_resume
10802   CLEAR_INSTANCE_VOLATILE_MARKER w0
10803   lsr     w2, wINST, #12              // w2<- B
10804   GET_VREG w2, w2                     // vB (object we're operating on)
10805   cbz     w2, common_errNullObject
10806   add     x3, x2, x0
10807   .if 0
10808   stlr x26, [x3]
10809   .else
10810   POISON_HEAP_REF_IF_OBJECT 0, w26
10811   stlr w26, [x3]
10812   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_slow_path_skip_write_barrier
10813   .endif
10814   FETCH_ADVANCE_INST 2
10815   GET_INST_OPCODE ip
10816   GOTO_OPCODE ip
10817
10818    NAME_END nterp_op_iput_slow_path
10819    NAME_START nterp_op_iput_wide_slow_path
10820   mov     x0, xSELF
10821   ldr     x1, [sp]
10822   mov     x2, xPC
10823   .if 0
10824   mov     x3, x26
10825   .else
10826   mov     x3, #0
10827   .endif
10828   EXPORT_PC
10829   bl      nterp_get_instance_field_offset
10830   // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is
10831   // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that
10832   // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9).
10833   mov     w0, w0
10834   .if 0
10835   // Reload the value as it may have moved.
10836   ubfx    w1, wINST, #8, #4           // w1<- A
10837   GET_VREG w26, w1                    // w26 <- v[A]
10838   .endif
10839   tbz     w0, #31, .Lop_iput_wide_resume
10840   CLEAR_INSTANCE_VOLATILE_MARKER w0
10841   lsr     w2, wINST, #12              // w2<- B
10842   GET_VREG w2, w2                     // vB (object we're operating on)
10843   cbz     w2, common_errNullObject
10844   add     x3, x2, x0
10845   .if 1
10846   stlr x26, [x3]
10847   .else
10848   POISON_HEAP_REF_IF_OBJECT 0, w26
10849   stlr w26, [x3]
10850   WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_wide_slow_path_skip_write_barrier
10851   .endif
10852   FETCH_ADVANCE_INST 2
10853   GET_INST_OPCODE ip
10854   GOTO_OPCODE ip
10855
10856    NAME_END nterp_op_iput_wide_slow_path
10857    NAME_START nterp_op_sget_boolean_slow_path
10858   mov     x0, xSELF
10859   ldr     x1, [sp]
10860   mov     x2, xPC
10861   mov     x3, #0
10862   EXPORT_PC
10863   bl      nterp_get_static_field
10864   tbz     x0, #0, .Lop_sget_boolean_resume
10865   CLEAR_STATIC_VOLATILE_MARKER x0
10866   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
10867   lsr     w2, wINST, #8               // w2 <- A
10868   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
10869   TEST_IF_MARKING .Lop_sget_boolean_slow_path_read_barrier
10870.Lop_sget_boolean_slow_path_resume_after_read_barrier:
10871   add     x0, x0, x1
10872   .if 0
10873   ldar    x0, [x0]
10874   SET_VREG_WIDE x0, w2                // fp[A] <- value
10875   .elseif 0
10876   ldarb w0, [x0]
10877   UNPOISON_HEAP_REF w0
10878   TEST_IF_MARKING .Lop_sget_boolean_mark_after_load
10879   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10880   .else
10881   ldarb w0, [x0]
10882
10883   SET_VREG w0, w2                     // fp[A] <- value
10884   .endif
10885   FETCH_ADVANCE_INST 2
10886   GET_INST_OPCODE ip
10887   GOTO_OPCODE ip
10888.Lop_sget_boolean_slow_path_read_barrier:
10889   bl      art_quick_read_barrier_mark_reg00
10890   b       .Lop_sget_boolean_slow_path_resume_after_read_barrier
10891
10892    NAME_END nterp_op_sget_boolean_slow_path
10893    NAME_START nterp_op_sget_byte_slow_path
10894   mov     x0, xSELF
10895   ldr     x1, [sp]
10896   mov     x2, xPC
10897   mov     x3, #0
10898   EXPORT_PC
10899   bl      nterp_get_static_field
10900   tbz     x0, #0, .Lop_sget_byte_resume
10901   CLEAR_STATIC_VOLATILE_MARKER x0
10902   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
10903   lsr     w2, wINST, #8               // w2 <- A
10904   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
10905   TEST_IF_MARKING .Lop_sget_byte_slow_path_read_barrier
10906.Lop_sget_byte_slow_path_resume_after_read_barrier:
10907   add     x0, x0, x1
10908   .if 0
10909   ldar    x0, [x0]
10910   SET_VREG_WIDE x0, w2                // fp[A] <- value
10911   .elseif 0
10912   ldarb w0, [x0]
10913   UNPOISON_HEAP_REF w0
10914   TEST_IF_MARKING .Lop_sget_byte_mark_after_load
10915   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10916   .else
10917   ldarb w0, [x0]
10918   sxtb w0, w0
10919   SET_VREG w0, w2                     // fp[A] <- value
10920   .endif
10921   FETCH_ADVANCE_INST 2
10922   GET_INST_OPCODE ip
10923   GOTO_OPCODE ip
10924.Lop_sget_byte_slow_path_read_barrier:
10925   bl      art_quick_read_barrier_mark_reg00
10926   b       .Lop_sget_byte_slow_path_resume_after_read_barrier
10927
10928    NAME_END nterp_op_sget_byte_slow_path
10929    NAME_START nterp_op_sget_char_slow_path
10930   mov     x0, xSELF
10931   ldr     x1, [sp]
10932   mov     x2, xPC
10933   mov     x3, #0
10934   EXPORT_PC
10935   bl      nterp_get_static_field
10936   tbz     x0, #0, .Lop_sget_char_resume
10937   CLEAR_STATIC_VOLATILE_MARKER x0
10938   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
10939   lsr     w2, wINST, #8               // w2 <- A
10940   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
10941   TEST_IF_MARKING .Lop_sget_char_slow_path_read_barrier
10942.Lop_sget_char_slow_path_resume_after_read_barrier:
10943   add     x0, x0, x1
10944   .if 0
10945   ldar    x0, [x0]
10946   SET_VREG_WIDE x0, w2                // fp[A] <- value
10947   .elseif 0
10948   ldarh w0, [x0]
10949   UNPOISON_HEAP_REF w0
10950   TEST_IF_MARKING .Lop_sget_char_mark_after_load
10951   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10952   .else
10953   ldarh w0, [x0]
10954
10955   SET_VREG w0, w2                     // fp[A] <- value
10956   .endif
10957   FETCH_ADVANCE_INST 2
10958   GET_INST_OPCODE ip
10959   GOTO_OPCODE ip
10960.Lop_sget_char_slow_path_read_barrier:
10961   bl      art_quick_read_barrier_mark_reg00
10962   b       .Lop_sget_char_slow_path_resume_after_read_barrier
10963
10964    NAME_END nterp_op_sget_char_slow_path
10965    NAME_START nterp_op_sget_object_slow_path
10966   mov     x0, xSELF
10967   ldr     x1, [sp]
10968   mov     x2, xPC
10969   mov     x3, #0
10970   EXPORT_PC
10971   bl      nterp_get_static_field
10972   tbz     x0, #0, .Lop_sget_object_resume
10973   CLEAR_STATIC_VOLATILE_MARKER x0
10974   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
10975   lsr     w2, wINST, #8               // w2 <- A
10976   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
10977   TEST_IF_MARKING .Lop_sget_object_slow_path_read_barrier
10978.Lop_sget_object_slow_path_resume_after_read_barrier:
10979   add     x0, x0, x1
10980   .if 0
10981   ldar    x0, [x0]
10982   SET_VREG_WIDE x0, w2                // fp[A] <- value
10983   .elseif 1
10984   ldar w0, [x0]
10985   UNPOISON_HEAP_REF w0
10986   TEST_IF_MARKING .Lop_sget_object_mark_after_load
10987   SET_VREG_OBJECT w0, w2              // fp[A] <- value
10988   .else
10989   ldar w0, [x0]
10990
10991   SET_VREG w0, w2                     // fp[A] <- value
10992   .endif
10993   FETCH_ADVANCE_INST 2
10994   GET_INST_OPCODE ip
10995   GOTO_OPCODE ip
10996.Lop_sget_object_slow_path_read_barrier:
10997   bl      art_quick_read_barrier_mark_reg00
10998   b       .Lop_sget_object_slow_path_resume_after_read_barrier
10999
11000    NAME_END nterp_op_sget_object_slow_path
11001    NAME_START nterp_op_sget_short_slow_path
11002   mov     x0, xSELF
11003   ldr     x1, [sp]
11004   mov     x2, xPC
11005   mov     x3, #0
11006   EXPORT_PC
11007   bl      nterp_get_static_field
11008   tbz     x0, #0, .Lop_sget_short_resume
11009   CLEAR_STATIC_VOLATILE_MARKER x0
11010   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11011   lsr     w2, wINST, #8               // w2 <- A
11012   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11013   TEST_IF_MARKING .Lop_sget_short_slow_path_read_barrier
11014.Lop_sget_short_slow_path_resume_after_read_barrier:
11015   add     x0, x0, x1
11016   .if 0
11017   ldar    x0, [x0]
11018   SET_VREG_WIDE x0, w2                // fp[A] <- value
11019   .elseif 0
11020   ldarh w0, [x0]
11021   UNPOISON_HEAP_REF w0
11022   TEST_IF_MARKING .Lop_sget_short_mark_after_load
11023   SET_VREG_OBJECT w0, w2              // fp[A] <- value
11024   .else
11025   ldarh w0, [x0]
11026   sxth w0, w0
11027   SET_VREG w0, w2                     // fp[A] <- value
11028   .endif
11029   FETCH_ADVANCE_INST 2
11030   GET_INST_OPCODE ip
11031   GOTO_OPCODE ip
11032.Lop_sget_short_slow_path_read_barrier:
11033   bl      art_quick_read_barrier_mark_reg00
11034   b       .Lop_sget_short_slow_path_resume_after_read_barrier
11035
11036    NAME_END nterp_op_sget_short_slow_path
11037    NAME_START nterp_op_sget_slow_path
11038   mov     x0, xSELF
11039   ldr     x1, [sp]
11040   mov     x2, xPC
11041   mov     x3, #0
11042   EXPORT_PC
11043   bl      nterp_get_static_field
11044   tbz     x0, #0, .Lop_sget_resume
11045   CLEAR_STATIC_VOLATILE_MARKER x0
11046   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11047   lsr     w2, wINST, #8               // w2 <- A
11048   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11049   TEST_IF_MARKING .Lop_sget_slow_path_read_barrier
11050.Lop_sget_slow_path_resume_after_read_barrier:
11051   add     x0, x0, x1
11052   .if 0
11053   ldar    x0, [x0]
11054   SET_VREG_WIDE x0, w2                // fp[A] <- value
11055   .elseif 0
11056   ldar w0, [x0]
11057   UNPOISON_HEAP_REF w0
11058   TEST_IF_MARKING .Lop_sget_mark_after_load
11059   SET_VREG_OBJECT w0, w2              // fp[A] <- value
11060   .else
11061   ldar w0, [x0]
11062
11063   SET_VREG w0, w2                     // fp[A] <- value
11064   .endif
11065   FETCH_ADVANCE_INST 2
11066   GET_INST_OPCODE ip
11067   GOTO_OPCODE ip
11068.Lop_sget_slow_path_read_barrier:
11069   bl      art_quick_read_barrier_mark_reg00
11070   b       .Lop_sget_slow_path_resume_after_read_barrier
11071
11072    NAME_END nterp_op_sget_slow_path
11073    NAME_START nterp_op_sget_wide_slow_path
11074   mov     x0, xSELF
11075   ldr     x1, [sp]
11076   mov     x2, xPC
11077   mov     x3, #0
11078   EXPORT_PC
11079   bl      nterp_get_static_field
11080   tbz     x0, #0, .Lop_sget_wide_resume
11081   CLEAR_STATIC_VOLATILE_MARKER x0
11082   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11083   lsr     w2, wINST, #8               // w2 <- A
11084   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11085   TEST_IF_MARKING .Lop_sget_wide_slow_path_read_barrier
11086.Lop_sget_wide_slow_path_resume_after_read_barrier:
11087   add     x0, x0, x1
11088   .if 1
11089   ldar    x0, [x0]
11090   SET_VREG_WIDE x0, w2                // fp[A] <- value
11091   .elseif 0
11092   ldar w0, [x0]
11093   UNPOISON_HEAP_REF w0
11094   TEST_IF_MARKING .Lop_sget_wide_mark_after_load
11095   SET_VREG_OBJECT w0, w2              // fp[A] <- value
11096   .else
11097   ldar w0, [x0]
11098
11099   SET_VREG w0, w2                     // fp[A] <- value
11100   .endif
11101   FETCH_ADVANCE_INST 2
11102   GET_INST_OPCODE ip
11103   GOTO_OPCODE ip
11104.Lop_sget_wide_slow_path_read_barrier:
11105   bl      art_quick_read_barrier_mark_reg00
11106   b       .Lop_sget_wide_slow_path_resume_after_read_barrier
11107
11108    NAME_END nterp_op_sget_wide_slow_path
11109    NAME_START nterp_op_sput_boolean_slow_path
11110   mov     x0, xSELF
11111   ldr     x1, [sp]
11112   mov     x2, xPC
11113   .if 0
11114   mov     x3, x26
11115   .else
11116   mov     x3, #0
11117   .endif
11118   EXPORT_PC
11119   bl      nterp_get_static_field
11120   .if 0
11121   // Reload the value as it may have moved.
11122   lsr     w2, wINST, #8               // w2 <- A
11123   GET_VREG w26, w2                    // w26 <- v[A]
11124   .endif
11125   tbz     x0, #0, .Lop_sput_boolean_resume
11126   CLEAR_STATIC_VOLATILE_MARKER x0
11127   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11128   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11129   TEST_IF_MARKING .Lop_sput_boolean_slow_path_read_barrier
11130.Lop_sput_boolean_slow_path_resume_after_read_barrier:
11131   add     x1, x0, x1
11132   .if 0
11133   stlrb    x26, [x1]
11134   .else
11135   POISON_HEAP_REF_IF_OBJECT 0, w26
11136   stlrb    w26, [x1]
11137   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_boolean_slow_path_skip_write_barrier
11138   .endif
11139   FETCH_ADVANCE_INST 2
11140   GET_INST_OPCODE ip
11141   GOTO_OPCODE ip
11142.Lop_sput_boolean_slow_path_read_barrier:
11143   bl      art_quick_read_barrier_mark_reg00
11144   b       .Lop_sput_boolean_slow_path_resume_after_read_barrier
11145
11146    NAME_END nterp_op_sput_boolean_slow_path
11147    NAME_START nterp_op_sput_byte_slow_path
11148   mov     x0, xSELF
11149   ldr     x1, [sp]
11150   mov     x2, xPC
11151   .if 0
11152   mov     x3, x26
11153   .else
11154   mov     x3, #0
11155   .endif
11156   EXPORT_PC
11157   bl      nterp_get_static_field
11158   .if 0
11159   // Reload the value as it may have moved.
11160   lsr     w2, wINST, #8               // w2 <- A
11161   GET_VREG w26, w2                    // w26 <- v[A]
11162   .endif
11163   tbz     x0, #0, .Lop_sput_byte_resume
11164   CLEAR_STATIC_VOLATILE_MARKER x0
11165   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11166   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11167   TEST_IF_MARKING .Lop_sput_byte_slow_path_read_barrier
11168.Lop_sput_byte_slow_path_resume_after_read_barrier:
11169   add     x1, x0, x1
11170   .if 0
11171   stlrb    x26, [x1]
11172   .else
11173   POISON_HEAP_REF_IF_OBJECT 0, w26
11174   stlrb    w26, [x1]
11175   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_byte_slow_path_skip_write_barrier
11176   .endif
11177   FETCH_ADVANCE_INST 2
11178   GET_INST_OPCODE ip
11179   GOTO_OPCODE ip
11180.Lop_sput_byte_slow_path_read_barrier:
11181   bl      art_quick_read_barrier_mark_reg00
11182   b       .Lop_sput_byte_slow_path_resume_after_read_barrier
11183
11184    NAME_END nterp_op_sput_byte_slow_path
11185    NAME_START nterp_op_sput_char_slow_path
11186   mov     x0, xSELF
11187   ldr     x1, [sp]
11188   mov     x2, xPC
11189   .if 0
11190   mov     x3, x26
11191   .else
11192   mov     x3, #0
11193   .endif
11194   EXPORT_PC
11195   bl      nterp_get_static_field
11196   .if 0
11197   // Reload the value as it may have moved.
11198   lsr     w2, wINST, #8               // w2 <- A
11199   GET_VREG w26, w2                    // w26 <- v[A]
11200   .endif
11201   tbz     x0, #0, .Lop_sput_char_resume
11202   CLEAR_STATIC_VOLATILE_MARKER x0
11203   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11204   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11205   TEST_IF_MARKING .Lop_sput_char_slow_path_read_barrier
11206.Lop_sput_char_slow_path_resume_after_read_barrier:
11207   add     x1, x0, x1
11208   .if 0
11209   stlrh    x26, [x1]
11210   .else
11211   POISON_HEAP_REF_IF_OBJECT 0, w26
11212   stlrh    w26, [x1]
11213   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_char_slow_path_skip_write_barrier
11214   .endif
11215   FETCH_ADVANCE_INST 2
11216   GET_INST_OPCODE ip
11217   GOTO_OPCODE ip
11218.Lop_sput_char_slow_path_read_barrier:
11219   bl      art_quick_read_barrier_mark_reg00
11220   b       .Lop_sput_char_slow_path_resume_after_read_barrier
11221
11222    NAME_END nterp_op_sput_char_slow_path
11223    NAME_START nterp_op_sput_object_slow_path
11224   mov     x0, xSELF
11225   ldr     x1, [sp]
11226   mov     x2, xPC
11227   .if 1
11228   mov     x3, x26
11229   .else
11230   mov     x3, #0
11231   .endif
11232   EXPORT_PC
11233   bl      nterp_get_static_field
11234   .if 1
11235   // Reload the value as it may have moved.
11236   lsr     w2, wINST, #8               // w2 <- A
11237   GET_VREG w26, w2                    // w26 <- v[A]
11238   .endif
11239   tbz     x0, #0, .Lop_sput_object_resume
11240   CLEAR_STATIC_VOLATILE_MARKER x0
11241   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11242   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11243   TEST_IF_MARKING .Lop_sput_object_slow_path_read_barrier
11244.Lop_sput_object_slow_path_resume_after_read_barrier:
11245   add     x1, x0, x1
11246   .if 0
11247   stlr    x26, [x1]
11248   .else
11249   POISON_HEAP_REF_IF_OBJECT 1, w26
11250   stlr    w26, [x1]
11251   WRITE_BARRIER_IF_OBJECT 1, w26, w0, .Lop_sput_object_slow_path_skip_write_barrier
11252   .endif
11253   FETCH_ADVANCE_INST 2
11254   GET_INST_OPCODE ip
11255   GOTO_OPCODE ip
11256.Lop_sput_object_slow_path_read_barrier:
11257   bl      art_quick_read_barrier_mark_reg00
11258   b       .Lop_sput_object_slow_path_resume_after_read_barrier
11259
11260    NAME_END nterp_op_sput_object_slow_path
11261    NAME_START nterp_op_sput_short_slow_path
11262   mov     x0, xSELF
11263   ldr     x1, [sp]
11264   mov     x2, xPC
11265   .if 0
11266   mov     x3, x26
11267   .else
11268   mov     x3, #0
11269   .endif
11270   EXPORT_PC
11271   bl      nterp_get_static_field
11272   .if 0
11273   // Reload the value as it may have moved.
11274   lsr     w2, wINST, #8               // w2 <- A
11275   GET_VREG w26, w2                    // w26 <- v[A]
11276   .endif
11277   tbz     x0, #0, .Lop_sput_short_resume
11278   CLEAR_STATIC_VOLATILE_MARKER x0
11279   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11280   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11281   TEST_IF_MARKING .Lop_sput_short_slow_path_read_barrier
11282.Lop_sput_short_slow_path_resume_after_read_barrier:
11283   add     x1, x0, x1
11284   .if 0
11285   stlrh    x26, [x1]
11286   .else
11287   POISON_HEAP_REF_IF_OBJECT 0, w26
11288   stlrh    w26, [x1]
11289   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_short_slow_path_skip_write_barrier
11290   .endif
11291   FETCH_ADVANCE_INST 2
11292   GET_INST_OPCODE ip
11293   GOTO_OPCODE ip
11294.Lop_sput_short_slow_path_read_barrier:
11295   bl      art_quick_read_barrier_mark_reg00
11296   b       .Lop_sput_short_slow_path_resume_after_read_barrier
11297
11298    NAME_END nterp_op_sput_short_slow_path
11299    NAME_START nterp_op_sput_slow_path
11300   mov     x0, xSELF
11301   ldr     x1, [sp]
11302   mov     x2, xPC
11303   .if 0
11304   mov     x3, x26
11305   .else
11306   mov     x3, #0
11307   .endif
11308   EXPORT_PC
11309   bl      nterp_get_static_field
11310   .if 0
11311   // Reload the value as it may have moved.
11312   lsr     w2, wINST, #8               // w2 <- A
11313   GET_VREG w26, w2                    // w26 <- v[A]
11314   .endif
11315   tbz     x0, #0, .Lop_sput_resume
11316   CLEAR_STATIC_VOLATILE_MARKER x0
11317   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11318   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11319   TEST_IF_MARKING .Lop_sput_slow_path_read_barrier
11320.Lop_sput_slow_path_resume_after_read_barrier:
11321   add     x1, x0, x1
11322   .if 0
11323   stlr    x26, [x1]
11324   .else
11325   POISON_HEAP_REF_IF_OBJECT 0, w26
11326   stlr    w26, [x1]
11327   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_slow_path_skip_write_barrier
11328   .endif
11329   FETCH_ADVANCE_INST 2
11330   GET_INST_OPCODE ip
11331   GOTO_OPCODE ip
11332.Lop_sput_slow_path_read_barrier:
11333   bl      art_quick_read_barrier_mark_reg00
11334   b       .Lop_sput_slow_path_resume_after_read_barrier
11335
11336    NAME_END nterp_op_sput_slow_path
11337    NAME_START nterp_op_sput_wide_slow_path
11338   mov     x0, xSELF
11339   ldr     x1, [sp]
11340   mov     x2, xPC
11341   .if 0
11342   mov     x3, x26
11343   .else
11344   mov     x3, #0
11345   .endif
11346   EXPORT_PC
11347   bl      nterp_get_static_field
11348   .if 0
11349   // Reload the value as it may have moved.
11350   lsr     w2, wINST, #8               // w2 <- A
11351   GET_VREG w26, w2                    // w26 <- v[A]
11352   .endif
11353   tbz     x0, #0, .Lop_sput_wide_resume
11354   CLEAR_STATIC_VOLATILE_MARKER x0
11355   ldr     w1, [x0, #ART_FIELD_OFFSET_OFFSET]
11356   ldr     w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET]
11357   TEST_IF_MARKING .Lop_sput_wide_slow_path_read_barrier
11358.Lop_sput_wide_slow_path_resume_after_read_barrier:
11359   add     x1, x0, x1
11360   .if 1
11361   stlr    x26, [x1]
11362   .else
11363   POISON_HEAP_REF_IF_OBJECT 0, w26
11364   stlr    w26, [x1]
11365   WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_wide_slow_path_skip_write_barrier
11366   .endif
11367   FETCH_ADVANCE_INST 2
11368   GET_INST_OPCODE ip
11369   GOTO_OPCODE ip
11370.Lop_sput_wide_slow_path_read_barrier:
11371   bl      art_quick_read_barrier_mark_reg00
11372   b       .Lop_sput_wide_slow_path_resume_after_read_barrier
11373
11374    NAME_END nterp_op_sput_wide_slow_path
11375/*
11376 * ===========================================================================
11377 *  Common subroutines and data
11378 * ===========================================================================
11379 */
11380
11381    .text
11382    .align  2
11383
11384// Enclose all code below in a symbol (which gets printed in backtraces).
11385NAME_START nterp_helper
11386
11387// Note: mterp also uses the common_* names below for helpers, but that's OK
11388// as the assembler compiled each interpreter separately.
11389common_errDivideByZero:
11390    EXPORT_PC
11391    bl art_quick_throw_div_zero
11392
11393// Expect index in w1, length in w3.
11394common_errArrayIndex:
11395    EXPORT_PC
11396    mov x0, x1
11397    mov x1, x3
11398    bl art_quick_throw_array_bounds
11399
11400common_errNullObject:
11401    EXPORT_PC
11402    bl art_quick_throw_null_pointer_exception
11403
11404NterpCommonInvokeStatic:
11405    COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic"
11406
11407NterpCommonInvokeStaticRange:
11408    COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic"
11409
11410NterpCommonInvokeInstance:
11411    COMMON_INVOKE_NON_RANGE suffix="invokeInstance"
11412
11413NterpCommonInvokeInstanceRange:
11414    COMMON_INVOKE_RANGE suffix="invokeInstance"
11415
11416NterpCommonInvokeInterface:
11417    COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface"
11418
11419NterpCommonInvokeInterfaceRange:
11420    COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface"
11421
11422NterpCommonInvokePolymorphic:
11423    COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic"
11424
11425NterpCommonInvokePolymorphicRange:
11426    COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic"
11427
11428NterpCommonInvokeCustom:
11429    COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
11430
11431NterpCommonInvokeCustomRange:
11432    COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom"
11433
11434NterpHandleStringInit:
11435   COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit"
11436
11437NterpHandleStringInitRange:
11438   COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit"
11439
11440NterpHandleHotnessOverflow:
11441    CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=1f, if_not_hot=5f
114421:
11443    mov x1, xPC
11444    mov x2, xFP
11445    bl nterp_hot_method
11446    cbnz x0, 3f
114472:
11448    FETCH wINST, 0                      // load wINST
11449    GET_INST_OPCODE ip                  // extract opcode from wINST
11450    GOTO_OPCODE ip                      // jump to next instruction
114513:
11452    // Drop the current frame.
11453    ldr ip, [xREFS, #-8]
11454    mov sp, ip
11455    .cfi_def_cfa sp, CALLEE_SAVES_SIZE
11456
11457    // The transition frame of type SaveAllCalleeSaves saves x19 and x20,
11458    // but not managed ABI. So we need to restore callee-saves of the nterp frame,
11459    // and save managed ABI callee saves, which will be restored by the callee upon
11460    // return.
11461    RESTORE_ALL_CALLEE_SAVES
11462    INCREASE_FRAME ((CALLEE_SAVES_SIZE) - 16)
11463
11464    // FP callee-saves
11465    stp d8, d9, [sp, #0]
11466    stp d10, d11, [sp, #16]
11467    stp d12, d13, [sp, #32]
11468    stp d14, d15, [sp, #48]
11469
11470    // GP callee-saves.
11471    SAVE_TWO_REGS x21, x22, 64
11472    SAVE_TWO_REGS x23, x24, 80
11473    SAVE_TWO_REGS x25, x26, 96
11474    SAVE_TWO_REGS x27, x28, 112
11475    SAVE_TWO_REGS x29, lr, 128
11476
11477    // Setup the new frame
11478    ldr x1, [x0, #OSR_DATA_FRAME_SIZE]
11479    // Given stack size contains all callee saved registers, remove them.
11480    sub x1, x1, #(CALLEE_SAVES_SIZE - 16)
11481
11482    // We know x1 cannot be 0, as it at least contains the ArtMethod.
11483
11484    // Remember CFA in a callee-save register.
11485    mov xINST, sp
11486    .cfi_def_cfa_register xINST
11487
11488    sub sp, sp, x1
11489
11490    add x2, x0, #OSR_DATA_MEMORY
114914:
11492    sub x1, x1, #8
11493    ldr ip, [x2, x1]
11494    str ip, [sp, x1]
11495    cbnz x1, 4b
11496
11497    // Fetch the native PC to jump to and save it in a callee-save register.
11498    ldr xFP, [x0, #OSR_DATA_NATIVE_PC]
11499
11500    // Free the memory holding OSR Data.
11501    bl free
11502
11503    // Jump to the compiled code.
11504    br xFP
115055:
11506    DO_SUSPEND_CHECK continue_label=2b
11507    b 2b
11508
11509// This is the logical end of ExecuteNterpImpl, where the frame info applies.
11510// EndExecuteNterpImpl includes the methods below as we want the runtime to
11511// see them as part of the Nterp PCs.
11512.cfi_endproc
11513
11514nterp_to_nterp_static_non_range:
11515    .cfi_startproc
11516    SETUP_STACK_FOR_INVOKE
11517    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0
11518    .cfi_endproc
11519
11520nterp_to_nterp_string_init_non_range:
11521    .cfi_startproc
11522    SETUP_STACK_FOR_INVOKE
11523    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
11524    .cfi_endproc
11525
11526nterp_to_nterp_instance_non_range:
11527    .cfi_startproc
11528    SETUP_STACK_FOR_INVOKE
11529    SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0
11530    .cfi_endproc
11531
11532nterp_to_nterp_static_range:
11533    .cfi_startproc
11534    SETUP_STACK_FOR_INVOKE
11535    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1
11536    .cfi_endproc
11537
11538nterp_to_nterp_instance_range:
11539    .cfi_startproc
11540    SETUP_STACK_FOR_INVOKE
11541    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0
11542    .cfi_endproc
11543
11544nterp_to_nterp_string_init_range:
11545    .cfi_startproc
11546    SETUP_STACK_FOR_INVOKE
11547    SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1
11548    .cfi_endproc
11549
11550NAME_END nterp_helper
11551
11552// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter
11553// entry point.
11554    .type EndExecuteNterpImpl, #function
11555    .hidden EndExecuteNterpImpl
11556    .global EndExecuteNterpImpl
11557EndExecuteNterpImpl:
11558
11559// Entrypoints into runtime.
11560NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField
11561NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset
11562NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray
11563NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange
11564NTERP_TRAMPOLINE nterp_get_class, NterpGetClass
11565NTERP_TRAMPOLINE nterp_allocate_object, NterpAllocateObject
11566NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod
11567NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod
11568NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject
11569
11570ENTRY nterp_deliver_pending_exception
11571    DELIVER_PENDING_EXCEPTION
11572END nterp_deliver_pending_exception
11573
11574// gen_mterp.py will inline the following definitions
11575// within [ExecuteNterpImpl, EndExecuteNterpImpl).
11576