xref: /aosp_15_r20/art/runtime/interpreter/mterp/riscv64/object.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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