1*795d594fSAndroid Build Coastguard Worker// check-cast vAA, type@BBBB 2*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|1f BBBB 3*795d594fSAndroid Build Coastguard Worker// Throw a ClassCastException if the reference in the given register cannot be cast to the indicated 4*795d594fSAndroid Build Coastguard Worker// type. 5*795d594fSAndroid Build Coastguard Worker%def op_check_cast(): 6*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*expected klass*/a1, .L${opcode}_miss, t0, t1 7*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss_resume: 8*795d594fSAndroid Build Coastguard Worker 9*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 10*795d594fSAndroid Build Coastguard Worker% get_vreg("a0", "t0", is_unsigned=True) # a0 := fp[AA], zext 11*795d594fSAndroid Build Coastguard Worker beqz a0, .L${opcode}_next // null 12*795d594fSAndroid Build Coastguard Worker lwu a2, MIRROR_OBJECT_CLASS_OFFSET(a0) // a2 := actual klass 13*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a2 14*795d594fSAndroid Build Coastguard Worker // Fast path: compare without read barrier. 15*795d594fSAndroid Build Coastguard Worker bne a1, a2, .L${opcode}_slow 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker.L${opcode}_next: 18*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 19*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 20*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss: 23*795d594fSAndroid Build Coastguard Worker EXPORT_PC 24*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 25*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // caller ArtMethod* 26*795d594fSAndroid Build Coastguard Worker mv a2, xPC 27*795d594fSAndroid Build Coastguard Worker call nterp_get_class 28*795d594fSAndroid Build Coastguard Worker mv a1, a0 29*795d594fSAndroid Build Coastguard Worker j .L${opcode}_miss_resume 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 32*795d594fSAndroid Build Coastguard Worker // A0 and A1 in position for quick call. 33*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_check_cast_slow_path, "t0", "t1", "t2") 34*795d594fSAndroid Build Coastguard Worker tail $slow_path // slow offset exceeds branch imm 35*795d594fSAndroid Build Coastguard Worker // args a0, a1, a2 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker// Checks cases for (1) interface, (2) array, and (3) super classes. 39*795d594fSAndroid Build Coastguard Worker// Hardcoded: a0 (obj), a1 (expected klass), a2 (actual klass) 40*795d594fSAndroid Build Coastguard Worker// 41*795d594fSAndroid Build Coastguard Worker// Note. We don't do read barriers for simplicity. However, this means that fetched objects may be a 42*795d594fSAndroid Build Coastguard Worker// from-space reference. That's OK as we only fetch constant information from the references. This 43*795d594fSAndroid Build Coastguard Worker// also means that some of the comparisons below may lead to false negative due to stale data, so 44*795d594fSAndroid Build Coastguard Worker// all negative cases must pass through the runtime, via potential read barrier. 45*795d594fSAndroid Build Coastguard Worker%def op_check_cast_slow_path(z0, z1, z2): 46*795d594fSAndroid Build Coastguard Worker // Interface check: cut to runtime. 47*795d594fSAndroid Build Coastguard Worker lwu $z0, MIRROR_CLASS_ACCESS_FLAGS_OFFSET(a1) 48*795d594fSAndroid Build Coastguard Worker BRANCH_IF_BIT_SET $z0, $z0, MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, .L${opcode}_runtime 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker // Array check handled below. 51*795d594fSAndroid Build Coastguard Worker lwu $z0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(a1) 52*795d594fSAndroid Build Coastguard Worker // Defer z0 unpoison to array path. 53*795d594fSAndroid Build Coastguard Worker bnez $z0, .L${opcode}_array 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker // Super check: find expected class, else cut to runtime. 56*795d594fSAndroid Build Coastguard Worker.L${opcode}_super: 57*795d594fSAndroid Build Coastguard Worker lwu a2, MIRROR_CLASS_SUPER_CLASS_OFFSET(a2) 58*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a2 59*795d594fSAndroid Build Coastguard Worker beq a2, a1, .L${opcode}_slow_next 60*795d594fSAndroid Build Coastguard Worker bnez a2, .L${opcode}_super 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker.L${opcode}_runtime: 63*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z0, .L${opcode}_mark 64*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 65*795d594fSAndroid Build Coastguard Worker EXPORT_PC 66*795d594fSAndroid Build Coastguard Worker call art_quick_check_instance_of // args a0 (obj), a1 (expected klass) 67*795d594fSAndroid Build Coastguard Worker 68*795d594fSAndroid Build Coastguard Worker // Advancement logic replicated here for branch distance. 69*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_next: 70*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 71*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 72*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 73*795d594fSAndroid Build Coastguard Worker 74*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 75*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg11 // a1, expected klass 76*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker.L${opcode}_array: 79*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF $z0 // z0 = expected.component 80*795d594fSAndroid Build Coastguard Worker lwu $z1, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(a2) // z1 := actual.component 81*795d594fSAndroid Build Coastguard Worker beqz $z1, .L${opcode}_runtime // null: actual not an array 82*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF $z1 83*795d594fSAndroid Build Coastguard Worker lwu $z2, MIRROR_CLASS_SUPER_CLASS_OFFSET($z0) // z2 := expected.component.super 84*795d594fSAndroid Build Coastguard Worker // z2 can skip unpoison for null check 85*795d594fSAndroid Build Coastguard Worker bnez $z2, .L${opcode}_runtime // super type exists 86*795d594fSAndroid Build Coastguard Worker // expected.component.super is null: expected is either Object[] or primitive array. 87*795d594fSAndroid Build Coastguard Worker lhu $z2, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET($z0) // z2 := expected.component.primitive 88*795d594fSAndroid Build Coastguard Worker bnez $z2, .L${opcode}_runtime // expected's component is primitive 89*795d594fSAndroid Build Coastguard Worker lwu $z2, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET($z1) // z2 := actual.component.primitive 90*795d594fSAndroid Build Coastguard Worker bnez $z2, .L${opcode}_runtime // actual's component is primitive 91*795d594fSAndroid Build Coastguard Worker // Here, z0 is Object, and z1 is a subclass of Object. 92*795d594fSAndroid Build Coastguard Worker j .L${opcode}_slow_next 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker// instance-of vA, vB, type@CCCC 96*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|20 CCCC 97*795d594fSAndroid Build Coastguard Worker// vA := 1 if vB instance-of CCCC, else 0 98*795d594fSAndroid Build Coastguard Worker// Store in the given destination register 1 if the indicated reference is an instance of the given 99*795d594fSAndroid Build Coastguard Worker// type, or 0 if not. 100*795d594fSAndroid Build Coastguard Worker%def op_instance_of(): 101*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 8 // s7 := B|A 102*795d594fSAndroid Build Coastguard Worker srliw s8, xINST, 12 // s8 := B 103*795d594fSAndroid Build Coastguard Worker andi s7, s7, 0xF // s7 := A, used in slow path 104*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*expected klass*/ a1, .L${opcode}_miss, t0, t1 105*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss_resume: 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker% get_vreg("a0", "s8", is_unsigned=True) # a0 := fp[B], zext 108*795d594fSAndroid Build Coastguard Worker beqz a0, .L${opcode}_next // a0 = null = dst value "false" 109*795d594fSAndroid Build Coastguard Worker lwu a2, MIRROR_OBJECT_CLASS_OFFSET(a0) // a2 := actual klass 110*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a2 111*795d594fSAndroid Build Coastguard Worker // Fast path: compare without read barrier. 112*795d594fSAndroid Build Coastguard Worker bne a1, a2, .L${opcode}_slow 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker li a0, 1 // dst value "true" 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker.L${opcode}_next: 117*795d594fSAndroid Build Coastguard Worker% set_vreg("a0", "s7", z0="t1") # fp[A] := a0 118*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 119*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 120*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss: 123*795d594fSAndroid Build Coastguard Worker EXPORT_PC 124*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 125*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // caller ArtMethod* 126*795d594fSAndroid Build Coastguard Worker mv a2, xPC 127*795d594fSAndroid Build Coastguard Worker call nterp_get_class 128*795d594fSAndroid Build Coastguard Worker mv a1, a0 129*795d594fSAndroid Build Coastguard Worker j .L${opcode}_miss_resume 130*795d594fSAndroid Build Coastguard Worker 131*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 132*795d594fSAndroid Build Coastguard Worker // A0 and A1 in position for quick call. 133*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_instance_of_slow_path, "s7", "t0", "t1", "t2") 134*795d594fSAndroid Build Coastguard Worker tail $slow_path // slow offset exceeds branch imm 135*795d594fSAndroid Build Coastguard Worker // args a0, a1, a2 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Worker// Checks cases for (1) interface, (2) array, and (3) super classes. 139*795d594fSAndroid Build Coastguard Worker// Hardcoded: a0 (obj), a1 (expected klass), a2 (actual klass) 140*795d594fSAndroid Build Coastguard Worker// 141*795d594fSAndroid Build Coastguard Worker// Npte. If marking, don't bother with read barrier calls - cut to runtime. This arrangement allows 142*795d594fSAndroid Build Coastguard Worker// the (non marking) super class fast path's negative case to skip the read barrier and runtime 143*795d594fSAndroid Build Coastguard Worker// call, and correctly diagnose the situation with fp[A] := 0. 144*795d594fSAndroid Build Coastguard Worker%def op_instance_of_slow_path(vA, z0, z1, z2): 145*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z0, .L${opcode}_runtime_with_read_barrier 146*795d594fSAndroid Build Coastguard Worker 147*795d594fSAndroid Build Coastguard Worker // Interface check: cut to runtime. 148*795d594fSAndroid Build Coastguard Worker lwu $z0, MIRROR_CLASS_ACCESS_FLAGS_OFFSET(a1) 149*795d594fSAndroid Build Coastguard Worker BRANCH_IF_BIT_SET $z0, $z0, MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, .L${opcode}_runtime 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker // Array check handled below. 152*795d594fSAndroid Build Coastguard Worker lwu $z0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(a1) 153*795d594fSAndroid Build Coastguard Worker // Defer z0 unpoison to array path. 154*795d594fSAndroid Build Coastguard Worker bnez $z0, .L${opcode}_array 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker // Super check: find klass up the hierarchy. 157*795d594fSAndroid Build Coastguard Worker.L${opcode}_super: 158*795d594fSAndroid Build Coastguard Worker lwu a2, MIRROR_CLASS_SUPER_CLASS_OFFSET(a2) 159*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a2 160*795d594fSAndroid Build Coastguard Worker beq a2, a1, .L${opcode}_super_exit 161*795d594fSAndroid Build Coastguard Worker bnez a2, .L${opcode}_super 162*795d594fSAndroid Build Coastguard Worker.L${opcode}_super_exit: 163*795d594fSAndroid Build Coastguard Worker snez a0, a2 // a0 := 1 if (a1 = a2 != null), else 0 (because a2 = null) 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_next: 166*795d594fSAndroid Build Coastguard Worker% set_vreg("a0", vA, z0=z0) # fp[A] := a0 167*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 168*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 169*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker.L${opcode}_runtime_with_read_barrier: 172*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg11 // a1, expected klass 173*795d594fSAndroid Build Coastguard Worker.L${opcode}_runtime: 174*795d594fSAndroid Build Coastguard Worker EXPORT_PC 175*795d594fSAndroid Build Coastguard Worker call artInstanceOfFromCode // args a0 (obj), a1 (expected klass) 176*795d594fSAndroid Build Coastguard Worker // return a0: 1 if true, else 0 177*795d594fSAndroid Build Coastguard Worker j .L${opcode}_slow_next 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker.L${opcode}_array: 180*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF $z0 // z0 = expected.component 181*795d594fSAndroid Build Coastguard Worker lwu $z1, MIRROR_CLASS_SUPER_CLASS_OFFSET($z0) // z1 := expected.component.super 182*795d594fSAndroid Build Coastguard Worker // z1 can skip unpoison for null check 183*795d594fSAndroid Build Coastguard Worker bnez $z1, .L${opcode}_runtime // super type exists 184*795d594fSAndroid Build Coastguard Worker // Here, expected.component.super is null: expected is either Object[] or primitive array. 185*795d594fSAndroid Build Coastguard Worker lwu a0, MIRROR_CLASS_COMPONENT_TYPE_OFFSET(a2) // a0 := actual.component 186*795d594fSAndroid Build Coastguard Worker beqz a0, .L${opcode}_slow_next // actual not an array, a0 = null = dst value "false" 187*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 188*795d594fSAndroid Build Coastguard Worker lhu $z1, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET($z0) // z1 := expected.component.primitive 189*795d594fSAndroid Build Coastguard Worker lhu $z2, MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(a0) // z2 := actual.component.primitive 190*795d594fSAndroid Build Coastguard Worker or a0, $z1, $z2 // a0 := 0 if z1 = z2 = 0, else non-zero (Primitive::Type enum) 191*795d594fSAndroid Build Coastguard Worker seqz a0, a0 // a0 := 1 if both are class types, else 0 192*795d594fSAndroid Build Coastguard Worker // Here, when a0 = 1, expected.component is Object, and actual.component is a subclass of Object. 193*795d594fSAndroid Build Coastguard Worker j .L${opcode}_slow_next 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker 196*795d594fSAndroid Build Coastguard Worker// new-instance vAA, type@BBBB 197*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|22 BBBB 198*795d594fSAndroid Build Coastguard Worker// Construct a new instance of the indicated type, storing a reference to it in the destination. The 199*795d594fSAndroid Build Coastguard Worker// type must refer to a non-array class. 200*795d594fSAndroid Build Coastguard Worker%def op_new_instance(): 201*795d594fSAndroid Build Coastguard Worker EXPORT_PC 202*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 8 // s7 := AA 203*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved klass*/a0, .L${opcode}_miss, t0, t1 204*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t0, .L${opcode}_mark 205*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 206*795d594fSAndroid Build Coastguard Worker 207*795d594fSAndroid Build Coastguard Worker ld t0, THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET(xSELF) 208*795d594fSAndroid Build Coastguard Worker jalr t0 // arg a0 (klass) 209*795d594fSAndroid Build Coastguard Worker // return a0 := new-obj 210*795d594fSAndroid Build Coastguard Worker fence w, w // constructor fence; main.S has details 211*795d594fSAndroid Build Coastguard Worker 212*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss_resume: 213*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT a0, s7, z0=t0 // refs[AA] := new-obj 214*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 215*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 216*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 217*795d594fSAndroid Build Coastguard Worker 218*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 219*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, klass 220*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 221*795d594fSAndroid Build Coastguard Worker 222*795d594fSAndroid Build Coastguard Worker.L${opcode}_miss: 223*795d594fSAndroid Build Coastguard Worker EXPORT_PC 224*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 225*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // caller ArtMethod* 226*795d594fSAndroid Build Coastguard Worker mv a2, xPC 227*795d594fSAndroid Build Coastguard Worker call nterp_allocate_object 228*795d594fSAndroid Build Coastguard Worker // return a0 := new-obj, plus cache entry is updated with the resolved klass 229*795d594fSAndroid Build Coastguard Worker j .L${opcode}_miss_resume 230*795d594fSAndroid Build Coastguard Worker 231*795d594fSAndroid Build Coastguard Worker 232*795d594fSAndroid Build Coastguard Worker// *** iget *** 233*795d594fSAndroid Build Coastguard Worker 234*795d594fSAndroid Build Coastguard Worker%def load(dst, src, width, zext): 235*795d594fSAndroid Build Coastguard Worker% if width == 8 and zext: 236*795d594fSAndroid Build Coastguard Worker lbu $dst, ($src) 237*795d594fSAndroid Build Coastguard Worker% elif width == 8: 238*795d594fSAndroid Build Coastguard Worker lb $dst, ($src) 239*795d594fSAndroid Build Coastguard Worker% elif width == 16 and zext: 240*795d594fSAndroid Build Coastguard Worker lhu $dst, ($src) 241*795d594fSAndroid Build Coastguard Worker% elif width == 16: 242*795d594fSAndroid Build Coastguard Worker lh $dst, ($src) 243*795d594fSAndroid Build Coastguard Worker% elif width == 32: 244*795d594fSAndroid Build Coastguard Worker lw $dst, ($src) 245*795d594fSAndroid Build Coastguard Worker% elif width == 64: 246*795d594fSAndroid Build Coastguard Worker ld $dst, ($src) 247*795d594fSAndroid Build Coastguard Worker% else: 248*795d594fSAndroid Build Coastguard Worker% assert False, width 249*795d594fSAndroid Build Coastguard Worker%#: 250*795d594fSAndroid Build Coastguard Worker 251*795d594fSAndroid Build Coastguard Worker 252*795d594fSAndroid Build Coastguard Worker%def store(src, dst, width): 253*795d594fSAndroid Build Coastguard Worker% if width == 8: 254*795d594fSAndroid Build Coastguard Worker sb $src, ($dst) 255*795d594fSAndroid Build Coastguard Worker% elif width == 16: 256*795d594fSAndroid Build Coastguard Worker sh $src, ($dst) 257*795d594fSAndroid Build Coastguard Worker% elif width == 32: 258*795d594fSAndroid Build Coastguard Worker sw $src, ($dst) 259*795d594fSAndroid Build Coastguard Worker% elif width == 64: 260*795d594fSAndroid Build Coastguard Worker sd $src, ($dst) 261*795d594fSAndroid Build Coastguard Worker% else: 262*795d594fSAndroid Build Coastguard Worker% assert False, width 263*795d594fSAndroid Build Coastguard Worker%#: 264*795d594fSAndroid Build Coastguard Worker 265*795d594fSAndroid Build Coastguard Worker 266*795d594fSAndroid Build Coastguard Worker// iget vA, vB, field@CCCC 267*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|52 CCCC 268*795d594fSAndroid Build Coastguard Worker// vA := vB.field 269*795d594fSAndroid Build Coastguard Worker%def op_iget(width=32, zext=False): 270*795d594fSAndroid Build Coastguard Worker srliw s8, xINST, 8 271*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 12 // s7 := B 272*795d594fSAndroid Build Coastguard Worker andi s8, s8, 0xF // s8 := A 273*795d594fSAndroid Build Coastguard Worker 274*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetInstanceFieldOffset's byte offset from thread-local cache. 275*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*field_offset*/a0, .L${opcode}_slow, t1, t2 276*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "s7", is_unsigned=True) # t0 := holder 279*795d594fSAndroid Build Coastguard Worker beqz t0, .L${opcode}_null 280*795d594fSAndroid Build Coastguard Worker add t0, a0, t0 // t0 := field addr 281*795d594fSAndroid Build Coastguard Worker% load(dst="t1", src="t0", width=width, zext=zext) 282*795d594fSAndroid Build Coastguard Worker // t1 := value 283*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 284*795d594fSAndroid Build Coastguard Worker% set_vreg("t1", "s8", z0="t0", width=width) 285*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 286*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 287*795d594fSAndroid Build Coastguard Worker 288*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 289*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 290*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 291*795d594fSAndroid Build Coastguard Worker mv a2, xPC 292*795d594fSAndroid Build Coastguard Worker mv a3, zero 293*795d594fSAndroid Build Coastguard Worker EXPORT_PC 294*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset // result a0 := field_offset 295*795d594fSAndroid Build Coastguard Worker 296*795d594fSAndroid Build Coastguard Worker // Test for volatile (negative value). 297*795d594fSAndroid Build Coastguard Worker bgez a0, .L${opcode}_slow_resume 298*795d594fSAndroid Build Coastguard Worker% volatile_path = add_slow_path(op_iget_volatile, width, zext, "s7", "s8", "t0", "t1") 299*795d594fSAndroid Build Coastguard Worker tail $volatile_path 300*795d594fSAndroid Build Coastguard Worker 301*795d594fSAndroid Build Coastguard Worker.L${opcode}_null: 302*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 303*795d594fSAndroid Build Coastguard Worker 304*795d594fSAndroid Build Coastguard Worker 305*795d594fSAndroid Build Coastguard Worker%def op_iget_volatile(width, zext, holder, dst, z0, z1): 306*795d594fSAndroid Build Coastguard Worker% get_vreg(z0, holder, is_unsigned=True) # z0 := holder 307*795d594fSAndroid Build Coastguard Worker beqz $z0, .L${opcode}_volatile_null 308*795d594fSAndroid Build Coastguard Worker sub $z0, $z0, a0 // z0 := field addr (holder - (-offset)) 309*795d594fSAndroid Build Coastguard Worker // Atomic load: "fence rw,rw ; LOAD ; fence r,rw" 310*795d594fSAndroid Build Coastguard Worker fence rw, rw 311*795d594fSAndroid Build Coastguard Worker% load(dst=z1, src=z0, width=width, zext=zext) 312*795d594fSAndroid Build Coastguard Worker fence r, rw 313*795d594fSAndroid Build Coastguard Worker // t1 := value 314*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 315*795d594fSAndroid Build Coastguard Worker% set_vreg(z1, dst, z0=z0, width=width) 316*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 317*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 318*795d594fSAndroid Build Coastguard Worker 319*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_null: 320*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 321*795d594fSAndroid Build Coastguard Worker 322*795d594fSAndroid Build Coastguard Worker 323*795d594fSAndroid Build Coastguard Worker// iget-wide vA, vB, field@CCCC 324*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|53 CCCC 325*795d594fSAndroid Build Coastguard Worker%def op_iget_wide(): 326*795d594fSAndroid Build Coastguard Worker% op_iget(width=64) 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker 329*795d594fSAndroid Build Coastguard Worker// iget-object vA, vB, field@CCCC 330*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|54 CCCC 331*795d594fSAndroid Build Coastguard Worker%def op_iget_object(): 332*795d594fSAndroid Build Coastguard Worker srliw s8, xINST, 8 333*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 12 // s7 := B 334*795d594fSAndroid Build Coastguard Worker andi s8, s8, 0xF // s8 := A 335*795d594fSAndroid Build Coastguard Worker 336*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetInstanceFieldOffset's byte offset from thread-local cache. 337*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*field_offset*/a0, .L${opcode}_slow, t1, t2 338*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 339*795d594fSAndroid Build Coastguard Worker 340*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "s7", is_unsigned=True) # t0 := holder 341*795d594fSAndroid Build Coastguard Worker beqz t0, .L${opcode}_null 342*795d594fSAndroid Build Coastguard Worker add t0, a0, t0 // t0 := field addr 343*795d594fSAndroid Build Coastguard Worker lwu a0, (t0) // a0 := object 344*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 345*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t1, .L${opcode}_mark 346*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 347*795d594fSAndroid Build Coastguard Worker 348*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 349*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT a0, s8, z0=t0 350*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 351*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 352*795d594fSAndroid Build Coastguard Worker 353*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 354*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, object 355*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 356*795d594fSAndroid Build Coastguard Worker 357*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 358*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_iget_object_slow_path, "s7", "s8", "t0", "t1") 359*795d594fSAndroid Build Coastguard Worker tail $slow_path 360*795d594fSAndroid Build Coastguard Worker 361*795d594fSAndroid Build Coastguard Worker.L${opcode}_null: 362*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 363*795d594fSAndroid Build Coastguard Worker 364*795d594fSAndroid Build Coastguard Worker 365*795d594fSAndroid Build Coastguard Worker%def op_iget_object_slow_path(holder, dst, z0, z1): 366*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 367*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 368*795d594fSAndroid Build Coastguard Worker mv a2, xPC 369*795d594fSAndroid Build Coastguard Worker mv a3, zero 370*795d594fSAndroid Build Coastguard Worker EXPORT_PC 371*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset // result a0 := field_offset 372*795d594fSAndroid Build Coastguard Worker 373*795d594fSAndroid Build Coastguard Worker // Test for volatile (negative value). 374*795d594fSAndroid Build Coastguard Worker bltz a0, .L${opcode}_volatile 375*795d594fSAndroid Build Coastguard Worker tail .L${opcode}_slow_resume // resume offset exceeds branch imm 376*795d594fSAndroid Build Coastguard Worker 377*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile: 378*795d594fSAndroid Build Coastguard Worker% get_vreg(z0, holder, is_unsigned=True) # z0 := holder 379*795d594fSAndroid Build Coastguard Worker beqz $z0, .L${opcode}_volatile_null 380*795d594fSAndroid Build Coastguard Worker sub $z0, $z0, a0 // z0 := field addr (holder - (-offset)) 381*795d594fSAndroid Build Coastguard Worker // Atomic load: "fence rw,rw ; LOAD ; fence r,rw" 382*795d594fSAndroid Build Coastguard Worker fence rw, rw 383*795d594fSAndroid Build Coastguard Worker lwu a0, ($z0) // a0 := object 384*795d594fSAndroid Build Coastguard Worker fence r, rw 385*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 386*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t1, .L${opcode}_volatile_mark 387*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark_resume: 388*795d594fSAndroid Build Coastguard Worker 389*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 390*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT a0, $dst, z0=$z0 391*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 392*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 393*795d594fSAndroid Build Coastguard Worker 394*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark: 395*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, object 396*795d594fSAndroid Build Coastguard Worker j .L${opcode}_volatile_mark_resume 397*795d594fSAndroid Build Coastguard Worker 398*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_null: 399*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 400*795d594fSAndroid Build Coastguard Worker 401*795d594fSAndroid Build Coastguard Worker 402*795d594fSAndroid Build Coastguard Worker// iget-boolean vA, vB, field@CCCC 403*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|55 CCCC 404*795d594fSAndroid Build Coastguard Worker%def op_iget_boolean(): 405*795d594fSAndroid Build Coastguard Worker% op_iget(width=8, zext=True) 406*795d594fSAndroid Build Coastguard Worker 407*795d594fSAndroid Build Coastguard Worker 408*795d594fSAndroid Build Coastguard Worker// iget-byte vA, vB, field@CCCC 409*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|56 CCCC 410*795d594fSAndroid Build Coastguard Worker%def op_iget_byte(): 411*795d594fSAndroid Build Coastguard Worker% op_iget(width=8) 412*795d594fSAndroid Build Coastguard Worker 413*795d594fSAndroid Build Coastguard Worker 414*795d594fSAndroid Build Coastguard Worker// iget-char vA, vB, field@CCCC 415*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|57 CCCC 416*795d594fSAndroid Build Coastguard Worker%def op_iget_char(): 417*795d594fSAndroid Build Coastguard Worker% op_iget(width=16, zext=True) 418*795d594fSAndroid Build Coastguard Worker 419*795d594fSAndroid Build Coastguard Worker 420*795d594fSAndroid Build Coastguard Worker// iget-short vA, vB, field@CCCC 421*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|58 CCCC 422*795d594fSAndroid Build Coastguard Worker%def op_iget_short(): 423*795d594fSAndroid Build Coastguard Worker% op_iget(width=16) 424*795d594fSAndroid Build Coastguard Worker 425*795d594fSAndroid Build Coastguard Worker 426*795d594fSAndroid Build Coastguard Worker// *** iput *** 427*795d594fSAndroid Build Coastguard Worker 428*795d594fSAndroid Build Coastguard Worker// iput vA, vB, field@CCCC 429*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|59 CCCC 430*795d594fSAndroid Build Coastguard Worker// vB.field := vA 431*795d594fSAndroid Build Coastguard Worker%def op_iput(width=32): 432*795d594fSAndroid Build Coastguard Worker srliw s8, xINST, 8 433*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 12 // s7 := B 434*795d594fSAndroid Build Coastguard Worker andi s8, s8, 0xF // s8 := A 435*795d594fSAndroid Build Coastguard Worker% get_vreg("s8", "s8", width=width) 436*795d594fSAndroid Build Coastguard Worker // s8 := value, held across slow path call 437*795d594fSAndroid Build Coastguard Worker 438*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetInstanceFieldOffset's byte offset from thread-local cache. 439*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 440*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 441*795d594fSAndroid Build Coastguard Worker 442*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "s7", is_unsigned=True) # t0 := holder 443*795d594fSAndroid Build Coastguard Worker beqz t0, .L${opcode}_null 444*795d594fSAndroid Build Coastguard Worker add t0, a0, t0 // t0 := field addr 445*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 446*795d594fSAndroid Build Coastguard Worker% store(src="s8", dst="t0", width=width) 447*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 448*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 449*795d594fSAndroid Build Coastguard Worker 450*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 451*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 452*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 453*795d594fSAndroid Build Coastguard Worker mv a2, xPC 454*795d594fSAndroid Build Coastguard Worker mv a3, zero 455*795d594fSAndroid Build Coastguard Worker EXPORT_PC 456*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset // result a0 := field_offset 457*795d594fSAndroid Build Coastguard Worker 458*795d594fSAndroid Build Coastguard Worker // Test for volatile (negative value). 459*795d594fSAndroid Build Coastguard Worker bgez a0, .L${opcode}_slow_resume 460*795d594fSAndroid Build Coastguard Worker% volatile_path = add_slow_path(op_iput_volatile, width, "s7", "s8", "t0", "t1") 461*795d594fSAndroid Build Coastguard Worker tail $volatile_path 462*795d594fSAndroid Build Coastguard Worker 463*795d594fSAndroid Build Coastguard Worker.L${opcode}_null: 464*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 465*795d594fSAndroid Build Coastguard Worker 466*795d594fSAndroid Build Coastguard Worker 467*795d594fSAndroid Build Coastguard Worker%def op_iput_volatile(width, holder, value, z0, z1): 468*795d594fSAndroid Build Coastguard Worker% get_vreg(z0, holder, is_unsigned=True) # z0 := holder 469*795d594fSAndroid Build Coastguard Worker beqz $z0, .L${opcode}_volatile_null 470*795d594fSAndroid Build Coastguard Worker sub $z0, $z0, a0 // z0 := field addr (holder - (-offset)) 471*795d594fSAndroid Build Coastguard Worker // Ensure the volatile store is released. 472*795d594fSAndroid Build Coastguard Worker% if width == 8: 473*795d594fSAndroid Build Coastguard Worker fence rw, w 474*795d594fSAndroid Build Coastguard Worker sb $value, ($z0) 475*795d594fSAndroid Build Coastguard Worker fence rw, rw 476*795d594fSAndroid Build Coastguard Worker% elif width == 16: 477*795d594fSAndroid Build Coastguard Worker fence rw, w 478*795d594fSAndroid Build Coastguard Worker sh $value, ($z0) 479*795d594fSAndroid Build Coastguard Worker fence rw, rw 480*795d594fSAndroid Build Coastguard Worker% elif width == 32: 481*795d594fSAndroid Build Coastguard Worker amoswap.w.rl zero, $value, ($z0) 482*795d594fSAndroid Build Coastguard Worker% elif width == 64: 483*795d594fSAndroid Build Coastguard Worker amoswap.d.rl zero, $value, ($z0) 484*795d594fSAndroid Build Coastguard Worker% else: 485*795d594fSAndroid Build Coastguard Worker% assert False, width 486*795d594fSAndroid Build Coastguard Worker%#: 487*795d594fSAndroid Build Coastguard Worker 488*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 489*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 490*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 491*795d594fSAndroid Build Coastguard Worker 492*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_null: 493*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 494*795d594fSAndroid Build Coastguard Worker 495*795d594fSAndroid Build Coastguard Worker 496*795d594fSAndroid Build Coastguard Worker// iput-wide vA, vB, field@CCCC 497*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5a CCCC 498*795d594fSAndroid Build Coastguard Worker%def op_iput_wide(): 499*795d594fSAndroid Build Coastguard Worker% op_iput(width=64) 500*795d594fSAndroid Build Coastguard Worker 501*795d594fSAndroid Build Coastguard Worker 502*795d594fSAndroid Build Coastguard Worker// iput-object vA, vB, field@CCCC 503*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5b CCCC 504*795d594fSAndroid Build Coastguard Worker%def op_iput_object(): 505*795d594fSAndroid Build Coastguard Worker srliw s8, xINST, 8 506*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 12 // s7 := B 507*795d594fSAndroid Build Coastguard Worker andi s8, s8, 0xF // s8 := A 508*795d594fSAndroid Build Coastguard Worker% get_vreg("s9", "s8", is_unsigned=True) # s9 := reference 509*795d594fSAndroid Build Coastguard Worker 510*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetInstanceFieldOffset's byte offset from thread-local cache. 511*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 512*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: // s9 := reference (slow path only) 513*795d594fSAndroid Build Coastguard Worker 514*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "s7", is_unsigned=True) # t0 := holder 515*795d594fSAndroid Build Coastguard Worker beqz t0, .L${opcode}_null 516*795d594fSAndroid Build Coastguard Worker add t1, a0, t0 // t1 := field addr 517*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF s9 // Poisoning maps null to null for the null check in write barrier. 518*795d594fSAndroid Build Coastguard Worker sw s9, (t1) 519*795d594fSAndroid Build Coastguard Worker% object_write_barrier(value="s9", holder="t0", z0="t1", z1="t2", uniq=f"{opcode}") 520*795d594fSAndroid Build Coastguard Worker 521*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 522*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 523*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 524*795d594fSAndroid Build Coastguard Worker 525*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 526*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_iput_object_slow_path, "s7", "s8", "s9", "t0", "t1", "t2") 527*795d594fSAndroid Build Coastguard Worker tail $slow_path 528*795d594fSAndroid Build Coastguard Worker 529*795d594fSAndroid Build Coastguard Worker.L${opcode}_null: 530*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 531*795d594fSAndroid Build Coastguard Worker 532*795d594fSAndroid Build Coastguard Worker 533*795d594fSAndroid Build Coastguard Worker%def op_iput_object_slow_path(holder, src, value, z0, z1, z2): 534*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 535*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 536*795d594fSAndroid Build Coastguard Worker mv a2, xPC 537*795d594fSAndroid Build Coastguard Worker mv a3, $value 538*795d594fSAndroid Build Coastguard Worker EXPORT_PC 539*795d594fSAndroid Build Coastguard Worker call nterp_get_instance_field_offset // result a0 := field_offset 540*795d594fSAndroid Build Coastguard Worker 541*795d594fSAndroid Build Coastguard Worker // Reload value, object may have moved. 542*795d594fSAndroid Build Coastguard Worker% get_vreg(value, src, is_unsigned=True) # value := fp[A] zext 543*795d594fSAndroid Build Coastguard Worker 544*795d594fSAndroid Build Coastguard Worker // Test for volatile (negative value). 545*795d594fSAndroid Build Coastguard Worker bltz a0, .L${opcode}_volatile 546*795d594fSAndroid Build Coastguard Worker tail .L${opcode}_slow_resume // resume offset exceeds branch imm 547*795d594fSAndroid Build Coastguard Worker 548*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile: 549*795d594fSAndroid Build Coastguard Worker% get_vreg(z0, holder, is_unsigned=True) # z0 := holder 550*795d594fSAndroid Build Coastguard Worker beqz $z0, .L${opcode}_volatile_null 551*795d594fSAndroid Build Coastguard Worker sub $z1, $z0, a0 // z1 := field addr (holder - (-offset)) 552*795d594fSAndroid Build Coastguard Worker // Ensure the volatile store is released. 553*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF $value // Poisoning maps null to null for the null check in write barrier. 554*795d594fSAndroid Build Coastguard Worker amoswap.w.rl zero, $value, ($z1) 555*795d594fSAndroid Build Coastguard Worker% object_write_barrier(value=value, holder=z0, z0=z1, z1=z2, uniq=f"slow_{opcode}") 556*795d594fSAndroid Build Coastguard Worker 557*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 558*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 559*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 560*795d594fSAndroid Build Coastguard Worker 561*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_null: 562*795d594fSAndroid Build Coastguard Worker tail common_errNullObject 563*795d594fSAndroid Build Coastguard Worker 564*795d594fSAndroid Build Coastguard Worker 565*795d594fSAndroid Build Coastguard Worker// iput-boolean vA, vB, field@CCCC 566*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5c CCCC 567*795d594fSAndroid Build Coastguard Worker%def op_iput_boolean(): 568*795d594fSAndroid Build Coastguard Worker% op_iput(width=8) 569*795d594fSAndroid Build Coastguard Worker 570*795d594fSAndroid Build Coastguard Worker 571*795d594fSAndroid Build Coastguard Worker// iput-byte vA, vB, field@CCCC 572*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5d CCCC 573*795d594fSAndroid Build Coastguard Worker%def op_iput_byte(): 574*795d594fSAndroid Build Coastguard Worker% op_iput(width=8) 575*795d594fSAndroid Build Coastguard Worker 576*795d594fSAndroid Build Coastguard Worker 577*795d594fSAndroid Build Coastguard Worker// iput-char vA, vB, field@CCCC 578*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5e CCCC 579*795d594fSAndroid Build Coastguard Worker%def op_iput_char(): 580*795d594fSAndroid Build Coastguard Worker% op_iput(width=16) 581*795d594fSAndroid Build Coastguard Worker 582*795d594fSAndroid Build Coastguard Worker 583*795d594fSAndroid Build Coastguard Worker// iput-short vA, vB, field@CCCC 584*795d594fSAndroid Build Coastguard Worker// Format 22c: B|A|5f CCCC 585*795d594fSAndroid Build Coastguard Worker%def op_iput_short(): 586*795d594fSAndroid Build Coastguard Worker% op_iput(width=16) 587*795d594fSAndroid Build Coastguard Worker 588*795d594fSAndroid Build Coastguard Worker 589*795d594fSAndroid Build Coastguard Worker// *** sget *** 590*795d594fSAndroid Build Coastguard Worker 591*795d594fSAndroid Build Coastguard Worker.macro CLEAR_STATIC_VOLATILE_MARKER reg 592*795d594fSAndroid Build Coastguard Worker andi \reg, \reg, ~0x1 593*795d594fSAndroid Build Coastguard Worker.endm 594*795d594fSAndroid Build Coastguard Worker 595*795d594fSAndroid Build Coastguard Worker// sget vAA, field@BBBB 596*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|60 BBBB 597*795d594fSAndroid Build Coastguard Worker// vAA := klass.field 598*795d594fSAndroid Build Coastguard Worker%def op_sget(width=32, zext=False): 599*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 8 // s7 := AA (live through volatile path) 600*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetStaticField's resolved_field from thread-local cache. 601*795d594fSAndroid Build Coastguard Worker // Stores cache value in a0 to match slow path's return from NterpGetStaticField. 602*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 603*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 604*795d594fSAndroid Build Coastguard Worker 605*795d594fSAndroid Build Coastguard Worker lwu t0, ART_FIELD_OFFSET_OFFSET(a0) // t0 := field offset 606*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 607*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t2, .L${opcode}_mark 608*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 609*795d594fSAndroid Build Coastguard Worker 610*795d594fSAndroid Build Coastguard Worker add t0, t0, a0 // t0 := field addr, after possible a0 update 611*795d594fSAndroid Build Coastguard Worker% load(dst="t1", src="t0", width=width, zext=zext) 612*795d594fSAndroid Build Coastguard Worker // t1 := value 613*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 614*795d594fSAndroid Build Coastguard Worker% set_vreg("t1", "s7", z0="t0", width=width) 615*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 616*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 617*795d594fSAndroid Build Coastguard Worker 618*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 619*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 620*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 621*795d594fSAndroid Build Coastguard Worker 622*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 623*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 624*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 625*795d594fSAndroid Build Coastguard Worker mv a2, xPC 626*795d594fSAndroid Build Coastguard Worker mv a3, zero 627*795d594fSAndroid Build Coastguard Worker EXPORT_PC 628*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field // result a0 := resolved_field 629*795d594fSAndroid Build Coastguard Worker 630*795d594fSAndroid Build Coastguard Worker // Test for volatile bit 631*795d594fSAndroid Build Coastguard Worker slli t0, a0, 63 632*795d594fSAndroid Build Coastguard Worker bgez t0, .L${opcode}_slow_resume 633*795d594fSAndroid Build Coastguard Worker% volatile_path = add_slow_path(op_sget_volatile, width, zext, "s7", "t0", "t1") 634*795d594fSAndroid Build Coastguard Worker tail $volatile_path 635*795d594fSAndroid Build Coastguard Worker 636*795d594fSAndroid Build Coastguard Worker 637*795d594fSAndroid Build Coastguard Worker// Volatile static load. 638*795d594fSAndroid Build Coastguard Worker// Temporaries: z0, z1, z2 639*795d594fSAndroid Build Coastguard Worker%def op_sget_volatile(width, zext, dst_vreg, z0, z1): 640*795d594fSAndroid Build Coastguard Worker CLEAR_STATIC_VOLATILE_MARKER a0 641*795d594fSAndroid Build Coastguard Worker lwu $z0, ART_FIELD_OFFSET_OFFSET(a0) // z0 := field offset 642*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 643*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z1, .L${opcode}_volatile_mark 644*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark_resume: 645*795d594fSAndroid Build Coastguard Worker 646*795d594fSAndroid Build Coastguard Worker add $z0, $z0, a0 // z0 := field addr, after possible a0 update 647*795d594fSAndroid Build Coastguard Worker // Atomic load: "fence rw,rw ; LOAD ; fence r,rw" 648*795d594fSAndroid Build Coastguard Worker fence rw, rw 649*795d594fSAndroid Build Coastguard Worker% load(dst=z1, src=z0, width=width, zext=zext) 650*795d594fSAndroid Build Coastguard Worker fence r, rw 651*795d594fSAndroid Build Coastguard Worker // z1 := value 652*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 653*795d594fSAndroid Build Coastguard Worker% set_vreg(z1, dst_vreg, z0=z0, width=width) 654*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 655*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 656*795d594fSAndroid Build Coastguard Worker 657*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark: 658*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 659*795d594fSAndroid Build Coastguard Worker j .L${opcode}_volatile_mark_resume 660*795d594fSAndroid Build Coastguard Worker 661*795d594fSAndroid Build Coastguard Worker 662*795d594fSAndroid Build Coastguard Worker// sget-wide vAA, field@BBBB 663*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|61 BBBB 664*795d594fSAndroid Build Coastguard Worker%def op_sget_wide(): 665*795d594fSAndroid Build Coastguard Worker% op_sget(width=64) 666*795d594fSAndroid Build Coastguard Worker 667*795d594fSAndroid Build Coastguard Worker 668*795d594fSAndroid Build Coastguard Worker// sget-object vAA, field@BBBB 669*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|62 BBBB 670*795d594fSAndroid Build Coastguard Worker// Variant for object load contains extra logic for GC mark. 671*795d594fSAndroid Build Coastguard Worker%def op_sget_object(): 672*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 8 // s7 := AA (live through volatile path) 673*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetStaticField's resolved_field from thread-local cache. 674*795d594fSAndroid Build Coastguard Worker // Stores cache value in a0 to match slow path's return from NterpGetStaticField. 675*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 676*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 677*795d594fSAndroid Build Coastguard Worker 678*795d594fSAndroid Build Coastguard Worker lwu t0, ART_FIELD_OFFSET_OFFSET(a0) // t0 := field offset 679*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 680*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t1, .L${opcode}_mark 681*795d594fSAndroid Build Coastguard Worker 682*795d594fSAndroid Build Coastguard Worker add t0, t0, a0 // t0 := field addr 683*795d594fSAndroid Build Coastguard Worker lwu a0, (t0) // a0 := value (ref) 684*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 685*795d594fSAndroid Build Coastguard Worker 686*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 687*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 688*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT a0, s7, z0=t0 689*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 690*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 691*795d594fSAndroid Build Coastguard Worker 692*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 693*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 694*795d594fSAndroid Build Coastguard Worker add t0, t0, a0 // t0 := field addr, after a0 update 695*795d594fSAndroid Build Coastguard Worker lwu a0, (t0) // a0 := value (ref) 696*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 697*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, object 698*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 699*795d594fSAndroid Build Coastguard Worker 700*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 701*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_sget_object_slow_path, "s7", "t0", "t1") 702*795d594fSAndroid Build Coastguard Worker tail $slow_path 703*795d594fSAndroid Build Coastguard Worker 704*795d594fSAndroid Build Coastguard Worker 705*795d594fSAndroid Build Coastguard Worker// Static load, object variant. Contains both slow path and volatile path 706*795d594fSAndroid Build Coastguard Worker// due to handler size limitation in op_sget_object. 707*795d594fSAndroid Build Coastguard Worker// Hardcoded: a0, a1, a2, a3, xSELF, xPC, xINST, xFP, xREFS 708*795d594fSAndroid Build Coastguard Worker// Temporaries: z0, z1 709*795d594fSAndroid Build Coastguard Worker%def op_sget_object_slow_path(dst_vreg, z0, z1): 710*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 711*795d594fSAndroid Build Coastguard Worker ld a1, (sp) // a1 := caller ArtMethod* 712*795d594fSAndroid Build Coastguard Worker mv a2, xPC 713*795d594fSAndroid Build Coastguard Worker mv a3, zero 714*795d594fSAndroid Build Coastguard Worker EXPORT_PC 715*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field // result a0 := resolved_field 716*795d594fSAndroid Build Coastguard Worker 717*795d594fSAndroid Build Coastguard Worker // Test for volatile bit 718*795d594fSAndroid Build Coastguard Worker slli $z0, a0, 63 719*795d594fSAndroid Build Coastguard Worker bltz $z0, .L${opcode}_volatile 720*795d594fSAndroid Build Coastguard Worker tail .L${opcode}_slow_resume // resume offset exceeds branch imm 721*795d594fSAndroid Build Coastguard Worker 722*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile: 723*795d594fSAndroid Build Coastguard Worker CLEAR_STATIC_VOLATILE_MARKER a0 724*795d594fSAndroid Build Coastguard Worker lwu $z0, ART_FIELD_OFFSET_OFFSET(a0) // z0 := field offset 725*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 726*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z1, .L${opcode}_volatile_mark 727*795d594fSAndroid Build Coastguard Worker 728*795d594fSAndroid Build Coastguard Worker add $z0, $z0, a0 // z0 := field addr 729*795d594fSAndroid Build Coastguard Worker fence rw, rw 730*795d594fSAndroid Build Coastguard Worker lwu a0, ($z0) // Atomic ref load: "fence rw,rw, ; LOAD ; fence r,rw" 731*795d594fSAndroid Build Coastguard Worker fence r, rw 732*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 733*795d594fSAndroid Build Coastguard Worker 734*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark_resume: 735*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 736*795d594fSAndroid Build Coastguard Worker SET_VREG_OBJECT a0, $dst_vreg, z0=$z0 737*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 738*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 739*795d594fSAndroid Build Coastguard Worker 740*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark: 741*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 742*795d594fSAndroid Build Coastguard Worker add $z0, $z0, a0 // z0 := field addr, after a0 update 743*795d594fSAndroid Build Coastguard Worker fence rw, rw 744*795d594fSAndroid Build Coastguard Worker lwu a0, ($z0) // Atomic ref load: "fence rw,rw, ; LOAD ; fence r,rw" 745*795d594fSAndroid Build Coastguard Worker fence r, rw 746*795d594fSAndroid Build Coastguard Worker UNPOISON_HEAP_REF a0 747*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, object 748*795d594fSAndroid Build Coastguard Worker j .L${opcode}_volatile_mark_resume 749*795d594fSAndroid Build Coastguard Worker 750*795d594fSAndroid Build Coastguard Worker 751*795d594fSAndroid Build Coastguard Worker// sget-boolean vAA, field@BBBB 752*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|63 BBBB 753*795d594fSAndroid Build Coastguard Worker%def op_sget_boolean(): 754*795d594fSAndroid Build Coastguard Worker% op_sget(width=8, zext=True) 755*795d594fSAndroid Build Coastguard Worker 756*795d594fSAndroid Build Coastguard Worker 757*795d594fSAndroid Build Coastguard Worker// sget-byte vAA, field@BBBB 758*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|64 BBBB 759*795d594fSAndroid Build Coastguard Worker%def op_sget_byte(): 760*795d594fSAndroid Build Coastguard Worker% op_sget(width=8) 761*795d594fSAndroid Build Coastguard Worker 762*795d594fSAndroid Build Coastguard Worker 763*795d594fSAndroid Build Coastguard Worker// sget-char vAA, field@BBBB 764*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|65 BBBB 765*795d594fSAndroid Build Coastguard Worker%def op_sget_char(): 766*795d594fSAndroid Build Coastguard Worker% op_sget(width=16, zext=True) 767*795d594fSAndroid Build Coastguard Worker 768*795d594fSAndroid Build Coastguard Worker 769*795d594fSAndroid Build Coastguard Worker// sget-short vAA, field@BBBB 770*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|66 BBBB 771*795d594fSAndroid Build Coastguard Worker%def op_sget_short(): 772*795d594fSAndroid Build Coastguard Worker% op_sget(width=16) 773*795d594fSAndroid Build Coastguard Worker 774*795d594fSAndroid Build Coastguard Worker 775*795d594fSAndroid Build Coastguard Worker// *** sput *** 776*795d594fSAndroid Build Coastguard Worker 777*795d594fSAndroid Build Coastguard Worker// sput vAA, field@BBBB 778*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|67 BBBB 779*795d594fSAndroid Build Coastguard Worker// klass.field := vAA 780*795d594fSAndroid Build Coastguard Worker%def op_sput(width=32): 781*795d594fSAndroid Build Coastguard Worker srliw t2, xINST, 8 // t2 := AA 782*795d594fSAndroid Build Coastguard Worker% get_vreg("s7", "t2", width=width) 783*795d594fSAndroid Build Coastguard Worker // s7 := value, held across slow path call 784*795d594fSAndroid Build Coastguard Worker 785*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetStaticField's resolved_field from thread-local cache. 786*795d594fSAndroid Build Coastguard Worker // Stores cache value in a0 to match slow path's return from NterpGetStaticField. 787*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 788*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: 789*795d594fSAndroid Build Coastguard Worker 790*795d594fSAndroid Build Coastguard Worker lwu t0, ART_FIELD_OFFSET_OFFSET(a0) 791*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 792*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t1, .L${opcode}_mark 793*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 794*795d594fSAndroid Build Coastguard Worker 795*795d594fSAndroid Build Coastguard Worker add t0, t0, a0 // t0 := field addr, after possible a0 update 796*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 797*795d594fSAndroid Build Coastguard Worker% store(src="s7", dst="t0", width=width) 798*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 799*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 800*795d594fSAndroid Build Coastguard Worker 801*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 802*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 803*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 804*795d594fSAndroid Build Coastguard Worker 805*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 806*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 807*795d594fSAndroid Build Coastguard Worker ld a1, (sp) 808*795d594fSAndroid Build Coastguard Worker mv a2, xPC 809*795d594fSAndroid Build Coastguard Worker mv a3, zero 810*795d594fSAndroid Build Coastguard Worker EXPORT_PC 811*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field // result a0 := resolved_field 812*795d594fSAndroid Build Coastguard Worker 813*795d594fSAndroid Build Coastguard Worker // Test for volatile bit 814*795d594fSAndroid Build Coastguard Worker slli t0, a0, 63 815*795d594fSAndroid Build Coastguard Worker bgez t0, .L${opcode}_slow_resume 816*795d594fSAndroid Build Coastguard Worker% volatile_path = add_slow_path(op_sput_volatile, width, "s7", "t0", "t1") 817*795d594fSAndroid Build Coastguard Worker tail $volatile_path 818*795d594fSAndroid Build Coastguard Worker 819*795d594fSAndroid Build Coastguard Worker 820*795d594fSAndroid Build Coastguard Worker// Volatile static store. 821*795d594fSAndroid Build Coastguard Worker// Temporaries: z0, z1 822*795d594fSAndroid Build Coastguard Worker%def op_sput_volatile(width, value, z0, z1): 823*795d594fSAndroid Build Coastguard Worker CLEAR_STATIC_VOLATILE_MARKER a0 824*795d594fSAndroid Build Coastguard Worker lwu $z0, ART_FIELD_OFFSET_OFFSET(a0) // z0 := field offset 825*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 826*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z1, .L${opcode}_volatile_mark 827*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark_resume: 828*795d594fSAndroid Build Coastguard Worker 829*795d594fSAndroid Build Coastguard Worker add $z0, $z0, a0 // z0 := field addr, after possible a0 update 830*795d594fSAndroid Build Coastguard Worker // Ensure the volatile store is released. 831*795d594fSAndroid Build Coastguard Worker% if width == 8: 832*795d594fSAndroid Build Coastguard Worker fence rw, w 833*795d594fSAndroid Build Coastguard Worker sb $value, ($z0) 834*795d594fSAndroid Build Coastguard Worker fence rw, rw 835*795d594fSAndroid Build Coastguard Worker% elif width == 16: 836*795d594fSAndroid Build Coastguard Worker fence rw, w 837*795d594fSAndroid Build Coastguard Worker sh $value, ($z0) 838*795d594fSAndroid Build Coastguard Worker fence rw, rw 839*795d594fSAndroid Build Coastguard Worker% elif width == 32: 840*795d594fSAndroid Build Coastguard Worker amoswap.w.rl zero, $value, ($z0) 841*795d594fSAndroid Build Coastguard Worker% elif width == 64: 842*795d594fSAndroid Build Coastguard Worker amoswap.d.rl zero, $value, ($z0) 843*795d594fSAndroid Build Coastguard Worker% else: 844*795d594fSAndroid Build Coastguard Worker% assert False, width 845*795d594fSAndroid Build Coastguard Worker%#: 846*795d594fSAndroid Build Coastguard Worker 847*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 848*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 849*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 850*795d594fSAndroid Build Coastguard Worker 851*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark: 852*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 853*795d594fSAndroid Build Coastguard Worker j .L${opcode}_volatile_mark_resume 854*795d594fSAndroid Build Coastguard Worker 855*795d594fSAndroid Build Coastguard Worker 856*795d594fSAndroid Build Coastguard Worker// sput-wide vAA, field@BBBB 857*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|68 BBBB 858*795d594fSAndroid Build Coastguard Worker%def op_sput_wide(): 859*795d594fSAndroid Build Coastguard Worker% op_sput(width=64) 860*795d594fSAndroid Build Coastguard Worker 861*795d594fSAndroid Build Coastguard Worker 862*795d594fSAndroid Build Coastguard Worker// sput-object vAA, field@BBBB 863*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|69 BBBB 864*795d594fSAndroid Build Coastguard Worker%def op_sput_object(): 865*795d594fSAndroid Build Coastguard Worker srliw s7, xINST, 8 // s7 := AA (live through slow path) 866*795d594fSAndroid Build Coastguard Worker% get_vreg("s8", "s7", is_unsigned=True) # s8 := reference, replaced in slow path 867*795d594fSAndroid Build Coastguard Worker 868*795d594fSAndroid Build Coastguard Worker // Fast path: NterpGetStaticField's resolved_field from thread-local cache. 869*795d594fSAndroid Build Coastguard Worker // Stores cache value in a0 to match slow path's return from NterpGetStaticField. 870*795d594fSAndroid Build Coastguard Worker FETCH_FROM_THREAD_CACHE /*resolved_field*/a0, .L${opcode}_slow, t0, t1 871*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow_resume: // s8 := reference (slow path only) 872*795d594fSAndroid Build Coastguard Worker 873*795d594fSAndroid Build Coastguard Worker lwu t0, ART_FIELD_OFFSET_OFFSET(a0) 874*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 875*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING t1, .L${opcode}_mark 876*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark_resume: 877*795d594fSAndroid Build Coastguard Worker 878*795d594fSAndroid Build Coastguard Worker add t0, t0, a0 // t0 := field addr, after possible a0 update 879*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF s8 // Poisoning maps null to null for the null check in write barrier. 880*795d594fSAndroid Build Coastguard Worker sw s8, (t0) // store reference 881*795d594fSAndroid Build Coastguard Worker% object_write_barrier(value="s8", holder="a0", z0="t0", z1="t1", uniq=f"{opcode}") 882*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 883*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 884*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 885*795d594fSAndroid Build Coastguard Worker 886*795d594fSAndroid Build Coastguard Worker.L${opcode}_mark: 887*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 888*795d594fSAndroid Build Coastguard Worker j .L${opcode}_mark_resume 889*795d594fSAndroid Build Coastguard Worker 890*795d594fSAndroid Build Coastguard Worker.L${opcode}_slow: 891*795d594fSAndroid Build Coastguard Worker% slow_path = add_slow_path(op_sput_object_slow_path, "s7", "s8", "t0", "t1") 892*795d594fSAndroid Build Coastguard Worker tail $slow_path // slow path offset exceeds regular branch imm in FETCH_FROM_THREAD_CACHE 893*795d594fSAndroid Build Coastguard Worker 894*795d594fSAndroid Build Coastguard Worker 895*795d594fSAndroid Build Coastguard Worker// Static store, object variant. Contains both slow path and volatile path 896*795d594fSAndroid Build Coastguard Worker// due to handler size limitation in op_sput_object. 897*795d594fSAndroid Build Coastguard Worker// Hardcoded: a0, a1, a2, a3, xSELF, xPC, xINST, xFP, xREFS 898*795d594fSAndroid Build Coastguard Worker// Temporaries z0, z1 899*795d594fSAndroid Build Coastguard Worker%def op_sput_object_slow_path(src_vreg, value, z0, z1): 900*795d594fSAndroid Build Coastguard Worker // Args for nterp_get_static_field 901*795d594fSAndroid Build Coastguard Worker mv a0, xSELF 902*795d594fSAndroid Build Coastguard Worker ld a1, (sp) 903*795d594fSAndroid Build Coastguard Worker mv a2, xPC 904*795d594fSAndroid Build Coastguard Worker mv a3, $value 905*795d594fSAndroid Build Coastguard Worker EXPORT_PC 906*795d594fSAndroid Build Coastguard Worker call nterp_get_static_field // result a0 := resolved_field 907*795d594fSAndroid Build Coastguard Worker 908*795d594fSAndroid Build Coastguard Worker // Reload value, it may have moved. 909*795d594fSAndroid Build Coastguard Worker% get_vreg(value, src_vreg, is_unsigned=True) # value := fp[AA], zext 910*795d594fSAndroid Build Coastguard Worker 911*795d594fSAndroid Build Coastguard Worker // Test for volatile bit 912*795d594fSAndroid Build Coastguard Worker slli $z0, a0, 63 913*795d594fSAndroid Build Coastguard Worker bltz $z0, .L${opcode}_volatile 914*795d594fSAndroid Build Coastguard Worker tail .L${opcode}_slow_resume // resume offset exceeds branch imm 915*795d594fSAndroid Build Coastguard Worker 916*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile: 917*795d594fSAndroid Build Coastguard Worker CLEAR_STATIC_VOLATILE_MARKER a0 918*795d594fSAndroid Build Coastguard Worker lwu $z0, ART_FIELD_OFFSET_OFFSET(a0) // z0 := field offset 919*795d594fSAndroid Build Coastguard Worker lwu a0, ART_FIELD_DECLARING_CLASS_OFFSET(a0) // a0 := holder 920*795d594fSAndroid Build Coastguard Worker TEST_IF_MARKING $z1, .L${opcode}_volatile_mark 921*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark_resume: 922*795d594fSAndroid Build Coastguard Worker 923*795d594fSAndroid Build Coastguard Worker add $z0, $z0, a0 // z0 := field addr, after possible a0 update 924*795d594fSAndroid Build Coastguard Worker // Ensure the volatile store is released. 925*795d594fSAndroid Build Coastguard Worker // \value must NOT be the destination register, the destination gets clobbered! 926*795d594fSAndroid Build Coastguard Worker // \value's original value is used in the write barrier below. 927*795d594fSAndroid Build Coastguard Worker POISON_HEAP_REF $value // Poisoning maps null to null for the null check in write barrier. 928*795d594fSAndroid Build Coastguard Worker amoswap.w.rl zero, $value, ($z0) 929*795d594fSAndroid Build Coastguard Worker% object_write_barrier(value=value, holder="a0", z0=z0, z1=z1, uniq=f"slow_{opcode}") 930*795d594fSAndroid Build Coastguard Worker 931*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 932*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE $z0 933*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE $z0 934*795d594fSAndroid Build Coastguard Worker 935*795d594fSAndroid Build Coastguard Worker.L${opcode}_volatile_mark: 936*795d594fSAndroid Build Coastguard Worker call art_quick_read_barrier_mark_reg10 // a0, holder 937*795d594fSAndroid Build Coastguard Worker j .L${opcode}_volatile_mark_resume 938*795d594fSAndroid Build Coastguard Worker 939*795d594fSAndroid Build Coastguard Worker 940*795d594fSAndroid Build Coastguard Worker%def object_write_barrier(value, holder, z0, z1, uniq): 941*795d594fSAndroid Build Coastguard Worker beqz $value, .L${uniq}_skip_write_barrier // No object, skip out. 942*795d594fSAndroid Build Coastguard Worker ld $z0, THREAD_CARD_TABLE_OFFSET(xSELF) 943*795d594fSAndroid Build Coastguard Worker srli $z1, $holder, CARD_TABLE_CARD_SHIFT 944*795d594fSAndroid Build Coastguard Worker add $z1, $z0, $z1 945*795d594fSAndroid Build Coastguard Worker sb $z0, ($z1) 946*795d594fSAndroid Build Coastguard Worker.L${uniq}_skip_write_barrier: 947*795d594fSAndroid Build Coastguard Worker 948*795d594fSAndroid Build Coastguard Worker 949*795d594fSAndroid Build Coastguard Worker// sput-object vAA, field@BBBB 950*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|6a BBBB 951*795d594fSAndroid Build Coastguard Worker%def op_sput_boolean(): 952*795d594fSAndroid Build Coastguard Worker% op_sput(width=8) 953*795d594fSAndroid Build Coastguard Worker 954*795d594fSAndroid Build Coastguard Worker 955*795d594fSAndroid Build Coastguard Worker// sput-object vAA, field@BBBB 956*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|6b BBBB 957*795d594fSAndroid Build Coastguard Worker%def op_sput_byte(): 958*795d594fSAndroid Build Coastguard Worker% op_sput(width=8) 959*795d594fSAndroid Build Coastguard Worker 960*795d594fSAndroid Build Coastguard Worker 961*795d594fSAndroid Build Coastguard Worker// sput-object vAA, field@BBBB 962*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|6c BBBB 963*795d594fSAndroid Build Coastguard Worker%def op_sput_char(): 964*795d594fSAndroid Build Coastguard Worker% op_sput(width=16) 965*795d594fSAndroid Build Coastguard Worker 966*795d594fSAndroid Build Coastguard Worker 967*795d594fSAndroid Build Coastguard Worker// sput-object vAA, field@BBBB 968*795d594fSAndroid Build Coastguard Worker// Format 21c: AA|6d BBBB 969*795d594fSAndroid Build Coastguard Worker%def op_sput_short(): 970*795d594fSAndroid Build Coastguard Worker% op_sput(width=16) 971*795d594fSAndroid Build Coastguard Worker 972