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