1# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14definitions: []
15tests:
16  - file-name: "jeqz"
17    isa:
18      title: Conditional compared to zero jump
19      description: >
20        Transfer execution to an instruction at offset bytes
21        from the beginning of the current instruction
22        if signed 32-bit integer in accumulator compares with 0 as specified.
23        Offset is sign extended to the size of instruction address.
24      exceptions:
25        - x_none
26    commands:
27
28      - file-name: "op"
29        isa:
30          instructions:
31            - sig: jeqz imm:i32
32              acc: in:i32
33              format: [op_imm_8, op_imm_16]
34        description: >
35          Check jump occurs or not occurs, depending on `acc == 0` condition
36          for forward, backward, or current cases.
37        code-template: |
38          #
39              %s
40        check-type: exit-positive
41        cases:
42          - values:
43            - |
44              # Check forward jump
45                  ldai 0
46                  jeqz label
47                  ldai 255 ##*65536
48                  return  # should be jumped over
49              label:
50          - values:
51            - |
52              # Check backward jump
53                  jmp label2
54              label1:
55                  jmp label3
56                  ldai 255 ##*65536
57              label2:
58                  ldai 0
59                  jeqz label1
60                  ldai 255
61                  return  # should be jumped over
62              label3:
63          - values:
64              - |
65                # Check jump to itself
66                    ldai 1
67                loop:
68                    jeqz loop
69            bugid: ['3468']
70          - values:
71              - |
72                # Check jump to itself
73                    ldai 0
74                loop:
75                    jeqz loop
76            runner-options: [compile-only]
77
78      - file-name: "op_bounds"
79        isa:
80          instructions:
81            - sig: jeqz imm:i32
82              acc: in:i32
83              format: [op_imm_8, op_imm_16]
84        description: >
85          Check jump occurs or not occurs, depending on `acc == 0` condition
86          for forward and backward cases.
87        code-template: |
88          #
89              %s
90        check-type: none
91        cases:
92          - values:
93            - |
94              # Max forward jump for imm8, 2 + 124 + 1 = 127 bytes
95                  ldai 0
96                  jeqz label    # 2-byte instruction
97                  neg
98                  ldai 2 ##*62
99              label:
100                  return
101          - values:
102            - |
103              # Max backward jump for imm8, 1 + 2 + 2*61 + 1 + 2 = 128 bytes
104                  jmp label2
105              label:
106                  neg
107                  ldai 61
108                  subi 1 ##*61
109                  return
110              label2:
111                  ldai 0
112                  jeqz label
113                  ldai 1
114                  return
115          - values:
116            - |
117              # Max forward jump for imm16, 3 + 32760 + 4 = 32767 bytes
118                  ldai 0
119                  jeqz label    # 3-byte instruction
120                  movi.64 v0, 0 ##*3276
121                  ldai 1
122                  ldai 1
123              label:
124                  return
125          - values:
126            - |
127              # Max backward jump for imm16, 1 + 4 + 32760 + 1 + 2 = 32768 bytes
128                  jmp label2
129              label:
130                  return
131                  ldai 2
132                  ldai 2
133                  movi.64 v0, 0 ##*3276
134                  return
135              label2:
136                  ldai 0
137                  jeqz label
138                  ldai 1
139                  return
140
141      - file-name: "vals"
142        isa:
143          instructions:
144            - sig: jeqz imm:i32
145              acc: in:i32
146              format: [op_imm_8, op_imm_16]
147        description: >
148          Check jump not occurs if `acc != 0`
149          for different values in acc.
150        code-template: |
151          #
152              ldai %s
153              jeqz label_bad
154              ldai 0
155              jeqz label_good
156          label_bad:
157              ldai 255
158              return  # should be jumped over
159          label_good:
160        check-type: exit-positive
161        cases:
162          - values:
163              - "-1"
164          - values:
165              - "1"
166          - values:
167              - "0x7FFFFFFF"
168          - values:
169              - "0x80000000"
170          - values:
171              - "0xFFFFFFFF"
172
173      - file-name: "type"
174        isa:
175          instructions:
176            - sig: jeqz imm:i32
177              acc: in:i32
178              format: [op_imm_8, op_imm_16]
179          verification:
180              - acc_type
181        description: >
182          Check jeqz with invalid types in acc.
183        tags: ['verifier']
184        runner-options: ['verifier-failure', 'verifier-config']
185        header-template: []
186        code-template: |
187          #
188          .record A {}
189          .record panda.String <external>
190          .record panda.Object <external>
191          .function i32 main() {
192              %s
193              jeqz label
194              ldai 255
195          label:
196        check-type: exit-positive
197        cases:
198          - values:
199              - lda.null
200          - values:
201              - ldai.64 0
202          - values:
203              - fldai 0
204          - values:
205              - fldai.64 0
206          - values:
207              - lda.type A
208          - values:
209              - lda.type A[]
210          - values:
211              - lda.type panda.String
212          - values:
213              - |
214                newobj v0, A
215                lda.obj v0
216          - values:
217              - |
218                newobj v0, panda.Object
219                lda.obj v0
220          - values:
221              - lda.str "0"
222          - values:
223              - |
224                #
225                    movi v0, 10
226                    newarr v0, v0, i32[]
227                    lda.obj v0
228
229      - file-name: "outside_function"
230        isa:
231          instructions:
232            - sig: jeqz imm:i32
233              acc: in:i32
234              format: [op_imm_8, op_imm_16]
235          verification:
236            - branch_target
237        description: >
238          Branch target should point to a beginning
239          of an instruction of the same method.
240        runner-options: ['compile-failure']
241        header-template: []
242        code-template: |
243          #
244          .function i32 f() {
245          label:
246              ldai 255
247              return
248          }
249          .function i32 main() {
250              ldai 0
251              jeqz label
252        check-type: exit-positive
253
254      - file-name: "outside_try_catch_p"
255        isa:
256          instructions:
257            - sig: jeqz imm:i32
258              acc: in:i32
259              format: [op_imm_8, op_imm_16]
260        description: Jump outside try/catch block.
261        bugid: ['3425']
262        header-template: []
263        code-template: |
264          .record panda.ArithmeticException <external>
265          .function i32 main() {
266          begin:
267              ldai 0
268              jeqz outside
269              newobj v0, panda.ArithmeticException
270              throw v0
271          end:
272              ldai 1
273              return
274          catch_ae:
275              ldai 2
276              return
277          .catch panda.ArithmeticException, begin, end, catch_ae
278              ldai 3
279              return
280          outside:
281        check-type: exit-positive
282
283      - file-name: "outside_try_catch_j"
284        isa:
285          instructions:
286            - sig: jeqz imm:i32
287              acc: in:i32
288              format: [op_imm_8, op_imm_16]
289        description: Jump outside try/catch block.
290        bugid: ['3425']
291        header-template: []
292        runner-options: ['use-pa']
293        code-template: |
294          .language PandaAssembly
295          .record panda.NullPointerException <external>
296          .function i32 main() {
297          begin:
298              ldai 0
299              jeqz outside
300              mov.null v0
301              throw v0
302          end:
303              ldai 1
304              return
305          catch_npe:
306              ldai 2
307              return
308          .catch panda.NullPointerException, begin, end, catch_npe
309              ldai 3
310              return
311          outside:
312        check-type: exit-positive
313
314      - file-name: uninitialized_regs
315        isa:
316          instructions:
317            - sig: jeqz imm:i32
318              acc: in:i32
319              format: [op_imm_8, op_imm_16]
320        description: Check `jeqz` with uninitialized acc.
321        tags: ['verifier']
322        runner-options: ['verifier-failure', 'verifier-config']
323        code-template: |
324          #
325          label:
326              jeqz label
327        check-type: exit-positive
328
329      - file-name: "invalid_branch_target"
330        isa:
331          verification:
332            - branch_target
333        runner-options: [compile-failure]
334        description: Check 'jeqz' instruction with invalid branch target.
335        header-template: []
336        code-template: |
337            .record R {}
338
339            .function void R.ctor(R a0) <ctor> {
340            lbl_ctor:
341                return.void
342            }
343
344            .function void R.cctor() <cctor> {
345            lbl_cctor:
346                return.void
347            }
348
349            .function i32 foo(i32 a0, i32 a1) <static> {
350                lda a0
351                jeqz %s
352                return
353            }
354
355            .function i32 bar() <static> {
356            lbl_bar:
357                ldai 1
358                return
359            }
360
361            .function i32 main() {
362                movi v0, 0
363                movi v1, 1
364                call.short foo, v0, v1
365            lbl_main:
366        check-type: exit-positive
367        cases:
368          - values: ["main"]
369          - values: ["foo"]
370          - values: ["bar"]
371          - values: ["baz"]
372          - values: ["R"]
373          - values: ["lbl_main"]
374          - values: ["lbl_bar"]
375          - values: ["lbl_ctor"]
376          - values: ["lbl_cctor"]
377
378
379      - file-name: "prohibited_branch_target"
380        isa:
381          verification:
382            - branch_target
383        runner-options: ['verifier-failure', 'verifier-config']
384        tags: [verifier]
385        description: Check 'jeqz' instruction with prohibited branch target.
386        header-template: []
387        code-template: |
388            .record E1 {}
389            .record E2 {}
390
391            .function i32 main() {
392                ldai 0
393                jeqz %s
394
395            begin:
396                ldai 0
397                return
398            mid:
399                ldai 1
400                return
401            end:
402                ldai 2
403                return
404
405            catch_E1_begin:
406                ldai 3
407                return
408            catch_E1_mid:
409                ldai 4
410                return
411            catch_E1_end:
412                ldai 5
413                return
414
415            catch_E2_begin:
416                ldai 6
417                return
418            catch_E2_mid:
419                ldai 7
420                return
421            catch_E2_end:
422
423            quit:
424                ldai 8
425                return
426
427            .catch E1, begin, end, catch_E1_begin, catch_E1_end
428            .catch E2, catch_E1_begin, catch_E1_end, catch_E2_begin, catch_E2_end
429            outside:
430        check-type: none
431        cases:
432          - values: ["begin"]
433            runner-options: ['verifier-only', 'verifier-config']
434          - values: ["mid"]
435            runner-options: ['verifier-only', 'verifier-config']
436          - values: ["end"]
437            runner-options: ['verifier-only', 'verifier-config']
438          - values: ["quit"]
439            runner-options: ['verifier-only', 'verifier-config']
440          - values: ["catch_E1_begin"]
441          - values: ["catch_E1_mid"]
442          - values: ["catch_E1_end"]
443            runner-options: ['verifier-only', 'verifier-config']
444          - values: ["catch_E2_begin"]
445          - values: ["catch_E2_mid"]
446          - values: ["catch_E2_end"]
447            runner-options: ['verifier-only', 'verifier-config']
448          - values: ["outside"]
449