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