1%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET"):
2    /*
3     * Array get, 32 bits or less.  vAA <- vBB[vCC].
4     *
5     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
6     * instructions.  We use a pair of FETCH_Bs instead.
7     *
8     * for: aget, aget-boolean, aget-byte, aget-char, aget-short
9     *
10     * NOTE: assumes data offset for arrays is the same for all non-wide types.
11     * If this changes, specialize.
12     */
13    /* op vAA, vBB, vCC */
14    FETCH_B w2, 1, 0                    // w2<- BB
15    lsr     w9, wINST, #8               // w9<- AA
16    FETCH_B w3, 1, 1                    // w3<- CC
17    GET_VREG w0, w2                     // w0<- vBB (array object)
18    GET_VREG w1, w3                     // w1<- vCC (requested index)
19    cbz     x0, common_errNullObject    // bail if null array object.
20    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
21    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
22    cmp     w1, w3                      // compare unsigned index, length
23    bcs     common_errArrayIndex        // index >= length, bail
24    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
25    $load   w2, [x0, #$data_offset]     // w2<- vBB[vCC]
26    GET_INST_OPCODE ip                  // extract opcode from rINST
27    SET_VREG w2, w9                     // vAA<- w2
28    GOTO_OPCODE ip                      // jump to next instruction
29
30%def op_aget_boolean():
31%  op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET")
32
33%def op_aget_byte():
34%  op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET")
35
36%def op_aget_char():
37%  op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET")
38
39%def op_aget_object():
40    /*
41     * Array object get.  vAA <- vBB[vCC].
42     *
43     * for: aget-object
44     */
45    /* op vAA, vBB, vCC */
46    FETCH_B w2, 1, 0                    // w2<- BB
47    FETCH_B w3, 1, 1                    // w3<- CC
48    EXPORT_PC
49    GET_VREG w0, w2                     // w0<- vBB (array object)
50    GET_VREG w1, w3                     // w1<- vCC (requested index)
51    bl       artAGetObjectFromMterp     // (array, index)
52    ldr      x1, [xSELF, #THREAD_EXCEPTION_OFFSET]
53    lsr      w2, wINST, #8               // w9<- AA
54    PREFETCH_INST 2
55    cbnz     w1, MterpException
56    SET_VREG_OBJECT w0, w2
57    ADVANCE 2
58    GET_INST_OPCODE ip
59    GOTO_OPCODE ip                      // jump to next instruction
60
61%def op_aget_short():
62%  op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET")
63
64%def op_aget_wide():
65    /*
66     * Array get, 64 bits.  vAA <- vBB[vCC].
67     *
68     */
69    /* aget-wide vAA, vBB, vCC */
70    FETCH w0, 1                         // w0<- CCBB
71    lsr     w4, wINST, #8               // w4<- AA
72    and     w2, w0, #255                // w2<- BB
73    lsr     w3, w0, #8                  // w3<- CC
74    GET_VREG w0, w2                     // w0<- vBB (array object)
75    GET_VREG w1, w3                     // w1<- vCC (requested index)
76    cbz     w0, common_errNullObject        // yes, bail
77    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
78    add     x0, x0, w1, uxtw #3         // w0<- arrayObj + index*width
79    cmp     w1, w3                      // compare unsigned index, length
80    bcs     common_errArrayIndex        // index >= length, bail
81    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
82    ldr     x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]  // x2<- vBB[vCC]
83    GET_INST_OPCODE ip                  // extract opcode from wINST
84    SET_VREG_WIDE x2, w4
85    GOTO_OPCODE ip                      // jump to next instruction
86
87%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET"):
88    /*
89     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
90     *
91     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
92     * instructions.  We use a pair of FETCH_Bs instead.
93     *
94     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
95     *
96     * NOTE: this assumes data offset for arrays is the same for all non-wide types.
97     * If this changes, specialize.
98     */
99    /* op vAA, vBB, vCC */
100    FETCH_B w2, 1, 0                    // w2<- BB
101    lsr     w9, wINST, #8               // w9<- AA
102    FETCH_B w3, 1, 1                    // w3<- CC
103    GET_VREG w0, w2                     // w0<- vBB (array object)
104    GET_VREG w1, w3                     // w1<- vCC (requested index)
105    cbz     w0, common_errNullObject    // bail if null
106    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
107    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
108    cmp     w1, w3                      // compare unsigned index, length
109    bcs     common_errArrayIndex        // index >= length, bail
110    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
111    GET_VREG w2, w9                     // w2<- vAA
112    GET_INST_OPCODE ip                  // extract opcode from rINST
113    $store  w2, [x0, #$data_offset]     // vBB[vCC]<- w2
114    GOTO_OPCODE ip                      // jump to next instruction
115
116%def op_aput_boolean():
117%  op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET")
118
119%def op_aput_byte():
120%  op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET")
121
122%def op_aput_char():
123%  op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET")
124
125%def op_aput_object():
126    /*
127     * Store an object into an array.  vBB[vCC] <- vAA.
128     */
129    /* op vAA, vBB, vCC */
130    EXPORT_PC
131    add     x0, xFP, #OFF_FP_SHADOWFRAME
132    mov     x1, xPC
133    mov     w2, wINST
134    bl      MterpAputObject
135    cbz     w0, MterpPossibleException
136    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
137    GET_INST_OPCODE ip                  // extract opcode from rINST
138    GOTO_OPCODE ip                      // jump to next instruction
139
140%def op_aput_short():
141%  op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET")
142
143%def op_aput_wide():
144    /*
145     * Array put, 64 bits.  vBB[vCC] <- vAA.
146     *
147     */
148    /* aput-wide vAA, vBB, vCC */
149    FETCH w0, 1                         // w0<- CCBB
150    lsr     w4, wINST, #8               // w4<- AA
151    and     w2, w0, #255                // w2<- BB
152    lsr     w3, w0, #8                  // w3<- CC
153    GET_VREG w0, w2                     // w0<- vBB (array object)
154    GET_VREG w1, w3                     // w1<- vCC (requested index)
155    cbz     w0, common_errNullObject    // bail if null
156    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
157    add     x0, x0, w1, uxtw #3         // w0<- arrayObj + index*width
158    cmp     w1, w3                      // compare unsigned index, length
159    bcs     common_errArrayIndex        // index >= length, bail
160    GET_VREG_WIDE x1, w4
161    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
162    GET_INST_OPCODE ip                  // extract opcode from wINST
163    str     x1, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET]
164    GOTO_OPCODE ip                      // jump to next instruction
165
166%def op_array_length():
167    /*
168     * Return the length of an array.
169     */
170    lsr     w1, wINST, #12              // w1<- B
171    ubfx    w2, wINST, #8, #4           // w2<- A
172    GET_VREG w0, w1                     // w0<- vB (object ref)
173    cbz     w0, common_errNullObject    // yup, fail
174    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
175    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- array length
176    GET_INST_OPCODE ip                  // extract opcode from rINST
177    SET_VREG w3, w2                     // vB<- length
178    GOTO_OPCODE ip                      // jump to next instruction
179
180%def op_fill_array_data():
181    /* fill-array-data vAA, +BBBBBBBB */
182    EXPORT_PC
183    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
184    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
185    lsr     w3, wINST, #8               // w3<- AA
186    orr     x1, x0, x1, lsl #16         // x1<- ssssssssBBBBbbbb
187    GET_VREG w0, w3                     // w0<- vAA (array object)
188    add     x1, xPC, x1, lsl #1         // x1<- PC + ssssssssBBBBbbbb*2 (array data off.)
189    bl      MterpFillArrayData          // (obj, payload)
190    cbz     w0, MterpPossibleException      // exception?
191    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
192    GET_INST_OPCODE ip                  // extract opcode from rINST
193    GOTO_OPCODE ip                      // jump to next instruction
194
195%def op_filled_new_array(helper="MterpFilledNewArray"):
196    /*
197     * Create a new array with elements filled from registers.
198     *
199     * for: filled-new-array, filled-new-array/range
200     */
201    /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */
202    /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */
203    .extern $helper
204    EXPORT_PC
205    add     x0, xFP, #OFF_FP_SHADOWFRAME
206    mov     x1, xPC
207    mov     x2, xSELF
208    bl      $helper
209    cbz     w0, MterpPossibleException
210    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
211    GET_INST_OPCODE ip                  // extract opcode from rINST
212    GOTO_OPCODE ip                      // jump to next instruction
213
214%def op_filled_new_array_range():
215%  op_filled_new_array(helper="MterpFilledNewArrayRange")
216
217%def op_new_array():
218    /*
219     * Allocate an array of objects, specified with the array class
220     * and a count.
221     *
222     * The verifier guarantees that this is an array class, so we don't
223     * check for it here.
224     */
225    /* new-array vA, vB, class//CCCC */
226    EXPORT_PC
227    add     x0, xFP, #OFF_FP_SHADOWFRAME
228    mov     x1, xPC
229    mov     w2, wINST
230    mov     x3, xSELF
231    bl      MterpNewArray
232    cbz     w0, MterpPossibleException
233    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
234    GET_INST_OPCODE ip                  // extract opcode from rINST
235    GOTO_OPCODE ip                      // jump to next instruction
236