%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"): /* * Array get. vAA <- vBB[vCC]. * * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object * */ FETCH_B r2, 1, 0 @ r2<- BB mov r4, rINST, lsr #8 @ r4<- AA FETCH_B r3, 1, 1 @ r3<- CC GET_VREG r0, r2 @ r0<- vBB (array object) GET_VREG r1, r3 @ r1<- vCC (requested index) cmp r0, #0 @ null array object? beq common_errNullObject @ yes, bail ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width cmp r1, r3 @ compare unsigned index, length bcs common_errArrayIndex @ index >= length, bail FETCH_ADVANCE_INST 2 @ advance rPC, load rINST .if $wide CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs ldrd r2, [r0, #$data_offset] @ r2/r3<- vBB[vCC] VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA] GET_INST_OPCODE ip @ extract opcode from rINST SET_VREG_WIDE_BY_ADDR r2, r3, r4 @ vAA/vAA+1<- r2/r3 GOTO_OPCODE ip @ jump to next instruction .elseif $is_object $load r2, [r0, #$data_offset] @ w2<- vBB[vCC] TEST_IF_MARKING 2f 1: GET_INST_OPCODE ip @ extract opcode from rINST SET_VREG_OBJECT r2, r4 @ vAA<- w2 GOTO_OPCODE ip @ jump to next instruction 2: bl art_quick_read_barrier_mark_reg02 b 1b .else GET_INST_OPCODE ip @ extract opcode from rINST $load r2, [r0, #$data_offset] @ r2<- vBB[vCC] SET_VREG r2, r4 @ vAA<- r2 GOTO_OPCODE ip @ jump to next instruction .endif %def op_aget_boolean(): % op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aget_byte(): % op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aget_char(): % op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aget_object(): % op_aget(load="ldr", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1") %def op_aget_short(): % op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aget_wide(): % op_aget(load="ldrd", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0") %def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET", wide="0", is_object="0"): /* * Array put. vBB[vCC] <- vAA. * * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object * */ FETCH_B r2, 1, 0 @ r2<- BB mov r4, rINST, lsr #8 @ r4<- AA FETCH_B r3, 1, 1 @ r3<- CC GET_VREG r0, r2 @ r0<- vBB (array object) GET_VREG r1, r3 @ r1<- vCC (requested index) cmp r0, #0 @ null array object? beq common_errNullObject @ yes, bail ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length cmp r1, r3 @ compare unsigned index, length bcs common_errArrayIndex @ index >= length, bail .if $is_object EXPORT_PC // Export PC before overwriting it. FETCH_ADVANCE_INST 2 @ advance rPC, load rINST GET_VREG r2, r4 @ r2<- vAA bl art_quick_aput_obj GET_INST_OPCODE ip @ extract opcode from rINST .elseif $wide add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA] FETCH_ADVANCE_INST 2 @ advance rPC, load rINST GET_VREG_WIDE_BY_ADDR r2, r3, r4 @ r2/r3<- vAA/vAA+1 GET_INST_OPCODE ip @ extract opcode from rINST strd r2, [r0, #$data_offset] @ r2/r3<- vBB[vCC] .else add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width FETCH_ADVANCE_INST 2 @ advance rPC, load rINST GET_VREG r2, r4 @ r2<- vAA GET_INST_OPCODE ip @ extract opcode from rINST $store r2, [r0, #$data_offset] @ vBB[vCC]<- r2 .endif GOTO_OPCODE ip @ jump to next instruction %def op_aput_boolean(): % op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aput_byte(): % op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aput_char(): % op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aput_short(): % op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET", wide="0", is_object="0") %def op_aput_wide(): % op_aput(store="str", shift="3", data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET", wide="1", is_object="0") %def op_aput_object(): % op_aput(store="str", shift="2", data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET", wide="0", is_object="1") %def op_array_length(): /* * Return the length of an array. */ mov r1, rINST, lsr #12 @ r1<- B ubfx r2, rINST, #8, #4 @ r2<- A GET_VREG r0, r1 @ r0<- vB (object ref) cmp r0, #0 @ is object null? beq common_errNullObject @ yup, fail FETCH_ADVANCE_INST 1 @ advance rPC, load rINST ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- array length GET_INST_OPCODE ip @ extract opcode from rINST SET_VREG r3, r2 @ vB<- length GOTO_OPCODE ip @ jump to next instruction %def op_fill_array_data(): /* fill-array-data vAA, +BBBBBBBB */ EXPORT_PC FETCH r0, 1 @ r0<- bbbb (lo) FETCH r1, 2 @ r1<- BBBB (hi) mov r3, rINST, lsr #8 @ r3<- AA orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb GET_VREG r1, r3 @ r1<- vAA (array object) add r0, rPC, r0, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) bl art_quick_handle_fill_data @ (payload, object) FETCH_ADVANCE_INST 3 @ advance rPC, load rINST GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction %def op_filled_new_array(helper="nterp_filled_new_array"): /* * Create a new array with elements filled from registers. * * for: filled-new-array, filled-new-array/range */ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ EXPORT_PC mov r0, rSELF ldr r1, [sp] mov r2, rFP mov r3, rPC bl $helper FETCH_ADVANCE_INST 3 // advance rPC, load rINST GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction %def op_filled_new_array_range(): % op_filled_new_array(helper="nterp_filled_new_array_range") %def op_new_array(): /* new-array vA, vB, class@CCCC */ EXPORT_PC // Fast-path which gets the class from thread-local cache. % fetch_from_thread_cache("r0", miss_label="2f") TEST_IF_MARKING 3f 1: lsr r1, rINST, #12 // r1<- B GET_VREG r1, r1 // r1<- vB (array length) ldr lr, [rSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET] blx lr dmb ishst // need fence for making array's class visible ubfx r1, rINST, #8, #4 // r1<- A SET_VREG_OBJECT r0, r1 FETCH_ADVANCE_INST 2 GET_INST_OPCODE ip GOTO_OPCODE ip 2: mov r0, rSELF ldr r1, [sp] mov r2, rPC bl nterp_get_class b 1b 3: bl art_quick_read_barrier_mark_reg00 b 1b