1%def field(helper=""):
2    /*
3     * General field read / write (iget-* iput-* sget-* sput-*).
4     */
5    .extern $helper
6    REFRESH_INST ${opnum}                      # fix rINST to include opcode
7    movq    rPC, OUT_ARG0                      # arg0: Instruction* inst
8    movl    rINST, OUT_32_ARG1                 # arg1: uint16_t inst_data
9    leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG2  # arg2: ShadowFrame* sf
10    movq    rSELF, OUT_ARG3                    # arg3: Thread* self
11    call    SYMBOL($helper)
12    testb   %al, %al
13    jz      MterpPossibleException
14    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
15
16%def op_check_cast():
17/*
18 * Check to see if a cast from one class to another is allowed.
19 */
20    /* check-cast vAA, class@BBBB */
21    EXPORT_PC
22    movzwq  2(rPC), OUT_ARG0                # OUT_ARG0 <- BBBB
23    leaq    VREG_ADDRESS(rINSTq), OUT_ARG1
24    movq    OFF_FP_METHOD(rFP), OUT_ARG2
25    movq    rSELF, OUT_ARG3
26    call    SYMBOL(MterpCheckCast)          # (index, &obj, method, self)
27    testb   %al, %al
28    jnz     MterpPossibleException
29    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
30
31%def op_iget(is_object="0", helper="MterpIGetU32"):
32%  field(helper=helper)
33
34%def op_iget_boolean():
35%  op_iget(helper="MterpIGetU8")
36
37%def op_iget_boolean_quick():
38%  op_iget_quick(load="movsbl")
39
40%def op_iget_byte():
41%  op_iget(helper="MterpIGetI8")
42
43%def op_iget_byte_quick():
44%  op_iget_quick(load="movsbl")
45
46%def op_iget_char():
47%  op_iget(helper="MterpIGetU16")
48
49%def op_iget_char_quick():
50%  op_iget_quick(load="movzwl")
51
52%def op_iget_object():
53%  op_iget(is_object="1", helper="MterpIGetObj")
54
55%def op_iget_object_quick():
56    /* For: iget-object-quick */
57    /* op vA, vB, offset@CCCC */
58    .extern artIGetObjectFromMterp
59    movzbq  rINSTbl, %rcx                   # rcx <- BA
60    sarl    $$4, %ecx                       # ecx <- B
61    GET_VREG OUT_32_ARG0, %rcx              # vB (object we're operating on)
62    movzwl  2(rPC), OUT_32_ARG1             # eax <- field byte offset
63    EXPORT_PC
64    callq   SYMBOL(artIGetObjectFromMterp)  # (obj, offset)
65    movq    rSELF, %rcx
66    cmpq    $$0, THREAD_EXCEPTION_OFFSET(%rcx)
67    jnz     MterpException                  # bail out
68    andb    $$0xf, rINSTbl                  # rINST <- A
69    SET_VREG_OBJECT %eax, rINSTq            # fp[A] <- value
70    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
71
72%def op_iget_quick(load="movl", wide="0"):
73    /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
74    /* op vA, vB, offset@CCCC */
75    movl    rINST, %ecx                     # rcx <- BA
76    sarl    $$4, %ecx                       # ecx <- B
77    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
78    movzwq  2(rPC), %rax                    # eax <- field byte offset
79    testl   %ecx, %ecx                      # is object null?
80    je      common_errNullObject
81    andb    $$0xf,rINSTbl                   # rINST <- A
82    .if $wide
83    movq (%rcx,%rax,1), %rax
84    SET_WIDE_VREG %rax, rINSTq              # fp[A] <- value
85    .else
86    ${load} (%rcx,%rax,1), %eax
87    SET_VREG %eax, rINSTq                   # fp[A] <- value
88    .endif
89    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
90
91%def op_iget_short():
92%  op_iget(helper="MterpIGetI16")
93
94%def op_iget_short_quick():
95%  op_iget_quick(load="movswl")
96
97%def op_iget_wide():
98%  op_iget(helper="MterpIGetU64")
99
100%def op_iget_wide_quick():
101%  op_iget_quick(load="movswl", wide="1")
102
103%def op_instance_of():
104/*
105 * Check to see if an object reference is an instance of a class.
106 *
107 * Most common situation is a non-null object, being compared against
108 * an already-resolved class.
109 */
110    /* instance-of vA, vB, class@CCCC */
111    EXPORT_PC
112    movzwl  2(rPC), OUT_32_ARG0             # OUT_32_ARG0 <- CCCC
113    movl    rINST, %eax                     # eax <- BA
114    sarl    $$4, %eax                       # eax <- B
115    leaq    VREG_ADDRESS(%rax), OUT_ARG1    # Get object address
116    movq    OFF_FP_METHOD(rFP), OUT_ARG2
117    movq    rSELF, OUT_ARG3
118    call    SYMBOL(MterpInstanceOf)         # (index, &obj, method, self)
119    movsbl  %al, %eax
120    movq    rSELF, %rcx
121    cmpq    $$0, THREAD_EXCEPTION_OFFSET(%rcx)
122    jnz     MterpException
123    andb    $$0xf, rINSTbl                  # rINSTbl <- A
124    SET_VREG %eax, rINSTq
125    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
126
127%def op_iput(is_object="0", helper="MterpIPutU32"):
128%  field(helper=helper)
129
130%def op_iput_boolean():
131%  op_iput(helper="MterpIPutU8")
132
133%def op_iput_boolean_quick():
134%  op_iput_quick(reg="rINSTbl", store="movb")
135
136%def op_iput_byte():
137%  op_iput(helper="MterpIPutI8")
138
139%def op_iput_byte_quick():
140%  op_iput_quick(reg="rINSTbl", store="movb")
141
142%def op_iput_char():
143%  op_iput(helper="MterpIPutU16")
144
145%def op_iput_char_quick():
146%  op_iput_quick(reg="rINSTw", store="movw")
147
148%def op_iput_object():
149%  op_iput(is_object="1", helper="MterpIPutObj")
150
151%def op_iput_object_quick():
152    EXPORT_PC
153    leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
154    movq    rPC, OUT_ARG1
155    REFRESH_INST ${opnum}
156    movl    rINST, OUT_32_ARG2
157    call    SYMBOL(MterpIputObjectQuick)
158    testb   %al, %al
159    jz      MterpException
160    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
161
162%def op_iput_quick(reg="rINST", store="movl"):
163    /* For: iput-quick, iput-object-quick */
164    /* op vA, vB, offset@CCCC */
165    movzbq  rINSTbl, %rcx                   # rcx <- BA
166    sarl    $$4, %ecx                       # ecx <- B
167    GET_VREG %ecx, %rcx                     # vB (object we're operating on)
168    testl   %ecx, %ecx                      # is object null?
169    je      common_errNullObject
170    andb    $$0xf, rINSTbl                  # rINST <- A
171    GET_VREG rINST, rINSTq                  # rINST <- v[A]
172    movzwq  2(rPC), %rax                    # rax <- field byte offset
173    ${store}    ${reg}, (%rcx,%rax,1)
174    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
175
176%def op_iput_short():
177%  op_iput(helper="MterpIPutI16")
178
179%def op_iput_short_quick():
180%  op_iput_quick(reg="rINSTw", store="movw")
181
182%def op_iput_wide():
183%  op_iput(helper="MterpIPutU64")
184
185%def op_iput_wide_quick():
186    /* iput-wide-quick vA, vB, offset@CCCC */
187    movzbq    rINSTbl, %rcx                 # rcx<- BA
188    sarl      $$4, %ecx                     # ecx<- B
189    GET_VREG  %ecx, %rcx                    # vB (object we're operating on)
190    testl     %ecx, %ecx                    # is object null?
191    je        common_errNullObject
192    movzwq    2(rPC), %rax                  # rax<- field byte offset
193    leaq      (%rcx,%rax,1), %rcx           # ecx<- Address of 64-bit target
194    andb      $$0xf, rINSTbl                # rINST<- A
195    GET_WIDE_VREG %rax, rINSTq              # rax<- fp[A]/fp[A+1]
196    movq      %rax, (%rcx)                  # obj.field<- r0/r1
197    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
198
199%def op_new_instance():
200/*
201 * Create a new instance of a class.
202 */
203    /* new-instance vAA, class@BBBB */
204    EXPORT_PC
205    leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
206    movq    rSELF, OUT_ARG1
207    REFRESH_INST ${opnum}
208    movq    rINSTq, OUT_ARG2
209    call    SYMBOL(MterpNewInstance)
210    testb   %al, %al                        # 0 means an exception is thrown
211    jz      MterpPossibleException
212    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
213
214%def op_sget(is_object="0", helper="MterpSGetU32"):
215%  field(helper=helper)
216
217%def op_sget_boolean():
218%  op_sget(helper="MterpSGetU8")
219
220%def op_sget_byte():
221%  op_sget(helper="MterpSGetI8")
222
223%def op_sget_char():
224%  op_sget(helper="MterpSGetU16")
225
226%def op_sget_object():
227%  op_sget(is_object="1", helper="MterpSGetObj")
228
229%def op_sget_short():
230%  op_sget(helper="MterpSGetI16")
231
232%def op_sget_wide():
233%  op_sget(helper="MterpSGetU64")
234
235%def op_sput(is_object="0", helper="MterpSPutU32"):
236%  field(helper=helper)
237
238%def op_sput_boolean():
239%  op_sput(helper="MterpSPutU8")
240
241%def op_sput_byte():
242%  op_sput(helper="MterpSPutI8")
243
244%def op_sput_char():
245%  op_sput(helper="MterpSPutU16")
246
247%def op_sput_object():
248%  op_sput(is_object="1", helper="MterpSPutObj")
249
250%def op_sput_short():
251%  op_sput(helper="MterpSPutI16")
252
253%def op_sput_wide():
254%  op_sput(helper="MterpSPutU64")
255