xref: /aosp_15_r20/art/runtime/interpreter/mterp/arm64ng/array.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
2*795d594fSAndroid Build Coastguard Worker/*
3*795d594fSAndroid Build Coastguard Worker * Array get.  vAA <- vBB[vCC].
4*795d594fSAndroid Build Coastguard Worker *
5*795d594fSAndroid Build Coastguard Worker * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object
6*795d594fSAndroid Build Coastguard Worker *
7*795d594fSAndroid Build Coastguard Worker */
8*795d594fSAndroid Build Coastguard Worker    FETCH_B w2, 1, 0                    // w2<- BB
9*795d594fSAndroid Build Coastguard Worker    lsr     w9, wINST, #8               // w9<- AA
10*795d594fSAndroid Build Coastguard Worker    FETCH_B w3, 1, 1                    // w3<- CC
11*795d594fSAndroid Build Coastguard Worker    GET_VREG w0, w2                     // w0<- vBB (array object)
12*795d594fSAndroid Build Coastguard Worker    GET_VREG w1, w3                     // w1<- vCC (requested index)
13*795d594fSAndroid Build Coastguard Worker    cbz     x0, common_errNullObject    // bail if null array object.
14*795d594fSAndroid Build Coastguard Worker    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
15*795d594fSAndroid Build Coastguard Worker    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
16*795d594fSAndroid Build Coastguard Worker    cmp     w1, w3                      // compare unsigned index, length
17*795d594fSAndroid Build Coastguard Worker    bcs     common_errArrayIndex        // index >= length, bail
18*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
19*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE x10                 // extract opcode from wINST
20*795d594fSAndroid Build Coastguard Worker    .if $wide
21*795d594fSAndroid Build Coastguard Worker    ldr     x2, [x0, #$data_offset]     // x2<- vBB[vCC]
22*795d594fSAndroid Build Coastguard Worker    SET_VREG_WIDE x2, w9
23*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE x10                     // jump to next instruction
24*795d594fSAndroid Build Coastguard Worker    .elseif $is_object
25*795d594fSAndroid Build Coastguard Worker    $load   w2, [x0, #$data_offset]     // w2<- vBB[vCC]
26*795d594fSAndroid Build Coastguard Worker    UNPOISON_HEAP_REF w2
27*795d594fSAndroid Build Coastguard Worker    TEST_IF_MARKING 2f
28*795d594fSAndroid Build Coastguard Worker1:
29*795d594fSAndroid Build Coastguard Worker    SET_VREG_OBJECT w2, w9              // vAA<- w2
30*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE x10                     // jump to next instruction
31*795d594fSAndroid Build Coastguard Worker2:
32*795d594fSAndroid Build Coastguard Worker    bl art_quick_read_barrier_mark_reg02
33*795d594fSAndroid Build Coastguard Worker    b 1b
34*795d594fSAndroid Build Coastguard Worker    .else
35*795d594fSAndroid Build Coastguard Worker    $load   w2, [x0, #$data_offset]     // w2<- vBB[vCC]
36*795d594fSAndroid Build Coastguard Worker    SET_VREG w2, w9                     // vAA<- w2
37*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE x10                     // jump to next instruction
38*795d594fSAndroid Build Coastguard Worker    .endif
39*795d594fSAndroid Build Coastguard Worker
40*795d594fSAndroid Build Coastguard Worker%def op_aget_boolean():
41*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", is_object="0")
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker%def op_aget_byte():
44*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", is_object="0")
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker%def op_aget_char():
47*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", is_object="0")
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker%def op_aget_object():
50*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldr", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", is_object="1")
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker%def op_aget_short():
53*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", is_object="0")
54*795d594fSAndroid Build Coastguard Worker
55*795d594fSAndroid Build Coastguard Worker%def op_aget_wide():
56*795d594fSAndroid Build Coastguard Worker%  op_aget(load="ldr", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Worker%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"):
59*795d594fSAndroid Build Coastguard Worker/*
60*795d594fSAndroid Build Coastguard Worker * Array put.  vBB[vCC] <- vAA.
61*795d594fSAndroid Build Coastguard Worker *
62*795d594fSAndroid Build Coastguard Worker * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object
63*795d594fSAndroid Build Coastguard Worker *
64*795d594fSAndroid Build Coastguard Worker */
65*795d594fSAndroid Build Coastguard Worker    FETCH_B w2, 1, 0                    // w2<- BB
66*795d594fSAndroid Build Coastguard Worker    lsr     w9, wINST, #8               // w9<- AA
67*795d594fSAndroid Build Coastguard Worker    FETCH_B w3, 1, 1                    // w3<- CC
68*795d594fSAndroid Build Coastguard Worker    GET_VREG w0, w2                     // w0<- vBB (array object)
69*795d594fSAndroid Build Coastguard Worker    GET_VREG w1, w3                     // w1<- vCC (requested index)
70*795d594fSAndroid Build Coastguard Worker    cbz     w0, common_errNullObject    // bail if null
71*795d594fSAndroid Build Coastguard Worker    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
72*795d594fSAndroid Build Coastguard Worker    .if !$is_object
73*795d594fSAndroid Build Coastguard Worker    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
74*795d594fSAndroid Build Coastguard Worker    .endif
75*795d594fSAndroid Build Coastguard Worker    cmp     w1, w3                      // compare unsigned index, length
76*795d594fSAndroid Build Coastguard Worker    bcs     common_errArrayIndex        // index >= length, bail
77*795d594fSAndroid Build Coastguard Worker    .if $is_object
78*795d594fSAndroid Build Coastguard Worker    EXPORT_PC                           // Export PC before overwriting it.
79*795d594fSAndroid Build Coastguard Worker    .endif
80*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
81*795d594fSAndroid Build Coastguard Worker    .if $wide
82*795d594fSAndroid Build Coastguard Worker    GET_VREG_WIDE x2, w9                // x2<- vAA
83*795d594fSAndroid Build Coastguard Worker    .else
84*795d594fSAndroid Build Coastguard Worker    GET_VREG w2, w9                     // w2<- vAA
85*795d594fSAndroid Build Coastguard Worker    .endif
86*795d594fSAndroid Build Coastguard Worker    .if $wide
87*795d594fSAndroid Build Coastguard Worker    $store  x2, [x0, #$data_offset]     // vBB[vCC]<- x2
88*795d594fSAndroid Build Coastguard Worker    .elseif $is_object
89*795d594fSAndroid Build Coastguard Worker    bl art_quick_aput_obj
90*795d594fSAndroid Build Coastguard Worker    .else
91*795d594fSAndroid Build Coastguard Worker    $store  w2, [x0, #$data_offset]     // vBB[vCC]<- w2
92*795d594fSAndroid Build Coastguard Worker    .endif
93*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
94*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
95*795d594fSAndroid Build Coastguard Worker
96*795d594fSAndroid Build Coastguard Worker%def op_aput_boolean():
97*795d594fSAndroid Build Coastguard Worker%  op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0")
98*795d594fSAndroid Build Coastguard Worker
99*795d594fSAndroid Build Coastguard Worker%def op_aput_byte():
100*795d594fSAndroid Build Coastguard Worker%  op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0")
101*795d594fSAndroid Build Coastguard Worker
102*795d594fSAndroid Build Coastguard Worker%def op_aput_char():
103*795d594fSAndroid Build Coastguard Worker%  op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0")
104*795d594fSAndroid Build Coastguard Worker
105*795d594fSAndroid Build Coastguard Worker%def op_aput_short():
106*795d594fSAndroid Build Coastguard Worker%  op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0")
107*795d594fSAndroid Build Coastguard Worker
108*795d594fSAndroid Build Coastguard Worker%def op_aput_wide():
109*795d594fSAndroid Build Coastguard Worker%  op_aput(store="str", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0")
110*795d594fSAndroid Build Coastguard Worker
111*795d594fSAndroid Build Coastguard Worker%def op_aput_object():
112*795d594fSAndroid Build Coastguard Worker%  op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="1")
113*795d594fSAndroid Build Coastguard Worker
114*795d594fSAndroid Build Coastguard Worker%def op_array_length():
115*795d594fSAndroid Build Coastguard Worker    /*
116*795d594fSAndroid Build Coastguard Worker     * Return the length of an array.
117*795d594fSAndroid Build Coastguard Worker     */
118*795d594fSAndroid Build Coastguard Worker    lsr     w1, wINST, #12              // w1<- B
119*795d594fSAndroid Build Coastguard Worker    ubfx    w2, wINST, #8, #4           // w2<- A
120*795d594fSAndroid Build Coastguard Worker    GET_VREG w0, w1                     // w0<- vB (object ref)
121*795d594fSAndroid Build Coastguard Worker    cbz     w0, common_errNullObject    // bail if null
122*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
123*795d594fSAndroid Build Coastguard Worker    ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- array length
124*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
125*795d594fSAndroid Build Coastguard Worker    SET_VREG w3, w2                     // vB<- length
126*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker%def op_fill_array_data():
129*795d594fSAndroid Build Coastguard Worker    /* fill-array-data vAA, +BBBBBBBB */
130*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
131*795d594fSAndroid Build Coastguard Worker    FETCH   w0, 1                       // x0<- 000000000000bbbb (lo)
132*795d594fSAndroid Build Coastguard Worker    FETCH_S x1, 2                       // x1<- ssssssssssssBBBB (hi)
133*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #8               // w3<- AA
134*795d594fSAndroid Build Coastguard Worker    orr     x0, x0, x1, lsl #16         // x0<- ssssssssBBBBbbbb
135*795d594fSAndroid Build Coastguard Worker    GET_VREG w1, w3                     // w1<- vAA (array object)
136*795d594fSAndroid Build Coastguard Worker    add     x0, xPC, x0, lsl #1         // x0<- PC + ssssssssBBBBbbbb*2 (array data off.)
137*795d594fSAndroid Build Coastguard Worker    bl      art_quick_handle_fill_data
138*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
139*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
140*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
141*795d594fSAndroid Build Coastguard Worker
142*795d594fSAndroid Build Coastguard Worker%def op_filled_new_array(helper="nterp_filled_new_array"):
143*795d594fSAndroid Build Coastguard Worker/*
144*795d594fSAndroid Build Coastguard Worker * Create a new array with elements filled from registers.
145*795d594fSAndroid Build Coastguard Worker *
146*795d594fSAndroid Build Coastguard Worker * for: filled-new-array, filled-new-array/range
147*795d594fSAndroid Build Coastguard Worker */
148*795d594fSAndroid Build Coastguard Worker    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
149*795d594fSAndroid Build Coastguard Worker    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
150*795d594fSAndroid Build Coastguard Worker    EXPORT_PC
151*795d594fSAndroid Build Coastguard Worker    mov     x0, xSELF
152*795d594fSAndroid Build Coastguard Worker    ldr     x1, [sp]
153*795d594fSAndroid Build Coastguard Worker    mov     x2, xFP
154*795d594fSAndroid Build Coastguard Worker    mov     x3, xPC
155*795d594fSAndroid Build Coastguard Worker    bl      $helper
156*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
157*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
158*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker%def op_filled_new_array_range():
161*795d594fSAndroid Build Coastguard Worker%  op_filled_new_array(helper="nterp_filled_new_array_range")
162*795d594fSAndroid Build Coastguard Worker
163*795d594fSAndroid Build Coastguard Worker%def op_new_array():
164*795d594fSAndroid Build Coastguard Worker   /* new-array vA, vB, class@CCCC */
165*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
166*795d594fSAndroid Build Coastguard Worker   // Fast-path which gets the class from thread-local cache.
167*795d594fSAndroid Build Coastguard Worker%  fetch_from_thread_cache("x0", miss_label="2f")
168*795d594fSAndroid Build Coastguard Worker   TEST_IF_MARKING 3f
169*795d594fSAndroid Build Coastguard Worker1:
170*795d594fSAndroid Build Coastguard Worker   lsr     w1, wINST, #12              // w1<- B
171*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1                     // w1<- vB (array length)
172*795d594fSAndroid Build Coastguard Worker   ldr lr, [xSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
173*795d594fSAndroid Build Coastguard Worker   blr lr
174*795d594fSAndroid Build Coastguard Worker   dmb ishst                           // need fence for making array's class visible
175*795d594fSAndroid Build Coastguard Worker   ubfx    w1, wINST, #8, #4           // w1<- A
176*795d594fSAndroid Build Coastguard Worker   SET_VREG_OBJECT w0, w1
177*795d594fSAndroid Build Coastguard Worker   FETCH_ADVANCE_INST 2
178*795d594fSAndroid Build Coastguard Worker   GET_INST_OPCODE ip
179*795d594fSAndroid Build Coastguard Worker   GOTO_OPCODE ip
180*795d594fSAndroid Build Coastguard Worker2:
181*795d594fSAndroid Build Coastguard Worker   mov x0, xSELF
182*795d594fSAndroid Build Coastguard Worker   ldr x1, [sp, 0]
183*795d594fSAndroid Build Coastguard Worker   mov x2, xPC
184*795d594fSAndroid Build Coastguard Worker   bl nterp_get_class
185*795d594fSAndroid Build Coastguard Worker   b 1b
186*795d594fSAndroid Build Coastguard Worker3:
187*795d594fSAndroid Build Coastguard Worker   bl art_quick_read_barrier_mark_reg00
188*795d594fSAndroid Build Coastguard Worker   b 1b
189