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_byte():
91%  op_iget(load="ldrsb", helper="MterpIGetI8")
92
93%def op_iget_char():
94%  op_iget(load="ldrh", helper="MterpIGetU16")
95
96%def op_iget_object():
97%  op_iget(is_object=True, helper="MterpIGetObj")
98
99%def op_iget_short():
100%  op_iget(load="ldrsh", helper="MterpIGetI16")
101
102%def op_iget_wide():
103%  op_iget(is_wide=True, helper="MterpIGetU64")
104
105%def op_instance_of():
106    /*
107     * Check to see if an object reference is an instance of a class.
108     *
109     * Most common situation is a non-null object, being compared against
110     * an already-resolved class.
111     */
112    /* instance-of vA, vB, class@CCCC */
113    EXPORT_PC
114    FETCH     r0, 1                     @ r0<- CCCC
115    mov       r1, rINST, lsr #12        @ r1<- B
116    VREG_INDEX_TO_ADDR r1, r1           @ r1<- &object
117    ldr       r2, [rFP, #OFF_FP_METHOD] @ r2<- method
118    mov       r3, rSELF                 @ r3<- self
119    bl        MterpInstanceOf           @ (index, &obj, method, self)
120    ldr       r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
121    ubfx      r9, rINST, #8, #4         @ r9<- A
122    PREFETCH_INST 2
123    cmp       r1, #0                    @ exception pending?
124    bne       MterpException
125    ADVANCE 2                           @ advance rPC
126    SET_VREG r0, r9                     @ vA<- r0
127    GET_INST_OPCODE ip                  @ extract opcode from rINST
128    GOTO_OPCODE ip                      @ jump to next instruction
129
130%def op_iput(helper="MterpIPutU32"):
131%  field(helper=helper)
132
133%def op_iput_boolean():
134%  op_iput(helper="MterpIPutU8")
135
136%def op_iput_byte():
137%  op_iput(helper="MterpIPutI8")
138
139%def op_iput_char():
140%  op_iput(helper="MterpIPutU16")
141
142%def op_iput_object():
143%  op_iput(helper="MterpIPutObj")
144
145%def op_iput_short():
146%  op_iput(helper="MterpIPutI16")
147
148%def op_iput_wide():
149%  op_iput(helper="MterpIPutU64")
150
151%def op_new_instance():
152    /*
153     * Create a new instance of a class.
154     */
155    /* new-instance vAA, class@BBBB */
156    EXPORT_PC
157    add     r0, rFP, #OFF_FP_SHADOWFRAME
158    mov     r1, rSELF
159    mov     r2, rINST
160    bl      MterpNewInstance           @ (shadow_frame, self, inst_data)
161    cmp     r0, #0
162    beq     MterpPossibleException
163    FETCH_ADVANCE_INST 2               @ advance rPC, load rINST
164    GET_INST_OPCODE ip                 @ extract opcode from rINST
165    GOTO_OPCODE ip                     @ jump to next instruction
166
167%def op_sget(helper="MterpSGetU32"):
168%  field(helper=helper)
169
170%def op_sget_boolean():
171%  op_sget(helper="MterpSGetU8")
172
173%def op_sget_byte():
174%  op_sget(helper="MterpSGetI8")
175
176%def op_sget_char():
177%  op_sget(helper="MterpSGetU16")
178
179%def op_sget_object():
180%  op_sget(helper="MterpSGetObj")
181
182%def op_sget_short():
183%  op_sget(helper="MterpSGetI16")
184
185%def op_sget_wide():
186%  op_sget(helper="MterpSGetU64")
187
188%def op_sput(helper="MterpSPutU32"):
189%  field(helper=helper)
190
191%def op_sput_boolean():
192%  op_sput(helper="MterpSPutU8")
193
194%def op_sput_byte():
195%  op_sput(helper="MterpSPutI8")
196
197%def op_sput_char():
198%  op_sput(helper="MterpSPutU16")
199
200%def op_sput_object():
201%  op_sput(helper="MterpSPutObj")
202
203%def op_sput_short():
204%  op_sput(helper="MterpSPutI16")
205
206%def op_sput_wide():
207%  op_sput(helper="MterpSPutU64")
208