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