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