xref: /aosp_15_r20/art/runtime/interpreter/mterp/riscv64/array.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1// array-length vA, vB
2// Format 12x: B|A|21
3// Store in the given destination register the length of the indicated array, in entries
4%def op_array_length():
5   srliw t0, xINST, 12     // t0 := B
6   GET_VREG_OBJECT t0, t0  // t0 := refs[B]
7   beqz t0, 1f
8   srliw t1, xINST, 8      // t1 := B|A
9   FETCH_ADVANCE_INST 1
10   andi t1, t1, 0xF        // t1 := A
11   GET_INST_OPCODE t3
12   lw t2, MIRROR_ARRAY_LENGTH_OFFSET(t0)
13%  set_vreg("t2", "t1", z0="t0")
14   GOTO_OPCODE t3
151:
16   tail common_errNullObject
17
18
19// new-array vA, vB, type@CCCC
20// Format 22c: B|A|23 CCCC
21// Construct a new array of the indicated type and size. The type must be an array type.
22%def op_new_array():
23   EXPORT_PC
24   srliw s8, xINST, 8   // s8 := B|A
25   srliw s7, xINST, 12  // s7 := B
26   andi s8, s8, 0xF     // s8 := A
27   FETCH_FROM_THREAD_CACHE /*resolved klass*/a0, .L${opcode}_miss, t0, t1
28   TEST_IF_MARKING t0, .L${opcode}_mark
29.L${opcode}_resume:
30
31%  get_vreg("a1", "s7")  # a1 := fp[B] length
32   ld t0, THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET(xSELF)
33   jalr t0     // args a0 (klass), a1 (length)
34               // return a0 := new-array
35   fence w, w  // constructor fence; main.S has details
36
37   SET_VREG_OBJECT a0, s8, z0=t0  // refs[A] := new-array
38   FETCH_ADVANCE_INST 2
39   GET_INST_OPCODE t0
40   GOTO_OPCODE t0
41
42.L${opcode}_mark:
43   call art_quick_read_barrier_mark_reg10  // a0, klass
44   j .L${opcode}_resume
45
46.L${opcode}_miss:
47   EXPORT_PC
48   mv a0, xSELF
49   ld a1, (sp)  // caller ArtMethod*
50   mv a2, xPC
51   call nterp_get_class
52   j .L${opcode}_resume
53
54
55
56
57// filled-new-array {vC, vD, vE, vF, vG}, type@BBBB
58// Format 35c: A|G|24 BBBB F|E|D|C
59// Construct an array of the given type and size, filling it with the supplied contents. The type
60// must be an array type. The array's contents must be single-word (that is, no arrays of long or
61// double, but reference types are acceptable). The constructed instance is stored as a "result" in
62// the same way that the method invocation instructions store their results, so the constructed
63// instance must be moved to a register with an immediately subsequent move-result-object
64// instruction (if it is to be used).
65%def op_filled_new_array(is_range=False):
66   EXPORT_PC
67   mv a0, xSELF
68   ld a1, (sp)  // a1 := caller ArtMethod*
69   mv a2, xFP   // a2 := vreg array
70   mv a3, xPC
71%  if is_range:
72     call nterp_filled_new_array_range  // args a0, a1, a2, a3
73%  else:
74     call nterp_filled_new_array  // args a0, a1, a2, a3
75%#:
76   FETCH_ADVANCE_INST 3
77   GET_INST_OPCODE t0
78   GOTO_OPCODE t0
79
80
81// filled-new-array/range {vCCCC .. vNNNN}, type@BBBB
82// where NNNN = CCCC + AA - 1
83// Format 3rc: AA|25 BBBB CCCC
84// Construct an array of the given type and size, filling it with the supplied contents.
85// Clarifications and restrictions are the same as filled-new-array, described above.
86%def op_filled_new_array_range():
87%  op_filled_new_array(is_range=True)
88
89
90// fill-array-data vAA, +BBBBBBBB
91// Format 31t: AA|26 BBBB(lo) BBBB(hi)
92// Fill the given array with the indicated data. The reference must be to an array of primitives,
93// and the data table must match it in type and must contain no more elements than will fit in the
94// array. That is, the array may be larger than the table, and if so, only the initial elements of
95// the array are set, leaving the remainder alone.
96%def op_fill_array_data():
97   EXPORT_PC
98   srliw t0, xINST, 8      // t0 := AA
99   FETCH t1, count=1, signed=1, width=32
100                           // t1 := ssssssssBBBBBBBB
101   GET_VREG_OBJECT a1, t0  // a1 := refs[AA] (array ref)
102   // +BBBBBBBB offset is in code units. Multiply by 2 for byte offset against dex PC.
103   sh1add a0, t1, xPC      // a0 := payload address
104   call art_quick_handle_fill_data  // args a0, a1
105   FETCH_ADVANCE_INST 3
106   GET_INST_OPCODE t0
107   GOTO_OPCODE t0
108
109
110// Common setup across APUT and AGET variants.
111// Sets \array, \index, and \length registers.
112// Branches to null handler and out-of-bounds handler.
113%def array_prelude(array, index, length, null_label, oob_label):
114   FETCH $index, count=1           // index := CC|BB
115   andi $array, $index, 0xFF       // array := BB
116   GET_VREG_OBJECT $array, $array  // array := refs[BB], array obj
117   beqz $array, $null_label
118
119   srliw $index, $index, 8         // index := CC
120%  get_vreg(index, index)          # index := fp[CC]
121   lw $length, MIRROR_ARRAY_LENGTH_OFFSET($array)  // length (signed 32b)
122   bgeu $index, $length, $oob_label  // Unsigned comparison also catches negative index.
123
124
125// aget vAA, vBB, vCC
126// Format 23x: AA|44 CC|BB
127// vAA := vBB[vCC]
128%def op_aget(width=32, zext=False):
129%  array_prelude(array="t0", index="a0", length="a1", null_label=f".L{opcode}_null", oob_label=f".L{opcode}_oob")
130       // t0 := vBB array object, a0 := vCC index, a1 := array length
131
132%  if width == 8 and zext:
133     add t0, a0, t0
134     lbu t0, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(t0)
135%  elif width == 8:
136     add t0, a0, t0
137     lb t0, MIRROR_BYTE_ARRAY_DATA_OFFSET(t0)
138%  elif width == 16 and zext:
139     sh1add t0, a0, t0
140     lhu t0, MIRROR_CHAR_ARRAY_DATA_OFFSET(t0)
141%  elif width == 16:
142     sh1add t0, a0, t0
143     lh t0, MIRROR_SHORT_ARRAY_DATA_OFFSET(t0)
144%  elif width == 32:
145     sh2add t0, a0, t0
146     lw t0, MIRROR_INT_ARRAY_DATA_OFFSET(t0)
147%  elif width == 64:
148     sh3add t0, a0, t0
149     ld t0, MIRROR_WIDE_ARRAY_DATA_OFFSET(t0)
150%  else:
151%    assert False, width
152%#:
153                       // t0 := *(array obj + data offset + idx * elem_size)
154   srliw t1, xINST, 8  // t1 := AA
155%  set_vreg("t0", "t1", z0="t2", width=width)
156
157   FETCH_ADVANCE_INST 2
158   GET_INST_OPCODE t0
159   GOTO_OPCODE t0
160
161.L${opcode}_null:
162   tail common_errNullObject
163.L${opcode}_oob:
164   tail common_errArrayIndex  // args a0 (index), a1 (length)
165
166
167// aget-wide vAA, vBB, vCC
168// Format 23x: AA|45 CC|BB
169%def op_aget_wide():
170%  op_aget(width=64)
171
172
173// aget-object vAA, vBB, vCC
174// Format 23x: AA|46 CC|BB
175%def op_aget_object():
176%  array_prelude(array="t0", index="a0", length="a1", null_label=f".L{opcode}_null", oob_label=f".L{opcode}_oob")
177       // t0 := vBB array object, a0 := vCC index, a1 := array length
178
179   sh2add t0, a0, t0
180   lwu a0, MIRROR_OBJECT_ARRAY_DATA_OFFSET(t0)
181       // a0 := *(array obj + data offset + idx * elem_size)
182   UNPOISON_HEAP_REF a0
183   TEST_IF_MARKING t1, .L${opcode}_mark
184.L${opcode}_mark_resume:
185   srliw t1, xINST, 8  // t1 := AA
186   SET_VREG_OBJECT a0, t1, z0=t2
187
188   FETCH_ADVANCE_INST 2
189   GET_INST_OPCODE t0
190   GOTO_OPCODE t0
191
192.L${opcode}_mark:
193   call art_quick_read_barrier_mark_reg10  // a0, object elem
194   j .L${opcode}_mark_resume
195.L${opcode}_null:
196   tail common_errNullObject
197.L${opcode}_oob:
198   tail common_errArrayIndex  // args a0 (index), a1 (length)
199
200
201// aget-boolean vAA, vBB, vCC
202// Format 23x: AA|47 CC|BB
203%def op_aget_boolean():
204%  op_aget(width=8, zext=True)
205
206
207// aget-byte vAA, vBB, vCC
208// Format 23x: AA|48 CC|BB
209%def op_aget_byte():
210%  op_aget(width=8)
211
212
213// aget_char vAA, vBB, vCC
214// Format 23x: AA|49 CC|BB
215%def op_aget_char():
216%  op_aget(width=16, zext=True)
217
218
219// aget-short vAA, vBB, vCC
220// Format 23x: AA|4a CC|BB
221%def op_aget_short():
222%  op_aget(width=16)
223
224
225// aput vAA, vBB, vCC
226// Format 23x: AA|4b CC|BB
227// vBB[vCC] := vAA
228%def op_aput(width=32, zext=False):
229%  array_prelude(array="t0", index="t1", length="t2", null_label=f".L{opcode}_null", oob_label=f".L{opcode}_oob")
230       // t0 := vBB array object, t1 := vCC zext index, t2 := array length
231
232   srliw t2, xINST, 8      // t2 := AA
233%  get_vreg("t2", "t2", width=width)  # t2 := fp[AA]
234%  if width == 8 and zext:
235     add t0, t1, t0
236     sb t2, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(t0)
237%  elif width == 8:
238     add t0, t1, t0
239     sb t2, MIRROR_BYTE_ARRAY_DATA_OFFSET(t0)
240%  elif width == 16 and zext:
241     sh1add t0, t1, t0
242     sh t2, MIRROR_CHAR_ARRAY_DATA_OFFSET(t0)
243%  elif width == 16:
244     sh1add t0, t1, t0
245     sh t2, MIRROR_SHORT_ARRAY_DATA_OFFSET(t0)
246%  elif width == 32:
247     sh2add t0, t1, t0
248     sw t2, MIRROR_INT_ARRAY_DATA_OFFSET(t0)
249%  elif width == 64:
250     sh3add t0, t1, t0
251     sd t2, MIRROR_WIDE_ARRAY_DATA_OFFSET(t0)
252%  else:
253%    assert False, width
254%#:
255   FETCH_ADVANCE_INST 2
256   GET_INST_OPCODE t0
257   GOTO_OPCODE t0
258
259.L${opcode}_null:
260   tail common_errNullObject
261.L${opcode}_oob:
262   sext.w a0, t1
263   mv a1, t2
264   tail common_errArrayIndex  // args a0 (index), a1 (length)
265
266
267// aput-wide vAA, vBB, vCC
268// Format 23x: AA|4c CC|BB
269%def op_aput_wide():
270%  op_aput(width=64)
271
272
273// aput-object vAA, vBB, vCC
274// Format 23x: AA|4d CC|BB
275%def op_aput_object():
276%  array_prelude(array="a0", index="a1", length="a2", null_label=f".L{opcode}_null", oob_label=f".L{opcode}_oob")
277       // a0 := vBB array object, a1 := vCC zext index, a2 := array length
278
279   EXPORT_PC
280   srliw a2, xINST, 8       // a2 := AA
281   GET_VREG_OBJECT a2, a2   // a2 := fp[AA]
282   sext.w a1, a1            // a1 := sext index
283   call art_quick_aput_obj  // args a0 (array obj), a1 (index), a2 (obj)
284
285   FETCH_ADVANCE_INST 2
286   GET_INST_OPCODE t0
287   GOTO_OPCODE t0
288
289.L${opcode}_null:
290   tail common_errNullObject
291.L${opcode}_oob:
292   sext.w a0, a1
293   mv a1, a2
294   tail common_errArrayIndex  // args a0 (index), a1 (length)
295
296// aput-boolean vAA, vBB, vCC
297// Format 23x: AA|4e CC|BB
298%def op_aput_boolean():
299%  op_aput(width=8, zext=True)
300
301
302// aput-byte vAA, vBB, vCC
303// Format 23x: AA|4f CC|BB
304%def op_aput_byte():
305%  op_aput(width=8)
306
307
308// aput-char vAA, vBB, vCC
309// Format 23x: AA|50 CC|BB
310%def op_aput_char():
311%  op_aput(width=16, zext=True)
312
313
314// aput-short vAA, vBB, vCC
315// Format 23x: AA|51 CC|BB
316%def op_aput_short():
317%  op_aput(width=16)
318