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