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 UNPOISON_HEAP_REF r2 30 TEST_IF_MARKING 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 /* new-array vA, vB, class@CCCC */ 172 EXPORT_PC 173 // Fast-path which gets the class from thread-local cache. 174% fetch_from_thread_cache("r0", miss_label="2f") 175 TEST_IF_MARKING 3f 1761: 177 lsr r1, rINST, #12 // r1<- B 178 GET_VREG r1, r1 // r1<- vB (array length) 179 ldr lr, [rSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET] 180 blx lr 181 dmb ishst // need fence for making array's class visible 182 ubfx r1, rINST, #8, #4 // r1<- A 183 SET_VREG_OBJECT r0, r1 184 FETCH_ADVANCE_INST 2 185 GET_INST_OPCODE ip 186 GOTO_OPCODE ip 1872: 188 mov r0, rSELF 189 ldr r1, [sp] 190 mov r2, rPC 191 bl nterp_get_class 192 b 1b 1933: 194 bl art_quick_read_barrier_mark_reg00 195 b 1b 196