1%def op_aget(load="ldr", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET"): 2 /* 3 * Array get, 32 bits or less. vAA <- vBB[vCC]. 4 * 5 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 6 * instructions. We use a pair of FETCH_Bs instead. 7 * 8 * for: aget, aget-boolean, aget-byte, aget-char, aget-short 9 * 10 * NOTE: assumes data offset for arrays is the same for all non-wide types. 11 * If this changes, specialize. 12 */ 13 /* op vAA, vBB, vCC */ 14 FETCH_B r2, 1, 0 @ r2<- BB 15 mov r9, rINST, lsr #8 @ r9<- AA 16 FETCH_B r3, 1, 1 @ r3<- CC 17 GET_VREG r0, r2 @ r0<- vBB (array object) 18 GET_VREG r1, r3 @ r1<- vCC (requested index) 19 cmp r0, #0 @ null array object? 20 beq common_errNullObject @ yes, bail 21 ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length 22 add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width 23 cmp r1, r3 @ compare unsigned index, length 24 bcs common_errArrayIndex @ index >= length, bail 25 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 26 $load r2, [r0, #$data_offset] @ r2<- vBB[vCC] 27 GET_INST_OPCODE ip @ extract opcode from rINST 28 SET_VREG r2, r9 @ vAA<- r2 29 GOTO_OPCODE ip @ jump to next instruction 30 31%def op_aget_boolean(): 32% op_aget(load="ldrb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET") 33 34%def op_aget_byte(): 35% op_aget(load="ldrsb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET") 36 37%def op_aget_char(): 38% op_aget(load="ldrh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET") 39 40%def op_aget_object(): 41 /* 42 * Array object get. vAA <- vBB[vCC]. 43 * 44 * for: aget-object 45 */ 46 /* op vAA, vBB, vCC */ 47 FETCH_B r2, 1, 0 @ r2<- BB 48 mov r9, rINST, lsr #8 @ r9<- AA 49 FETCH_B r3, 1, 1 @ r3<- CC 50 EXPORT_PC 51 GET_VREG r0, r2 @ r0<- vBB (array object) 52 GET_VREG r1, r3 @ r1<- vCC (requested index) 53 bl artAGetObjectFromMterp @ (array, index) 54 ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET] 55 PREFETCH_INST 2 56 cmp r1, #0 57 bne MterpException 58 SET_VREG_OBJECT r0, r9 59 ADVANCE 2 60 GET_INST_OPCODE ip 61 GOTO_OPCODE ip @ jump to next instruction 62 63%def op_aget_short(): 64% op_aget(load="ldrsh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET") 65 66%def op_aget_wide(): 67 /* 68 * Array get, 64 bits. vAA <- vBB[vCC]. 69 * 70 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 71 */ 72 /* aget-wide vAA, vBB, vCC */ 73 FETCH r0, 1 @ r0<- CCBB 74 mov r9, rINST, lsr #8 @ r9<- AA 75 and r2, r0, #255 @ r2<- BB 76 mov r3, r0, lsr #8 @ r3<- CC 77 GET_VREG r0, r2 @ r0<- vBB (array object) 78 GET_VREG r1, r3 @ r1<- vCC (requested index) 79 cmp r0, #0 @ null array object? 80 beq common_errNullObject @ yes, bail 81 ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length 82 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 83 cmp r1, r3 @ compare unsigned index, length 84 bcs common_errArrayIndex @ index >= length, bail 85 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 86 CLEAR_SHADOW_PAIR r9, lr, ip @ Zero out the shadow regs 87 ldrd r2, [r0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] @ r2/r3<- vBB[vCC] 88 VREG_INDEX_TO_ADDR r9, r9 @ r9<- &fp[AA] 89 GET_INST_OPCODE ip @ extract opcode from rINST 90 SET_VREG_WIDE_BY_ADDR r2, r3, r9 @ vAA/vAA+1<- r2/r3 91 GOTO_OPCODE ip @ jump to next instruction 92 93%def op_aput(store="str", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET"): 94 /* 95 * Array put, 32 bits or less. vBB[vCC] <- vAA. 96 * 97 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 98 * instructions. We use a pair of FETCH_Bs instead. 99 * 100 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 101 * 102 * NOTE: this assumes data offset for arrays is the same for all non-wide types. 103 * If this changes, specialize. 104 */ 105 /* op vAA, vBB, vCC */ 106 FETCH_B r2, 1, 0 @ r2<- BB 107 mov r9, rINST, lsr #8 @ r9<- AA 108 FETCH_B r3, 1, 1 @ r3<- CC 109 GET_VREG r0, r2 @ r0<- vBB (array object) 110 GET_VREG r1, r3 @ r1<- vCC (requested index) 111 cmp r0, #0 @ null array object? 112 beq common_errNullObject @ yes, bail 113 ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length 114 add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width 115 cmp r1, r3 @ compare unsigned index, length 116 bcs common_errArrayIndex @ index >= length, bail 117 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 118 GET_VREG r2, r9 @ r2<- vAA 119 GET_INST_OPCODE ip @ extract opcode from rINST 120 $store r2, [r0, #$data_offset] @ vBB[vCC]<- r2 121 GOTO_OPCODE ip @ jump to next instruction 122 123%def op_aput_boolean(): 124% op_aput(store="strb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET") 125 126%def op_aput_byte(): 127% op_aput(store="strb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET") 128 129%def op_aput_char(): 130% op_aput(store="strh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET") 131 132%def op_aput_object(): 133 /* 134 * Store an object into an array. vBB[vCC] <- vAA. 135 */ 136 /* op vAA, vBB, vCC */ 137 EXPORT_PC 138 add r0, rFP, #OFF_FP_SHADOWFRAME 139 mov r1, rPC 140 mov r2, rINST 141 bl MterpAputObject 142 cmp r0, #0 143 beq MterpPossibleException 144 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 145 GET_INST_OPCODE ip @ extract opcode from rINST 146 GOTO_OPCODE ip @ jump to next instruction 147 148%def op_aput_short(): 149% op_aput(store="strh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET") 150 151%def op_aput_wide(): 152 /* 153 * Array put, 64 bits. vBB[vCC] <- vAA. 154 * 155 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 156 */ 157 /* aput-wide vAA, vBB, vCC */ 158 FETCH r0, 1 @ r0<- CCBB 159 mov r9, rINST, lsr #8 @ r9<- AA 160 and r2, r0, #255 @ r2<- BB 161 mov r3, r0, lsr #8 @ r3<- CC 162 GET_VREG r0, r2 @ r0<- vBB (array object) 163 GET_VREG r1, r3 @ r1<- vCC (requested index) 164 cmp r0, #0 @ null array object? 165 beq common_errNullObject @ yes, bail 166 ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length 167 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 168 cmp r1, r3 @ compare unsigned index, length 169 VREG_INDEX_TO_ADDR r9, r9 @ r9<- &fp[AA] 170 bcs common_errArrayIndex @ index >= length, bail 171 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 172 GET_VREG_WIDE_BY_ADDR r2, r3, r9 @ r2/r3<- vAA/vAA+1 173 GET_INST_OPCODE ip @ extract opcode from rINST 174 strd r2, [r0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] @ r2/r3<- vBB[vCC] 175 GOTO_OPCODE ip @ jump to next instruction 176 177%def op_array_length(): 178 /* 179 * Return the length of an array. 180 */ 181 mov r1, rINST, lsr #12 @ r1<- B 182 ubfx r2, rINST, #8, #4 @ r2<- A 183 GET_VREG r0, r1 @ r0<- vB (object ref) 184 cmp r0, #0 @ is object null? 185 beq common_errNullObject @ yup, fail 186 FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 187 ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- array length 188 GET_INST_OPCODE ip @ extract opcode from rINST 189 SET_VREG r3, r2 @ vB<- length 190 GOTO_OPCODE ip @ jump to next instruction 191 192%def op_fill_array_data(): 193 /* fill-array-data vAA, +BBBBBBBB */ 194 EXPORT_PC 195 FETCH r0, 1 @ r0<- bbbb (lo) 196 FETCH r1, 2 @ r1<- BBBB (hi) 197 mov r3, rINST, lsr #8 @ r3<- AA 198 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 199 GET_VREG r0, r3 @ r0<- vAA (array object) 200 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 201 bl MterpFillArrayData @ (obj, payload) 202 cmp r0, #0 @ 0 means an exception is thrown 203 beq MterpPossibleException @ exception? 204 FETCH_ADVANCE_INST 3 @ advance rPC, load rINST 205 GET_INST_OPCODE ip @ extract opcode from rINST 206 GOTO_OPCODE ip @ jump to next instruction 207 208%def op_filled_new_array(helper="MterpFilledNewArray"): 209 /* 210 * Create a new array with elements filled from registers. 211 * 212 * for: filled-new-array, filled-new-array/range 213 */ 214 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 215 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 216 .extern $helper 217 EXPORT_PC 218 add r0, rFP, #OFF_FP_SHADOWFRAME 219 mov r1, rPC 220 mov r2, rSELF 221 bl $helper 222 cmp r0, #0 223 beq MterpPossibleException 224 FETCH_ADVANCE_INST 3 @ advance rPC, load rINST 225 GET_INST_OPCODE ip @ extract opcode from rINST 226 GOTO_OPCODE ip @ jump to next instruction 227 228%def op_filled_new_array_range(): 229% op_filled_new_array(helper="MterpFilledNewArrayRange") 230 231%def op_new_array(): 232 /* 233 * Allocate an array of objects, specified with the array class 234 * and a count. 235 * 236 * The verifier guarantees that this is an array class, so we don't 237 * check for it here. 238 */ 239 /* new-array vA, vB, class@CCCC */ 240 EXPORT_PC 241 add r0, rFP, #OFF_FP_SHADOWFRAME 242 mov r1, rPC 243 mov r2, rINST 244 mov r3, rSELF 245 bl MterpNewArray 246 cmp r0, #0 247 beq MterpPossibleException 248 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 249 GET_INST_OPCODE ip @ extract opcode from rINST 250 GOTO_OPCODE ip @ jump to next instruction 251