1%def op_check_cast(): 2 // Fast-path which gets the class from thread-local cache. 3 EXPORT_PC 4 FETCH_FROM_THREAD_CACHE x1, 3f 5 cbnz wMR, 4f 61: 7 lsr w2, wINST, #8 // w2<- A 8 GET_VREG w0, w2 // w0<- vA (object) 9 cbz w0, 2f 10 bl art_quick_check_instance_of 112: 12 FETCH_ADVANCE_INST 2 13 GET_INST_OPCODE ip 14 GOTO_OPCODE ip 153: 16 mov x0, xSELF 17 ldr x1, [sp] 18 mov x2, xPC 19 bl nterp_get_class_or_allocate_object 20 mov x1, x0 21 b 1b 224: 23 bl art_quick_read_barrier_mark_reg01 24 b 1b 25 26%def op_instance_of(): 27 /* instance-of vA, vB, class@CCCC */ 28 // Fast-path which gets the class from thread-local cache. 29 EXPORT_PC 30 FETCH_FROM_THREAD_CACHE x1, 3f 31 cbnz wMR, 4f 321: 33 lsr w2, wINST, #12 // w2<- B 34 GET_VREG w0, w2 // w0<- vB (object) 35 cbz w0, 2f 36 bl artInstanceOfFromCode 372: 38 ubfx w1, wINST, #8, #4 // w1<- A 39 SET_VREG w0, w1 40 FETCH_ADVANCE_INST 2 41 GET_INST_OPCODE ip 42 GOTO_OPCODE ip 433: 44 mov x0, xSELF 45 ldr x1, [sp] 46 mov x2, xPC 47 bl nterp_get_class_or_allocate_object 48 mov x1, x0 49 b 1b 504: 51 bl art_quick_read_barrier_mark_reg01 52 b 1b 53 54%def op_iget_boolean(): 55% op_iget(load="ldrb", volatile_load="ldarb", maybe_extend="", wide="0", is_object="0") 56 57%def op_iget_byte(): 58% op_iget(load="ldrsb", volatile_load="ldarb", maybe_extend="sxtb w0, w0", wide="0", is_object="0") 59 60%def op_iget_char(): 61% op_iget(load="ldrh", volatile_load="ldarh", maybe_extend="", wide="0", is_object="0") 62 63%def op_iget_short(): 64% op_iget(load="ldrsh", volatile_load="ldarh", maybe_extend="sxth w0, w0", wide="0", is_object="0") 65 66%def op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="0"): 67% slow_path = add_helper(lambda: op_iget_slow_path(volatile_load, maybe_extend, wide, is_object)) 68 // Fast-path which gets the field from thread-local cache. 69 FETCH_FROM_THREAD_CACHE x0, ${slow_path} 70.L${opcode}_resume: 71 lsr w2, wINST, #12 // w2<- B 72 GET_VREG w3, w2 // w3<- object we're operating on 73 ubfx w2, wINST, #8, #4 // w2<- A 74 cbz w3, common_errNullObject // object was null 75 .if $wide 76 $load x0, [x3, x0] 77 SET_VREG_WIDE x0, w2 // fp[A] <- value 78 .elseif $is_object 79 $load w0, [x3, x0] 80 cbnz wMR, .L${opcode}_read_barrier 81.L${opcode}_resume_after_read_barrier: 82 SET_VREG_OBJECT w0, w2 // fp[A] <- value 83 .else 84 $load w0, [x3, x0] 85 SET_VREG w0, w2 // fp[A] <- value 86 .endif 87 FETCH_ADVANCE_INST 2 88 GET_INST_OPCODE ip 89 GOTO_OPCODE ip 90 .if $is_object 91.L${opcode}_read_barrier: 92 bl art_quick_read_barrier_mark_reg00 93 b .L${opcode}_resume_after_read_barrier 94 .endif 95 96%def op_iget_slow_path(volatile_load, maybe_extend, wide, is_object): 97 mov x0, xSELF 98 ldr x1, [sp] 99 mov x2, xPC 100 mov x3, #0 101 EXPORT_PC 102 bl nterp_get_instance_field_offset 103 tbz w0, #31, .L${opcode}_resume 104 CLEAR_INSTANCE_VOLATILE_MARKER w0 105 lsr w2, wINST, #12 // w2<- B 106 GET_VREG w3, w2 // w3<- object we're operating on 107 ubfx w2, wINST, #8, #4 // w2<- A 108 cbz w3, common_errNullObject // object was null 109 add x3, x3, x0 110 .if $wide 111 $volatile_load x0, [x3] 112 SET_VREG_WIDE x0, w2 // fp[A] <- value 113 .elseif $is_object 114 $volatile_load w0, [x3] 115 cbnz wMR, .L${opcode}_read_barrier 116 SET_VREG_OBJECT w0, w2 // fp[A] <- value 117 .else 118 $volatile_load w0, [x3] 119 $maybe_extend 120 SET_VREG w0, w2 // fp[A] <- value 121 .endif 122 FETCH_ADVANCE_INST 2 123 GET_INST_OPCODE ip 124 GOTO_OPCODE ip 125 126%def op_iget_wide(): 127% op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="1", is_object="0") 128 129%def op_iget_object(): 130% op_iget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="1") 131 132%def op_iput_boolean(): 133% op_iput(store="strb", volatile_store="stlrb", wide="0", is_object="0") 134 135%def op_iput_byte(): 136% op_iput(store="strb", volatile_store="stlrb", wide="0", is_object="0") 137 138%def op_iput_char(): 139% op_iput(store="strh", volatile_store="stlrh", wide="0", is_object="0") 140 141%def op_iput_short(): 142% op_iput(store="strh", volatile_store="stlrh", wide="0", is_object="0") 143 144%def op_iput(store="str", volatile_store="stlr", wide="0", is_object="0"): 145 // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh). 146 // It does not matter to which `.L${opcode}_resume` the slow path returns. 147% slow_path = "nterp_op_iput_helper_" + store + wide + is_object 148% add_helper(lambda: op_iput_slow_path(volatile_store, wide, is_object), slow_path) 149 ubfx w1, wINST, #8, #4 // w1<- A 150 .if $wide 151 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 152 .else 153 GET_VREG w26, w1 // w26 <- v[A] 154 .endif 155 // Fast-path which gets the field from thread-local cache. 156 FETCH_FROM_THREAD_CACHE x0, ${slow_path} 157.L${opcode}_resume: 158 lsr w2, wINST, #12 // w2<- B 159 GET_VREG w2, w2 // vB (object we're operating on) 160 cbz w2, common_errNullObject 161 .if $wide 162 $store x26, [x2, x0] 163 .else 164 $store w26, [x2, x0] 165 WRITE_BARRIER_IF_OBJECT $is_object, w26, w2, .L${opcode}_skip_write_barrier 166 .endif 167 FETCH_ADVANCE_INST 2 168 GET_INST_OPCODE ip 169 GOTO_OPCODE ip 170 171%def op_iput_slow_path(volatile_store, wide, is_object): 172 mov x0, xSELF 173 ldr x1, [sp] 174 mov x2, xPC 175 .if $is_object 176 mov x3, x26 177 .else 178 mov x3, #0 179 .endif 180 EXPORT_PC 181 bl nterp_get_instance_field_offset 182 .if $is_object 183 // Reload the value as it may have moved. 184 ubfx w1, wINST, #8, #4 // w1<- A 185 GET_VREG w26, w1 // w26 <- v[A] 186 .endif 187 tbz w0, #31, .L${opcode}_resume 188 CLEAR_INSTANCE_VOLATILE_MARKER w0 189 lsr w2, wINST, #12 // w2<- B 190 GET_VREG w2, w2 // vB (object we're operating on) 191 cbz w2, common_errNullObject 192 add x3, x2, x0 193 .if $wide 194 $volatile_store x26, [x3] 195 .else 196 $volatile_store w26, [x3] 197 WRITE_BARRIER_IF_OBJECT $is_object, w26, w2, .L${opcode}_slow_path_skip_write_barrier 198 .endif 199 FETCH_ADVANCE_INST 2 200 GET_INST_OPCODE ip 201 GOTO_OPCODE ip 202 203%def op_iput_wide(): 204% op_iput(store="str", volatile_store="stlr", wide="1", is_object="0") 205 206%def op_iput_object(): 207% op_iput(store="str", volatile_store="stlr", wide="0", is_object="1") 208 209%def op_sget_boolean(): 210% op_sget(load="ldrb", volatile_load="ldarb", maybe_extend="", wide="0", is_object="0") 211 212%def op_sget_byte(): 213% op_sget(load="ldrsb", volatile_load="ldarb", maybe_extend="sxtb w0, w0", wide="0", is_object="0") 214 215%def op_sget_char(): 216% op_sget(load="ldrh", volatile_load="ldarh", maybe_extend="", wide="0", is_object="0") 217 218%def op_sget_short(): 219% op_sget(load="ldrsh", volatile_load="ldarh", maybe_extend="sxth w0, w0", wide="0", is_object="0") 220 221%def op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="0"): 222% slow_path = add_helper(lambda: op_sget_slow_path(volatile_load, maybe_extend, wide, is_object)) 223 // Fast-path which gets the field from thread-local cache. 224 FETCH_FROM_THREAD_CACHE x0, ${slow_path} 225.L${opcode}_resume: 226 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 227 lsr w2, wINST, #8 // w2 <- A 228 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 229 cbnz wMR, .L${opcode}_read_barrier 230.L${opcode}_resume_after_read_barrier: 231 .if $wide 232 ldr x0, [x0, x1] 233 SET_VREG_WIDE x0, w2 // fp[A] <- value 234 .elseif $is_object 235 $load w0, [x0, x1] 236 // No need to check the marking register, we know it's not set here. 237.L${opcode}_after_reference_load: 238 SET_VREG_OBJECT w0, w2 // fp[A] <- value 239 .else 240 $load w0, [x0, x1] 241 SET_VREG w0, w2 // fp[A] <- value 242 .endif 243 FETCH_ADVANCE_INST 2 244 GET_INST_OPCODE ip 245 GOTO_OPCODE ip 246.L${opcode}_read_barrier: 247 bl art_quick_read_barrier_mark_reg00 248 .if $is_object 249 $load w0, [x0, x1] 250.L${opcode}_mark_after_load: 251 // Here, we know the marking register is set. 252 bl art_quick_read_barrier_mark_reg00 253 b .L${opcode}_after_reference_load 254 .else 255 b .L${opcode}_resume_after_read_barrier 256 .endif 257 258%def op_sget_slow_path(volatile_load, maybe_extend, wide, is_object): 259 mov x0, xSELF 260 ldr x1, [sp] 261 mov x2, xPC 262 mov x3, #0 263 EXPORT_PC 264 bl nterp_get_static_field 265 tbz x0, #0, .L${opcode}_resume 266 CLEAR_STATIC_VOLATILE_MARKER x0 267 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 268 lsr w2, wINST, #8 // w2 <- A 269 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 270 cbnz wMR, .L${opcode}_slow_path_read_barrier 271.L${opcode}_slow_path_resume_after_read_barrier: 272 add x0, x0, x1 273 .if $wide 274 ldar x0, [x0] 275 SET_VREG_WIDE x0, w2 // fp[A] <- value 276 .elseif $is_object 277 $volatile_load w0, [x0] 278 cbnz wMR, .L${opcode}_mark_after_load 279 SET_VREG_OBJECT w0, w2 // fp[A] <- value 280 .else 281 $volatile_load w0, [x0] 282 $maybe_extend 283 SET_VREG w0, w2 // fp[A] <- value 284 .endif 285 FETCH_ADVANCE_INST 2 286 GET_INST_OPCODE ip 287 GOTO_OPCODE ip 288.L${opcode}_slow_path_read_barrier: 289 bl art_quick_read_barrier_mark_reg00 290 b .L${opcode}_slow_path_resume_after_read_barrier 291 292%def op_sget_wide(): 293% op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="1", is_object="0") 294 295%def op_sget_object(): 296% op_sget(load="ldr", volatile_load="ldar", maybe_extend="", wide="0", is_object="1") 297 298%def op_sput_boolean(): 299% op_sput(store="strb", volatile_store="stlrb", wide="0", is_object="0") 300 301%def op_sput_byte(): 302% op_sput(store="strb", volatile_store="stlrb", wide="0", is_object="0") 303 304%def op_sput_char(): 305% op_sput(store="strh", volatile_store="stlrh", wide="0", is_object="0") 306 307%def op_sput_short(): 308% op_sput(store="strh", volatile_store="stlrh", wide="0", is_object="0") 309 310%def op_sput(store="str", volatile_store="stlr", wide="0", is_object="0"): 311 // Share slow paths for boolean and byte (strb) and slow paths for char and short (strh). 312 // It does not matter to which `.L${opcode}_resume` the slow path returns. 313% slow_path = "nterp_op_sput_helper_" + store + wide + is_object 314% add_helper(lambda: op_sput_slow_path(volatile_store, wide, is_object), slow_path) 315 lsr w2, wINST, #8 // w2 <- A 316 .if $wide 317 GET_VREG_WIDE x26, w2 // x26 <- v[A] 318 .else 319 GET_VREG w26, w2 // w26 <- v[A] 320 .endif 321 // Fast-path which gets the field from thread-local cache. 322 FETCH_FROM_THREAD_CACHE x0, ${slow_path} 323.L${opcode}_resume: 324 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 325 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 326 cbnz wMR, .L${opcode}_read_barrier 327.L${opcode}_resume_after_read_barrier: 328 .if $wide 329 $store x26, [x0, x1] 330 .else 331 $store w26, [x0, x1] 332 WRITE_BARRIER_IF_OBJECT $is_object, w26, w0, .L${opcode}_skip_write_barrier 333 .endif 334 FETCH_ADVANCE_INST 2 335 GET_INST_OPCODE ip 336 GOTO_OPCODE ip 337.L${opcode}_read_barrier: 338 bl art_quick_read_barrier_mark_reg00 339 b .L${opcode}_resume_after_read_barrier 340 341%def op_sput_slow_path(volatile_store, wide, is_object): 342 mov x0, xSELF 343 ldr x1, [sp] 344 mov x2, xPC 345 .if $is_object 346 mov x3, x26 347 .else 348 mov x3, #0 349 .endif 350 EXPORT_PC 351 bl nterp_get_static_field 352 .if $is_object 353 // Reload the value as it may have moved. 354 lsr w2, wINST, #8 // w2 <- A 355 GET_VREG w26, w2 // w26 <- v[A] 356 .endif 357 tbz x0, #0, .L${opcode}_resume 358 CLEAR_STATIC_VOLATILE_MARKER x0 359 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 360 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 361 cbnz wMR, .L${opcode}_slow_path_read_barrier 362.L${opcode}_slow_path_resume_after_read_barrier: 363 add x1, x0, x1 364 .if $wide 365 $volatile_store x26, [x1] 366 .else 367 $volatile_store w26, [x1] 368 WRITE_BARRIER_IF_OBJECT $is_object, w26, w0, .L${opcode}_slow_path_skip_write_barrier 369 .endif 370 FETCH_ADVANCE_INST 2 371 GET_INST_OPCODE ip 372 GOTO_OPCODE ip 373.L${opcode}_slow_path_read_barrier: 374 bl art_quick_read_barrier_mark_reg00 375 b .L${opcode}_slow_path_resume_after_read_barrier 376 377%def op_sput_wide(): 378% op_sput(store="str", volatile_store="stlr", wide="1", is_object="0") 379 380%def op_sput_object(): 381% op_sput(store="str", volatile_store="stlr", wide="0", is_object="1") 382 383%def op_new_instance(): 384 EXPORT_PC 385 // Fast-path which gets the class from thread-local cache. 386 FETCH_FROM_THREAD_CACHE x0, 2f 387 cbnz wMR, 3f 3884: 389 ldr lr, [xSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET] 390 blr lr 3911: 392 lsr w1, wINST, #8 // w1 <- A 393 SET_VREG_OBJECT w0, w1 // fp[A] <- value 394 FETCH_ADVANCE_INST 2 395 GET_INST_OPCODE ip 396 GOTO_OPCODE ip 3972: 398 mov x0, xSELF 399 ldr x1, [sp] 400 mov x2, xPC 401 bl nterp_get_class_or_allocate_object 402 b 1b 4033: 404 bl art_quick_read_barrier_mark_reg00 405 b 4b 406