1%def op_aget(load="ldr", shift="2", 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    FETCH_B r2, 1, 0                    @ r2<- BB
9    mov     r4, rINST, lsr #8           @ r4<- AA
10    FETCH_B r3, 1, 1                    @ r3<- CC
11    GET_VREG r0, r2                     @ r0<- vBB (array object)
12    GET_VREG r1, r3                     @ r1<- vCC (requested index)
13    cmp     r0, #0                      @ null array object?
14    beq     common_errNullObject        @ yes, bail
15    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]    @ r3<- arrayObj->length
16    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
17    cmp     r1, r3                      @ compare unsigned index, length
18    bcs     common_errArrayIndex        @ index >= length, bail
19    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
20    .if $wide
21    CLEAR_SHADOW_PAIR r4, lr, ip        @ Zero out the shadow regs
22    ldrd    r2, [r0, #$data_offset]     @ r2/r3<- vBB[vCC]
23    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
24    GET_INST_OPCODE ip                  @ extract opcode from rINST
25    SET_VREG_WIDE_BY_ADDR r2, r3, r4    @ vAA/vAA+1<- r2/r3
26    GOTO_OPCODE ip                      @ jump to next instruction
27    .elseif $is_object
28    $load   r2, [r0, #$data_offset]     @ w2<- vBB[vCC]
29    cmp rMR, #0
30    bne 2f
311:
32    GET_INST_OPCODE ip                  @ extract opcode from rINST
33    SET_VREG_OBJECT r2, r4              @ vAA<- w2
34    GOTO_OPCODE ip                      @ jump to next instruction
352:
36    bl art_quick_read_barrier_mark_reg02
37    b 1b
38    .else
39    GET_INST_OPCODE ip                  @ extract opcode from rINST
40    $load   r2, [r0, #$data_offset]     @ r2<- vBB[vCC]
41    SET_VREG r2, r4                     @ vAA<- r2
42    GOTO_OPCODE ip                      @ jump to next instruction
43    .endif
44
45%def op_aget_boolean():
46%  op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
47
48%def op_aget_byte():
49%  op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
50
51%def op_aget_char():
52%  op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
53
54%def op_aget_object():
55%  op_aget(load="ldr", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
56
57%def op_aget_short():
58%  op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
59
60%def op_aget_wide():
61%  op_aget(load="ldrd", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
62
63%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
64/*
65 * Array put.  vBB[vCC] <- vAA.
66 *
67 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
68 *
69 */
70    FETCH_B r2, 1, 0                    @ r2<- BB
71    mov     r4, rINST, lsr #8           @ r4<- AA
72    FETCH_B r3, 1, 1                    @ r3<- CC
73    GET_VREG r0, r2                     @ r0<- vBB (array object)
74    GET_VREG r1, r3                     @ r1<- vCC (requested index)
75    cmp     r0, #0                      @ null array object?
76    beq     common_errNullObject        @ yes, bail
77    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]     @ r3<- arrayObj->length
78    cmp     r1, r3                      @ compare unsigned index, length
79    bcs     common_errArrayIndex        @ index >= length, bail
80    .if $is_object
81    EXPORT_PC                           // Export PC before overwriting it.
82    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
83    GET_VREG r2, r4                     @ r2<- vAA
84    bl art_quick_aput_obj
85    GET_INST_OPCODE ip                  @ extract opcode from rINST
86    .elseif $wide
87    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
88    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[AA]
89    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
90    GET_VREG_WIDE_BY_ADDR r2, r3, r4    @ r2/r3<- vAA/vAA+1
91    GET_INST_OPCODE ip                  @ extract opcode from rINST
92    strd    r2, [r0, #$data_offset]     @ r2/r3<- vBB[vCC]
93    .else
94    add     r0, r0, r1, lsl #$shift     @ r0<- arrayObj + index*width
95    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
96    GET_VREG r2, r4                     @ r2<- vAA
97    GET_INST_OPCODE ip                  @ extract opcode from rINST
98    $store  r2, [r0, #$data_offset]     @ vBB[vCC]<- r2
99    .endif
100    GOTO_OPCODE ip                      @ jump to next instruction
101
102%def op_aput_boolean():
103%  op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
104
105%def op_aput_byte():
106%  op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
107
108%def op_aput_char():
109%  op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
110
111%def op_aput_short():
112%  op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
113
114%def op_aput_wide():
115%  op_aput(store="str", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
116
117%def op_aput_object():
118%  op_aput(store="str", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
119
120%def op_array_length():
121    /*
122     * Return the length of an array.
123     */
124    mov     r1, rINST, lsr #12          @ r1<- B
125    ubfx    r2, rINST, #8, #4           @ r2<- A
126    GET_VREG r0, r1                     @ r0<- vB (object ref)
127    cmp     r0, #0                      @ is object null?
128    beq     common_errNullObject        @ yup, fail
129    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
130    ldr     r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET]    @ r3<- array length
131    GET_INST_OPCODE ip                  @ extract opcode from rINST
132    SET_VREG r3, r2                     @ vB<- length
133    GOTO_OPCODE ip                      @ jump to next instruction
134
135%def op_fill_array_data():
136    /* fill-array-data vAA, +BBBBBBBB */
137    EXPORT_PC
138    FETCH r0, 1                         @ r0<- bbbb (lo)
139    FETCH r1, 2                         @ r1<- BBBB (hi)
140    mov     r3, rINST, lsr #8           @ r3<- AA
141    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
142    GET_VREG r1, r3                     @ r1<- vAA (array object)
143    add     r0, rPC, r0, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
144    bl      art_quick_handle_fill_data  @ (payload, object)
145    FETCH_ADVANCE_INST 3                @ advance rPC, load rINST
146    GET_INST_OPCODE ip                  @ extract opcode from rINST
147    GOTO_OPCODE ip                      @ jump to next instruction
148
149%def op_filled_new_array(helper="nterp_filled_new_array"):
150/*
151 * Create a new array with elements filled from registers.
152 *
153 * for: filled-new-array, filled-new-array/range
154 */
155    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
156    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
157    EXPORT_PC
158    mov     r0, rSELF
159    ldr     r1, [sp]
160    mov     r2, rFP
161    mov     r3, rPC
162    bl      $helper
163    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
164    GET_INST_OPCODE ip                  // extract opcode from rINST
165    GOTO_OPCODE ip                      // jump to next instruction
166
167%def op_filled_new_array_range():
168%  op_filled_new_array(helper="nterp_filled_new_array_range")
169
170%def op_new_array():
171  b NterpNewArray
172