1%def const(helper="UndefinedConstHandler"):
2    /* const/class vAA, type@BBBB */
3    /* const/method-handle vAA, method_handle@BBBB */
4    /* const/method-type vAA, proto@BBBB */
5    /* const/string vAA, string@@BBBB */
6    .extern $helper
7    EXPORT_PC
8    FETCH w0, 1                         // w0<- BBBB
9    lsr     w1, wINST, #8               // w1<- AA
10    add     x2, xFP, #OFF_FP_SHADOWFRAME
11    mov     x3, xSELF
12    bl      $helper                     // (index, tgt_reg, shadow_frame, self)
13    PREFETCH_INST 2                     // load rINST
14    cbnz    w0, MterpPossibleException  // let reference interpreter deal with it.
15    ADVANCE 2                           // advance rPC
16    GET_INST_OPCODE ip                  // extract opcode from rINST
17    GOTO_OPCODE ip                      // jump to next instruction
18
19%def unused():
20/*
21 * Bail to reference interpreter to throw.
22 */
23  b MterpFallback
24
25%def op_const():
26    /* const vAA, #+BBBBbbbb */
27    lsr     w3, wINST, #8               // w3<- AA
28    FETCH w0, 1                         // w0<- bbbb (low
29    FETCH w1, 2                         // w1<- BBBB (high
30    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
31    orr     w0, w0, w1, lsl #16         // w0<- BBBBbbbb
32    GET_INST_OPCODE ip                  // extract opcode from wINST
33    SET_VREG w0, w3                     // vAA<- w0
34    GOTO_OPCODE ip                      // jump to next instruction
35
36%def op_const_16():
37    /* const/16 vAA, #+BBBB */
38    FETCH_S w0, 1                       // w0<- ssssBBBB (sign-extended)
39    lsr     w3, wINST, #8               // w3<- AA
40    FETCH_ADVANCE_INST 2                // advance xPC, load wINST
41    SET_VREG w0, w3                     // vAA<- w0
42    GET_INST_OPCODE ip                  // extract opcode from wINST
43    GOTO_OPCODE ip                      // jump to next instruction
44
45%def op_const_4():
46    /* const/4 vA, #+B */
47    sbfx    w1, wINST, #12, #4          // w1<- sssssssB
48    ubfx    w0, wINST, #8, #4           // w0<- A
49    FETCH_ADVANCE_INST 1                // advance xPC, load wINST
50    GET_INST_OPCODE ip                  // ip<- opcode from xINST
51    SET_VREG w1, w0                     // fp[A]<- w1
52    GOTO_OPCODE ip                      // execute next instruction
53
54%def op_const_class():
55%  const(helper="MterpConstClass")
56
57%def op_const_high16():
58    /* const/high16 vAA, #+BBBB0000 */
59    FETCH   w0, 1                       // r0<- 0000BBBB (zero-extended)
60    lsr     w3, wINST, #8               // r3<- AA
61    lsl     w0, w0, #16                 // r0<- BBBB0000
62    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
63    SET_VREG w0, w3                     // vAA<- r0
64    GET_INST_OPCODE ip                  // extract opcode from rINST
65    GOTO_OPCODE ip                      // jump to next instruction
66
67%def op_const_method_handle():
68%  const(helper="MterpConstMethodHandle")
69
70%def op_const_method_type():
71%  const(helper="MterpConstMethodType")
72
73%def op_const_string():
74%  const(helper="MterpConstString")
75
76%def op_const_string_jumbo():
77    /* const/string vAA, String//BBBBBBBB */
78    EXPORT_PC
79    FETCH w0, 1                         // w0<- bbbb (low
80    FETCH w2, 2                         // w2<- BBBB (high
81    lsr     w1, wINST, #8               // w1<- AA
82    orr     w0, w0, w2, lsl #16         // w1<- BBBBbbbb
83    add     x2, xFP, #OFF_FP_SHADOWFRAME
84    mov     x3, xSELF
85    bl      MterpConstString            // (index, tgt_reg, shadow_frame, self)
86    PREFETCH_INST 3                     // advance rPC
87    cbnz    w0, MterpPossibleException      // let reference interpreter deal with it.
88    ADVANCE 3                           // advance rPC
89    GET_INST_OPCODE ip                  // extract opcode from rINST
90    GOTO_OPCODE ip                      // jump to next instruction
91
92%def op_const_wide():
93    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
94    FETCH w0, 1                         // w0<- bbbb (low)
95    FETCH w1, 2                         // w1<- BBBB (low middle)
96    FETCH w2, 3                         // w2<- hhhh (high middle)
97    FETCH w3, 4                         // w3<- HHHH (high)
98    lsr     w4, wINST, #8               // r4<- AA
99    FETCH_ADVANCE_INST 5                // advance rPC, load wINST
100    GET_INST_OPCODE ip                  // extract opcode from wINST
101    orr     w0, w0, w1, lsl #16         // w0<-         BBBBbbbb
102    orr     x0, x0, x2, lsl #32         // w0<-     hhhhBBBBbbbb
103    orr     x0, x0, x3, lsl #48         // w0<- HHHHhhhhBBBBbbbb
104    SET_VREG_WIDE x0, w4
105    GOTO_OPCODE ip                      // jump to next instruction
106
107%def op_const_wide_16():
108    /* const-wide/16 vAA, #+BBBB */
109    FETCH_S x0, 1                       // x0<- ssssssssssssBBBB (sign-extended)
110    lsr     w3, wINST, #8               // w3<- AA
111    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
112    GET_INST_OPCODE ip                  // extract opcode from rINST
113    SET_VREG_WIDE x0, w3
114    GOTO_OPCODE ip                      // jump to next instruction
115
116%def op_const_wide_32():
117    /* const-wide/32 vAA, #+BBBBbbbb */
118    FETCH   w0, 1                       // x0<- 000000000000bbbb (low)
119    lsr     w3, wINST, #8               // w3<- AA
120    FETCH_S x2, 2                       // x2<- ssssssssssssBBBB (high)
121    FETCH_ADVANCE_INST 3                // advance rPC, load wINST
122    GET_INST_OPCODE ip                  // extract opcode from wINST
123    orr     x0, x0, x2, lsl #16         // x0<- ssssssssBBBBbbbb
124    SET_VREG_WIDE x0, w3
125    GOTO_OPCODE ip                      // jump to next instruction
126
127%def op_const_wide_high16():
128    /* const-wide/high16 vAA, #+BBBB000000000000 */
129    FETCH w0, 1                         // w0<- 0000BBBB (zero-extended)
130    lsr     w1, wINST, #8               // w1<- AA
131    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
132    lsl     x0, x0, #48
133    SET_VREG_WIDE x0, w1
134    GET_INST_OPCODE ip                  // extract opcode from wINST
135    GOTO_OPCODE ip                      // jump to next instruction
136
137%def op_monitor_enter():
138    /*
139     * Synchronize on an object.
140     */
141    /* monitor-enter vAA */
142    EXPORT_PC
143    lsr      w2, wINST, #8               // w2<- AA
144    GET_VREG w0, w2                      // w0<- vAA (object)
145    mov      x1, xSELF                   // w1<- self
146    bl       artLockObjectFromCode
147    cbnz     w0, MterpException
148    FETCH_ADVANCE_INST 1
149    ldr      w0, [xSELF, #THREAD_USE_MTERP_OFFSET]
150    cbz      w0, MterpFallback
151    GET_INST_OPCODE ip                   // extract opcode from rINST
152    GOTO_OPCODE ip                       // jump to next instruction
153
154%def op_monitor_exit():
155    /*
156     * Unlock an object.
157     *
158     * Exceptions that occur when unlocking a monitor need to appear as
159     * if they happened at the following instruction.  See the Dalvik
160     * instruction spec.
161     */
162    /* monitor-exit vAA */
163    EXPORT_PC
164    lsr      w2, wINST, #8              // w2<- AA
165    GET_VREG w0, w2                     // w0<- vAA (object)
166    mov      x1, xSELF                  // w0<- self
167    bl       artUnlockObjectFromCode    // w0<- success for unlock(self, obj)
168    cbnz     w0, MterpException
169    FETCH_ADVANCE_INST 1                // before throw: advance rPC, load rINST
170    ldr      w0, [xSELF, #THREAD_USE_MTERP_OFFSET]
171    cbz      w0, MterpFallback
172    GET_INST_OPCODE ip                  // extract opcode from rINST
173    GOTO_OPCODE ip                      // jump to next instruction
174
175%def op_move(is_object="0"):
176    /* for move, move-object, long-to-int */
177    /* op vA, vB */
178    lsr     w1, wINST, #12              // x1<- B from 15:12
179    ubfx    w0, wINST, #8, #4           // x0<- A from 11:8
180    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
181    GET_VREG w2, w1                     // x2<- fp[B]
182    GET_INST_OPCODE ip                  // ip<- opcode from wINST
183    .if $is_object
184    SET_VREG_OBJECT w2, w0              // fp[A]<- x2
185    .else
186    SET_VREG w2, w0                     // fp[A]<- x2
187    .endif
188    GOTO_OPCODE ip                      // execute next instruction
189
190%def op_move_16(is_object="0"):
191    /* for: move/16, move-object/16 */
192    /* op vAAAA, vBBBB */
193    FETCH w1, 2                         // w1<- BBBB
194    FETCH w0, 1                         // w0<- AAAA
195    FETCH_ADVANCE_INST 3                // advance xPC, load xINST
196    GET_VREG w2, w1                     // w2<- fp[BBBB]
197    GET_INST_OPCODE ip                  // extract opcode from xINST
198    .if $is_object
199    SET_VREG_OBJECT w2, w0              // fp[AAAA]<- w2
200    .else
201    SET_VREG w2, w0                     // fp[AAAA]<- w2
202    .endif
203    GOTO_OPCODE ip                      // jump to next instruction
204
205%def op_move_exception():
206    /* move-exception vAA */
207    lsr     w2, wINST, #8               // w2<- AA
208    ldr     x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
209    mov     x1, #0                      // w1<- 0
210    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
211    SET_VREG_OBJECT w3, w2              // fp[AA]<- exception obj
212    GET_INST_OPCODE ip                  // extract opcode from rINST
213    str     x1, [xSELF, #THREAD_EXCEPTION_OFFSET]  // clear exception
214    GOTO_OPCODE ip                      // jump to next instruction
215
216%def op_move_from16(is_object="0"):
217    /* for: move/from16, move-object/from16 */
218    /* op vAA, vBBBB */
219    FETCH w1, 1                         // r1<- BBBB
220    lsr     w0, wINST, #8               // r0<- AA
221    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
222    GET_VREG w2, w1                     // r2<- fp[BBBB]
223    GET_INST_OPCODE ip                  // extract opcode from wINST
224    .if $is_object
225    SET_VREG_OBJECT w2, w0              // fp[AA]<- r2
226    .else
227    SET_VREG w2, w0                     // fp[AA]<- r2
228    .endif
229    GOTO_OPCODE ip                      // jump to next instruction
230
231%def op_move_object():
232%  op_move(is_object="1")
233
234%def op_move_object_16():
235%  op_move_16(is_object="1")
236
237%def op_move_object_from16():
238%  op_move_from16(is_object="1")
239
240%def op_move_result(is_object="0"):
241    /* for: move-result, move-result-object */
242    /* op vAA */
243    lsr     w2, wINST, #8               // r2<- AA
244    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
245    ldr     x0, [xFP, #OFF_FP_RESULT_REGISTER]  // get pointer to result JType.
246    ldr     w0, [x0]                    // r0 <- result.i.
247    GET_INST_OPCODE ip                  // extract opcode from wINST
248    .if $is_object
249    SET_VREG_OBJECT w0, w2, w1          // fp[AA]<- r0
250    .else
251    SET_VREG w0, w2                     // fp[AA]<- r0
252    .endif
253    GOTO_OPCODE ip                      // jump to next instruction
254
255%def op_move_result_object():
256%  op_move_result(is_object="1")
257
258%def op_move_result_wide():
259    /* for: move-result-wide */
260    /* op vAA */
261    lsr     w2, wINST, #8               // r2<- AA
262    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
263    ldr     x0, [xFP, #OFF_FP_RESULT_REGISTER]  // get pointer to result JType.
264    ldr     x0, [x0]                    // r0 <- result.i.
265    GET_INST_OPCODE ip                  // extract opcode from wINST
266    SET_VREG_WIDE x0, w2                // fp[AA]<- r0
267    GOTO_OPCODE ip                      // jump to next instruction
268
269%def op_move_wide():
270    /* move-wide vA, vB */
271    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
272    lsr     w3, wINST, #12              // w3<- B
273    ubfx    w2, wINST, #8, #4           // w2<- A
274    GET_VREG_WIDE  x3, w3
275    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
276    GET_INST_OPCODE ip                  // extract opcode from wINST
277    SET_VREG_WIDE  x3, w2
278    GOTO_OPCODE ip                      // jump to next instruction
279
280%def op_move_wide_16():
281    /* move-wide/16 vAAAA, vBBBB */
282    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
283    FETCH w3, 2                         // w3<- BBBB
284    FETCH w2, 1                         // w2<- AAAA
285    GET_VREG_WIDE x3, w3
286    FETCH_ADVANCE_INST 3                // advance rPC, load rINST
287    SET_VREG_WIDE x3, w2
288    GET_INST_OPCODE ip                  // extract opcode from rINST
289    GOTO_OPCODE ip                      // jump to next instruction
290
291%def op_move_wide_from16():
292    /* move-wide/from16 vAA, vBBBB */
293    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
294    FETCH w3, 1                         // w3<- BBBB
295    lsr     w2, wINST, #8               // w2<- AA
296    GET_VREG_WIDE x3, w3
297    FETCH_ADVANCE_INST 2                // advance rPC, load wINST
298    GET_INST_OPCODE ip                  // extract opcode from wINST
299    SET_VREG_WIDE x3, w2
300    GOTO_OPCODE ip                      // jump to next instruction
301
302%def op_nop():
303    FETCH_ADVANCE_INST 1                // advance to next instr, load rINST
304    GET_INST_OPCODE ip                  // ip<- opcode from rINST
305    GOTO_OPCODE ip                      // execute it
306
307%def op_unused_3e():
308%  unused()
309
310%def op_unused_3f():
311%  unused()
312
313%def op_unused_40():
314%  unused()
315
316%def op_unused_41():
317%  unused()
318
319%def op_unused_42():
320%  unused()
321
322%def op_unused_43():
323%  unused()
324
325%def op_unused_73():
326%  unused()
327
328%def op_unused_79():
329%  unused()
330
331%def op_unused_7a():
332%  unused()
333
334%def op_unused_f3():
335%  unused()
336
337%def op_unused_f4():
338%  unused()
339
340%def op_unused_f5():
341%  unused()
342
343%def op_unused_f6():
344%  unused()
345
346%def op_unused_f7():
347%  unused()
348
349%def op_unused_f8():
350%  unused()
351
352%def op_unused_f9():
353%  unused()
354
355%def op_unused_fc():
356%  unused()
357
358%def op_unused_fd():
359%  unused()
360