1%def field(helper=""): 2 /* 3 * General field read / write (iget-* iput-* sget-* sput-*). 4 */ 5 .extern $helper 6 mov x0, xPC // arg0: Instruction* inst 7 mov x1, xINST // arg1: uint16_t inst_data 8 add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf 9 mov x3, xSELF // arg3: Thread* self 10 PREFETCH_INST 2 // prefetch next opcode 11 bl $helper 12 cbz x0, MterpPossibleException 13 ADVANCE 2 14 GET_INST_OPCODE ip // extract opcode from rINST 15 GOTO_OPCODE ip // jump to next instruction 16 17%def op_check_cast(): 18 /* 19 * Check to see if a cast from one class to another is allowed. 20 */ 21 /* check-cast vAA, class//BBBB */ 22 EXPORT_PC 23 FETCH w0, 1 // w0<- BBBB 24 lsr w1, wINST, #8 // w1<- AA 25 VREG_INDEX_TO_ADDR x1, w1 // w1<- &object 26 ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method 27 mov x3, xSELF // w3<- self 28 bl MterpCheckCast // (index, &obj, method, self) 29 PREFETCH_INST 2 30 cbnz w0, MterpPossibleException 31 ADVANCE 2 32 GET_INST_OPCODE ip // extract opcode from rINST 33 GOTO_OPCODE ip // jump to next instruction 34 35%def op_iget(is_object=False, is_wide=False, load="ldr", helper="MterpIGetU32"): 36 // Fast-path which gets the field offset from thread-local cache. 37 add x0, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 38 ubfx x1, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 39 add x0, x0, x1, lsl #4 // entry address within the cache 40 ldp x0, x1, [x0] // entry key (pc) and value (offset) 41 lsr w2, wINST, #12 // B 42 GET_VREG w2, w2 // object we're operating on 43 cmp x0, xPC 44% slow_path_label = add_helper(lambda: field(helper)) 45 b.ne ${slow_path_label} // cache miss 46 cbz w2, common_errNullObject // null object 47% if is_wide: 48 ldr x0, [x2, x1] // x0<- obj.field 49% else: 50 ${load} w0, [x2, x1] // w0<- obj.field 51% #endif 52% if is_object: 53 UNPOISON_HEAP_REF w0 54#if defined(USE_READ_BARRIER) 55# if defined(USE_BAKER_READ_BARRIER) 56 ldr w1, [xSELF, #THREAD_IS_GC_MARKING_OFFSET] 57 cbnz w1, .L_${opcode}_mark // GC is active. 58.L_${opcode}_marked: 59# else 60 bl artReadBarrierMark // x0 <- artReadBarrierMark(x0) 61# endif 62#endif 63% #endif 64 ubfx w2, wINST, #8, #4 // w2<- A 65 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 66% if is_object: 67 SET_VREG_OBJECT w0, w2 // fp[A]<- w0 68% elif is_wide: 69 SET_VREG_WIDE x0, w2 // fp[A]<- x0 70% else: 71 SET_VREG w0, w2 // fp[A]<- w0 72% #endif 73 GET_INST_OPCODE ip // extract opcode from rINST 74 GOTO_OPCODE ip // jump to next instruction 75% if is_object: 76#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 77.L_${opcode}_mark: 78 bl artReadBarrierMark // x0 <- artReadBarrierMark(x0) 79 b .L_${opcode}_marked 80#endif 81% #endif 82 83%def op_iget_boolean(): 84% op_iget(load="ldrb", helper="MterpIGetU8") 85 86%def op_iget_boolean_quick(): 87% op_iget_quick(load="ldrb") 88 89%def op_iget_byte(): 90% op_iget(load="ldrsb", helper="MterpIGetI8") 91 92%def op_iget_byte_quick(): 93% op_iget_quick(load="ldrsb") 94 95%def op_iget_char(): 96% op_iget(load="ldrh", helper="MterpIGetU16") 97 98%def op_iget_char_quick(): 99% op_iget_quick(load="ldrh") 100 101%def op_iget_object(): 102% op_iget(is_object=True, helper="MterpIGetObj") 103 104%def op_iget_object_quick(): 105 /* For: iget-object-quick */ 106 /* op vA, vB, offset//CCCC */ 107 lsr w2, wINST, #12 // w2<- B 108 FETCH w1, 1 // w1<- field byte offset 109 EXPORT_PC 110 GET_VREG w0, w2 // w0<- object we're operating on 111 bl artIGetObjectFromMterp // (obj, offset) 112 ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] 113 ubfx w2, wINST, #8, #4 // w2<- A 114 PREFETCH_INST 2 115 cbnz w3, MterpPossibleException // bail out 116 SET_VREG_OBJECT w0, w2 // fp[A]<- w0 117 ADVANCE 2 // advance rPC 118 GET_INST_OPCODE ip // extract opcode from wINST 119 GOTO_OPCODE ip // jump to next instruction 120 121%def op_iget_quick(load="ldr", extend=""): 122 /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ 123 /* op vA, vB, offset//CCCC */ 124 lsr w2, wINST, #12 // w2<- B 125 FETCH w1, 1 // w1<- field byte offset 126 GET_VREG w3, w2 // w3<- object we're operating on 127 ubfx w2, wINST, #8, #4 // w2<- A 128 cbz w3, common_errNullObject // object was null 129 $load w0, [x3, x1] // w0<- obj.field 130 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 131 $extend 132 SET_VREG w0, w2 // fp[A]<- w0 133 GET_INST_OPCODE ip // extract opcode from rINST 134 GOTO_OPCODE ip // jump to next instruction 135 136%def op_iget_short(): 137% op_iget(load="ldrsh", helper="MterpIGetI16") 138 139%def op_iget_short_quick(): 140% op_iget_quick(load="ldrsh") 141 142%def op_iget_wide(): 143% op_iget(is_wide=True, helper="MterpIGetU64") 144 145%def op_iget_wide_quick(): 146 /* iget-wide-quick vA, vB, offset//CCCC */ 147 lsr w2, wINST, #12 // w2<- B 148 FETCH w4, 1 // w4<- field byte offset 149 GET_VREG w3, w2 // w3<- object we're operating on 150 ubfx w2, wINST, #8, #4 // w2<- A 151 cbz w3, common_errNullObject // object was null 152 ldr x0, [x3, x4] // x0<- obj.field 153 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 154 SET_VREG_WIDE x0, w2 155 GET_INST_OPCODE ip // extract opcode from wINST 156 GOTO_OPCODE ip // jump to next instruction 157 158%def op_instance_of(): 159 /* 160 * Check to see if an object reference is an instance of a class. 161 * 162 * Most common situation is a non-null object, being compared against 163 * an already-resolved class. 164 */ 165 /* instance-of vA, vB, class//CCCC */ 166 EXPORT_PC 167 FETCH w0, 1 // w0<- CCCC 168 lsr w1, wINST, #12 // w1<- B 169 VREG_INDEX_TO_ADDR x1, w1 // w1<- &object 170 ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method 171 mov x3, xSELF // w3<- self 172 bl MterpInstanceOf // (index, &obj, method, self) 173 ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] 174 ubfx w2, wINST, #8, #4 // w2<- A 175 PREFETCH_INST 2 176 cbnz x1, MterpException 177 ADVANCE 2 // advance rPC 178 SET_VREG w0, w2 // vA<- w0 179 GET_INST_OPCODE ip // extract opcode from rINST 180 GOTO_OPCODE ip // jump to next instruction 181 182%def op_iput(helper="MterpIPutU32"): 183% field(helper=helper) 184 185%def op_iput_boolean(): 186% op_iput(helper="MterpIPutU8") 187 188%def op_iput_boolean_quick(): 189% op_iput_quick(store="strb") 190 191%def op_iput_byte(): 192% op_iput(helper="MterpIPutI8") 193 194%def op_iput_byte_quick(): 195% op_iput_quick(store="strb") 196 197%def op_iput_char(): 198% op_iput(helper="MterpIPutU16") 199 200%def op_iput_char_quick(): 201% op_iput_quick(store="strh") 202 203%def op_iput_object(): 204% op_iput(helper="MterpIPutObj") 205 206%def op_iput_object_quick(): 207 EXPORT_PC 208 add x0, xFP, #OFF_FP_SHADOWFRAME 209 mov x1, xPC 210 mov w2, wINST 211 bl MterpIputObjectQuick 212 cbz w0, MterpException 213 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 214 GET_INST_OPCODE ip // extract opcode from rINST 215 GOTO_OPCODE ip // jump to next instruction 216 217%def op_iput_quick(store="str"): 218 /* For: iput-quick, iput-object-quick */ 219 /* op vA, vB, offset//CCCC */ 220 lsr w2, wINST, #12 // w2<- B 221 FETCH w1, 1 // w1<- field byte offset 222 GET_VREG w3, w2 // w3<- fp[B], the object pointer 223 ubfx w2, wINST, #8, #4 // w2<- A 224 cbz w3, common_errNullObject // object was null 225 GET_VREG w0, w2 // w0<- fp[A] 226 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 227 $store w0, [x3, x1] // obj.field<- w0 228 GET_INST_OPCODE ip // extract opcode from rINST 229 GOTO_OPCODE ip // jump to next instruction 230 231%def op_iput_short(): 232% op_iput(helper="MterpIPutI16") 233 234%def op_iput_short_quick(): 235% op_iput_quick(store="strh") 236 237%def op_iput_wide(): 238% op_iput(helper="MterpIPutU64") 239 240%def op_iput_wide_quick(): 241 /* iput-wide-quick vA, vB, offset//CCCC */ 242 lsr w2, wINST, #12 // w2<- B 243 FETCH w3, 1 // w3<- field byte offset 244 GET_VREG w2, w2 // w2<- fp[B], the object pointer 245 ubfx w0, wINST, #8, #4 // w0<- A 246 cbz w2, common_errNullObject // object was null 247 GET_VREG_WIDE x0, w0 // x0<- fp[A] 248 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 249 str x0, [x2, x3] // obj.field<- x0 250 GET_INST_OPCODE ip // extract opcode from wINST 251 GOTO_OPCODE ip // jump to next instruction 252 253%def op_new_instance(): 254 /* 255 * Create a new instance of a class. 256 */ 257 /* new-instance vAA, class//BBBB */ 258 EXPORT_PC 259 add x0, xFP, #OFF_FP_SHADOWFRAME 260 mov x1, xSELF 261 mov w2, wINST 262 bl MterpNewInstance // (shadow_frame, self, inst_data) 263 cbz w0, MterpPossibleException 264 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 265 GET_INST_OPCODE ip // extract opcode from rINST 266 GOTO_OPCODE ip // jump to next instruction 267 268%def op_sget(helper="MterpSGetU32"): 269% field(helper=helper) 270 271%def op_sget_boolean(): 272% op_sget(helper="MterpSGetU8") 273 274%def op_sget_byte(): 275% op_sget(helper="MterpSGetI8") 276 277%def op_sget_char(): 278% op_sget(helper="MterpSGetU16") 279 280%def op_sget_object(): 281% op_sget(helper="MterpSGetObj") 282 283%def op_sget_short(): 284% op_sget(helper="MterpSGetI16") 285 286%def op_sget_wide(): 287% op_sget(helper="MterpSGetU64") 288 289%def op_sput(helper="MterpSPutU32"): 290% field(helper=helper) 291 292%def op_sput_boolean(): 293% op_sput(helper="MterpSPutU8") 294 295%def op_sput_byte(): 296% op_sput(helper="MterpSPutI8") 297 298%def op_sput_char(): 299% op_sput(helper="MterpSPutU16") 300 301%def op_sput_object(): 302% op_sput(helper="MterpSPutObj") 303 304%def op_sput_short(): 305% op_sput(helper="MterpSPutI16") 306 307%def op_sput_wide(): 308% op_sput(helper="MterpSPutU64") 309