1%def op_aget(load="lw", 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(a2, 1, 0) # a2 <- BB 15 GET_OPA(rOBJ) # rOBJ <- AA 16 FETCH_B(a3, 1, 1) # a3 <- CC 17 GET_VREG(a0, a2) # a0 <- vBB (array object) 18 GET_VREG(a1, a3) # a1 <- vCC (requested index) 19 # null array object? 20 beqz a0, common_errNullObject # yes, bail 21 LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length 22 EASN(a0, a0, a1, $shift) # a0 <- arrayObj + index*width 23 # a1 >= a3; compare unsigned index 24 bgeu a1, a3, common_errArrayIndex # index >= length, bail 25 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 26 $load a2, $data_offset(a0) # a2 <- vBB[vCC] 27 GET_INST_OPCODE(t0) # extract opcode from rINST 28 SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2 29 30%def op_aget_boolean(): 31% op_aget(load="lbu", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET") 32 33%def op_aget_byte(): 34% op_aget(load="lb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET") 35 36%def op_aget_char(): 37% op_aget(load="lhu", 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(a2, 1, 0) # a2 <- BB 47 GET_OPA(rOBJ) # rOBJ <- AA 48 FETCH_B(a3, 1, 1) # a3 <- CC 49 EXPORT_PC() 50 GET_VREG(a0, a2) # a0 <- vBB (array object) 51 GET_VREG(a1, a3) # a1 <- vCC (requested index) 52 JAL(artAGetObjectFromMterp) # v0 <- GetObj(array, index) 53 lw a1, THREAD_EXCEPTION_OFFSET(rSELF) 54 PREFETCH_INST(2) # load rINST 55 bnez a1, MterpException 56 ADVANCE(2) # advance rPC 57 GET_INST_OPCODE(t0) # extract opcode from rINST 58 SET_VREG_OBJECT_GOTO(v0, rOBJ, t0) # vAA <- v0 59 60%def op_aget_short(): 61% op_aget(load="lh", shift="1", data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET") 62 63%def op_aget_wide(): 64 /* 65 * Array get, 64 bits. vAA <- vBB[vCC]. 66 * 67 * Arrays of long/double are 64-bit aligned. 68 */ 69 /* aget-wide vAA, vBB, vCC */ 70 FETCH(a0, 1) # a0 <- CCBB 71 GET_OPA(rOBJ) # rOBJ <- AA 72 and a2, a0, 255 # a2 <- BB 73 srl a3, a0, 8 # a3 <- CC 74 GET_VREG(a0, a2) # a0 <- vBB (array object) 75 GET_VREG(a1, a3) # a1 <- vCC (requested index) 76 # null array object? 77 beqz a0, common_errNullObject # yes, bail 78 LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length 79 EAS3(a0, a0, a1) # a0 <- arrayObj + index*width 80 bgeu a1, a3, common_errArrayIndex # index >= length, bail 81 82 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 83 LOAD64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET) 84 GET_INST_OPCODE(t0) # extract opcode from rINST 85 SET_VREG64_GOTO(a2, a3, rOBJ, t0) # vAA/vAA+1 <- a2/a3 86 87%def op_aput(store="sw", shift="2", data_offset="MIRROR_INT_ARRAY_DATA_OFFSET"): 88 89 /* 90 * Array put, 32 bits or less. vBB[vCC] <- vAA. 91 * 92 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 93 * 94 * NOTE: this assumes data offset for arrays is the same for all non-wide types. 95 * If this changes, specialize. 96 */ 97 /* op vAA, vBB, vCC */ 98 FETCH_B(a2, 1, 0) # a2 <- BB 99 GET_OPA(rOBJ) # rOBJ <- AA 100 FETCH_B(a3, 1, 1) # a3 <- CC 101 GET_VREG(a0, a2) # a0 <- vBB (array object) 102 GET_VREG(a1, a3) # a1 <- vCC (requested index) 103 # null array object? 104 beqz a0, common_errNullObject # yes, bail 105 LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length 106 EASN(a0, a0, a1, $shift) # a0 <- arrayObj + index*width 107 bgeu a1, a3, common_errArrayIndex # index >= length, bail 108 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 109 GET_VREG(a2, rOBJ) # a2 <- vAA 110 GET_INST_OPCODE(t0) # extract opcode from rINST 111 GET_OPCODE_TARGET(t0) 112 $store a2, $data_offset(a0) # vBB[vCC] <- a2 113 JR(t0) # jump to next instruction 114 115%def op_aput_boolean(): 116% op_aput(store="sb", shift="0", data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET") 117 118%def op_aput_byte(): 119% op_aput(store="sb", shift="0", data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET") 120 121%def op_aput_char(): 122% op_aput(store="sh", shift="1", data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET") 123 124%def op_aput_object(): 125 /* 126 * Store an object into an array. vBB[vCC] <- vAA. 127 * 128 */ 129 /* op vAA, vBB, vCC */ 130 EXPORT_PC() 131 addu a0, rFP, OFF_FP_SHADOWFRAME 132 move a1, rPC 133 move a2, rINST 134 JAL(MterpAputObject) 135 beqz v0, MterpPossibleException 136 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 137 GET_INST_OPCODE(t0) # extract opcode from rINST 138 GOTO_OPCODE(t0) # jump to next instruction 139 140%def op_aput_short(): 141% op_aput(store="sh", 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 /* aput-wide vAA, vBB, vCC */ 148 FETCH(a0, 1) # a0 <- CCBB 149 GET_OPA(t0) # t0 <- AA 150 and a2, a0, 255 # a2 <- BB 151 srl a3, a0, 8 # a3 <- CC 152 GET_VREG(a0, a2) # a0 <- vBB (array object) 153 GET_VREG(a1, a3) # a1 <- vCC (requested index) 154 # null array object? 155 beqz a0, common_errNullObject # yes, bail 156 LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length 157 EAS3(a0, a0, a1) # a0 <- arrayObj + index*width 158 EAS2(rOBJ, rFP, t0) # rOBJ <- &fp[AA] 159 # compare unsigned index, length 160 bgeu a1, a3, common_errArrayIndex # index >= length, bail 161 162 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 163 LOAD64(a2, a3, rOBJ) # a2/a3 <- vAA/vAA+1 164 GET_INST_OPCODE(t0) # extract opcode from rINST 165 GET_OPCODE_TARGET(t0) 166 STORE64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET) # a2/a3 <- vBB[vCC] 167 JR(t0) # jump to next instruction 168 169%def op_array_length(): 170 /* 171 * Return the length of an array. 172 */ 173 /* array-length vA, vB */ 174 GET_OPB(a1) # a1 <- B 175 GET_OPA4(a2) # a2 <- A+ 176 GET_VREG(a0, a1) # a0 <- vB (object ref) 177 # is object null? 178 beqz a0, common_errNullObject # yup, fail 179 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 180 LOAD_base_offMirrorArray_length(a3, a0) # a3 <- array length 181 GET_INST_OPCODE(t0) # extract opcode from rINST 182 SET_VREG_GOTO(a3, a2, t0) # vA <- length 183 184%def op_fill_array_data(): 185 /* fill-array-data vAA, +BBBBBBBB */ 186 EXPORT_PC() 187 FETCH(a1, 1) # a1 <- bbbb (lo) 188 FETCH(a0, 2) # a0 <- BBBB (hi) 189 GET_OPA(a3) # a3 <- AA 190 INSERT_HIGH_HALF(a1, a0) # a1 <- BBBBbbbb 191 GET_VREG(a0, a3) # a0 <- vAA (array object) 192 EAS1(a1, rPC, a1) # a1 <- PC + BBBBbbbb*2 (array data off.) 193 JAL(MterpFillArrayData) # v0 <- Mterp(obj, payload) 194 beqz v0, MterpPossibleException # has exception 195 FETCH_ADVANCE_INST(3) # advance rPC, load rINST 196 GET_INST_OPCODE(t0) # extract opcode from rINST 197 GOTO_OPCODE(t0) # jump to next instruction 198 199%def op_filled_new_array(helper="MterpFilledNewArray"): 200 /* 201 * Create a new array with elements filled from registers. 202 * 203 * for: filled-new-array, filled-new-array/range 204 */ 205 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 206 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 207 .extern $helper 208 EXPORT_PC() 209 addu a0, rFP, OFF_FP_SHADOWFRAME # a0 <- shadow frame 210 move a1, rPC 211 move a2, rSELF 212 JAL($helper) # v0 <- helper(shadow_frame, pc, self) 213 beqz v0, MterpPossibleException # has exception 214 FETCH_ADVANCE_INST(3) # advance rPC, load rINST 215 GET_INST_OPCODE(t0) # extract opcode from rINST 216 GOTO_OPCODE(t0) # jump to next instruction 217 218%def op_filled_new_array_range(): 219% op_filled_new_array(helper="MterpFilledNewArrayRange") 220 221%def op_new_array(): 222 /* 223 * Allocate an array of objects, specified with the array class 224 * and a count. 225 * 226 * The verifier guarantees that this is an array class, so we don't 227 * check for it here. 228 */ 229 /* new-array vA, vB, class@CCCC */ 230 EXPORT_PC() 231 addu a0, rFP, OFF_FP_SHADOWFRAME 232 move a1, rPC 233 move a2, rINST 234 move a3, rSELF 235 JAL(MterpNewArray) 236 beqz v0, MterpPossibleException 237 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 238 GET_INST_OPCODE(t0) # extract opcode from rINST 239 GOTO_OPCODE(t0) # jump to next instruction 240