1%def op_aget(load="movl", multiplier="4", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
2/*
3 * Array get.  vAA <- vBB[vCC].
4 *
5 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
6 *
7 */
8    /* op vAA, vBB, vCC */
9    movzbl  2(rPC), %eax                    # eax <- BB
10    movzbl  3(rPC), %ecx                    # ecx <- CC
11    GET_VREG %eax, %eax                     # eax <- vBB (array object)
12    GET_VREG %ecx, %ecx                     # ecx <- vCC (requested index)
13    testl   %eax, %eax                      # null array object?
14    je      common_errNullObject            # bail if so
15    cmpl    MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
16    jae     common_errArrayIndex            # index >= length, bail.
17    .if $wide
18    movq $data_offset(%eax,%ecx,8), %xmm0
19    SET_WIDE_FP_VREG %xmm0, rINST           # vAA <- xmm0
20    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
21    .elseif $is_object
22    testb $$READ_BARRIER_TEST_VALUE, GRAY_BYTE_OFFSET(%eax)
23    $load   $data_offset(%eax,%ecx,$multiplier), %eax
24    jnz 2f
25    UNPOISON_HEAP_REF eax  // Affects flags, so we cannot unpoison before the jnz.
261:
27    SET_VREG_OBJECT %eax, rINST
28    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
292:
30    UNPOISON_HEAP_REF eax
31    // reg00 is eax
32    call art_quick_read_barrier_mark_reg00
33    jmp 1b
34    .else
35    $load   $data_offset(%eax,%ecx,$multiplier), %eax
36    SET_VREG %eax, rINST
37    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
38    .endif
39
40%def op_aget_boolean():
41%  op_aget(load="movzbl", multiplier="1", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET")
42
43%def op_aget_byte():
44%  op_aget(load="movsbl", multiplier="1", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET")
45
46%def op_aget_char():
47%  op_aget(load="movzwl", multiplier="2", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET")
48
49%def op_aget_object():
50%  op_aget(load="movl", multiplier="4", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", is_object="1")
51
52%def op_aget_short():
53%  op_aget(load="movswl", multiplier="2", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET")
54
55%def op_aget_wide():
56%  op_aget(load="", multiplier="8", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1")
57
58%def op_aput(rINST_reg="rINST", store="movl", multiplier="4", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0"):
59/*
60 * Array put.  vBB[vCC] <- vAA.
61 *
62 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
63 *
64 */
65    /* op vAA, vBB, vCC */
66    movzbl  2(rPC), %eax                     # eax <- BB
67    movzbl  3(rPC), %ecx                     # ecx <- CC
68    GET_VREG %eax, %eax                      # eax <- vBB (array object)
69    GET_VREG %ecx, %ecx                      # ecx <- vCC (requested index)
70    testl   %eax, %eax                       # null array object?
71    je      common_errNullObject             # bail if so
72    cmpl    MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
73    jae     common_errArrayIndex             # index >= length, bail.
74    .if $wide
75    GET_WIDE_FP_VREG %xmm0, rINST            # xmm0 <- vAA
76    movq    %xmm0, $data_offset(%eax,%ecx,8) # vBB[vCC] <- xmm0
77    .else
78    GET_VREG rINST, rINST
79    $store    $rINST_reg, $data_offset(%eax,%ecx,$multiplier)
80    .endif
81    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
82
83%def op_aput_boolean():
84%  op_aput(rINST_reg="rINSTbl", store="movb", multiplier="1", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET")
85
86%def op_aput_byte():
87%  op_aput(rINST_reg="rINSTbl", store="movb", multiplier="1", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET")
88
89%def op_aput_char():
90%  op_aput(rINST_reg="rINSTw", store="movw", multiplier="2", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET")
91
92%def op_aput_short():
93%  op_aput(rINST_reg="rINSTw", store="movw", multiplier="2", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET")
94
95%def op_aput_wide():
96%  op_aput(rINST_reg="", store="", multiplier="8", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1")
97
98%def op_aput_object():
99    EXPORT_PC                               # for the art_quick_aput_obj call
100    movzbl  2(rPC), %eax                    # eax <- BB
101    movzbl  3(rPC), %ecx                    # ecx <- CC
102    GET_VREG %eax, %eax                     # eax <- vBB (array object)
103    GET_VREG %ecx, %ecx                     # ecx <- vCC (requested index)
104    testl   %eax, %eax                      # null array object?
105    je      common_errNullObject            # bail if so
106    cmpl    MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
107    jae     common_errArrayIndex            # index >= length, bail.
108    GET_VREG %edx, rINST
109    call art_quick_aput_obj
110    RESTORE_IBASE                           # edx got overwritten, restore it
111    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
112
113%def op_array_length():
114/*
115 * Return the length of an array.
116 */
117    movl    rINST, %eax                     # eax <- BA
118    sarl    $$4, rINST                      # rINST <- B
119    GET_VREG %ecx, rINST                    # ecx <- vB (object ref)
120    testl   %ecx, %ecx                      # is null?
121    je      common_errNullObject
122    andb    $$0xf, %al                      # eax <- A
123    movl    MIRROR_ARRAY_LENGTH_OFFSET(%ecx), rINST
124    SET_VREG rINST, %eax
125    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
126
127%def op_fill_array_data():
128    /* fill-array-data vAA, +BBBBBBBB */
129    EXPORT_PC
130    movl    2(rPC), %ecx                    # ecx <- BBBBbbbb
131    leal    (rPC,%ecx,2), ARG0              # ARG0 <- PC + BBBBbbbb*2
132    GET_VREG ARG1, rINST                    # ARG1 <- vAA (array object)
133    call    art_quick_handle_fill_data
134    RESTORE_IBASE
135    ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
136
137%def op_filled_new_array(helper="nterp_filled_new_array"):
138/*
139 * Create a new array with elements filled from registers.
140 *
141 * for: filled-new-array, filled-new-array/range
142 */
143    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
144    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
145    EXPORT_PC
146    movl    rSELF:THREAD_SELF_OFFSET, ARG0
147    movl    (%esp), ARG1
148    movl    rFP, ARG2
149    movl    rPC, ARG3
150    call    SYMBOL($helper)
151    ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
152
153%def op_filled_new_array_range():
154%  op_filled_new_array(helper="nterp_filled_new_array_range")
155
156%def op_new_array():
157  jmp NterpNewArray
158