# Copyright (c) 2021-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. tests: - file-name: "jlt" isa: title: Conditional compared to register jump description: > Transfer execution to an instruction at offset bytes from the beginning of the current instruction if signed 32-bit integers in accumulator and register compare as specified. Offset is sign extended to the size of instruction address. exceptions: - x_none instructions: - sig: jlt v:in:i32, imm:i32 acc: in:i32 format: [op_v_8_imm_8, op_v_8_imm_16] commands: - file-name: "invalid_v_reg" isa: verification: - v1_type runner-options: [compile-failure] description: Check 'jlt' instruction with invalid 'v' register. header-template: [] code-template: | .function i32 main() { jlt %s lbl: check-type: exit-positive cases: - values: ["v256, lbl"] - values: ["v65535, lbl"] - values: ["v65536, lbl"] - values: ["a0, lbl"] - values: ["a256, lbl"] - values: ["a65535, lbl"] - values: ["lbl"] - values: [""] - values: ["}"] - values: ["# v1, lbl"] - values: ["V1, lbl"] - values: ["v1, Lbl"] - file-name: "invalid_a_reg" isa: verification: - v1_type runner-options: [compile-failure] description: Check 'jlt' instruction with invalid 'a' register. header-template: [] code-template: | .function void foo(i32 a0, i32 a1, i32 a2, i32 a3, i32 a4, i32 a5) { jlt %s lbl: return.void } .function i32 main() { call.range foo, v0 check-type: exit-positive cases: - values: ["v256, lbl"] - values: ["v65535, lbl"] - values: ["v65536, lbl"] - values: ["a6, lbl"] - values: ["a256, lbl"] - values: ["a65535, lbl"] - values: ["lbl"] - values: [""] - values: ["}"] - values: ["# a1, lbl"] - values: ["A1, lbl"] - values: ["a1, Lbl"] - file-name: "valid_v_reg" isa: verification: - v1_type instructions: - sig: jlt v:in:i32, imm:i32 acc: in:i32 format: [op_v_8_imm_8, op_v_8_imm_16] description: Check 'jlt' instruction with valid 'v' register. header-template: [] code-template: | .function i32 main() { movi %s, 2 ldai 1 jlt %s, lbl ldai 1 return lbl: check-type: exit-positive cases: - values: ["v0", "v0"] - values: ["v7", "v7"] - values: ["v8", "v8"] - values: ["v15", "v15"] - values: ["v16", "v16"] - values: ["v254", "v254"] - values: ["v255", "v255"] tags: [tsan] - file-name: "valid_a_reg" isa: verification: - v1_type instructions: - sig: jlt v:in:i32, imm:i32 acc: in:i32 format: [op_v_8_imm_8, op_v_8_imm_16] description: Check 'jlt' instruction with valid 'a' register. header-template: [] code-template: | .function i32 foo(%s) { ldai 1 jlt %s, lbl ldai 1 return lbl: ldai 0 return } .function i32 main() { %s call.range foo, v0 check-type: no-check cases: - values: - i32 a0 - a0 - | # movi v0, 2 - values: - i16 a0, i32 a1 - a1 - | # movi v0, 2 movi v1, 3 tags: [tsan] - values: - "#{[*0..255].map do |i| \" i32 a#{i}\" end .join(\",\")}" - a254 - "#{[*0..255].map do |i| \" movi v#{i}, #{i}\\n\" end .join}" bugid: ['3855'] - values: - "#{[*0..255].map do |i| \" i32 a#{i}\" end .join(\",\")}" - a255 - "#{[*0..255].map do |i| \" movi v#{i}, #{i}\\n\" end .join}" bugid: ['3855'] - file-name: "uninitialized_regs" isa: verification: - acc_type - v1_type runner-options: ['verifier-failure', 'verifier-config'] tags: [verifier] description: Check 'jlt' instruction with uninitialized registers. header-template: [] code-template: | .function i32 main() { %s jlt v1, lbl ldai 1 return lbl: check-type: exit-positive cases: - description: Accumulator is not initialized. values: - movi v1, 1 - description: V register is not initialized. values: - ldai 1 - description: Accumulator and 'v' register are both not initialized. values: - "" - file-name: "invalid_branch_target" isa: verification: - branch_target runner-options: [compile-failure] description: Check 'jlt' instruction with invalid branch target. header-template: [] code-template: | .record R {} .function void R.ctor(R a0) { lbl_ctor: return.void } .function void R.cctor() { lbl_cctor: return.void } .function i32 foo(i32 a0, i32 a1) { lda a0 jlt a1, %s return } .function i32 bar() { lbl_bar: ldai 1 return } .function i32 main() { movi v0, 0 movi v1, 1 call.short foo, v0, v1 lbl_main: check-type: exit-positive cases: - values: ["main"] - values: ["foo"] - values: ["bar"] - values: ["baz"] - values: ["R"] - values: ["lbl_main"] - values: ["lbl_bar"] - values: ["lbl_ctor"] - values: ["lbl_cctor"] - file-name: "prohibited_branch_target" isa: verification: - branch_target runner-options: ['verifier-failure', 'verifier-config'] tags: [verifier] description: Check 'jlt' instruction with prohibited branch target. header-template: [] code-template: | .record E1 {} .record E2 {} .function i32 main() { ldai 1 movi v0, 1 jlt v0, %s begin: ldai 0 return mid: ldai 1 return end: ldai 2 return catch_E1_begin: ldai 3 return catch_E1_mid: ldai 4 return catch_E1_end: ldai 5 return catch_E2_begin: ldai 6 return catch_E2_mid: ldai 7 return catch_E2_end: quit: ldai 8 return .catch E1, begin, end, catch_E1_begin, catch_E1_end .catch E2, catch_E1_begin, catch_E1_end, catch_E2_begin, catch_E2_end outside: check-type: none cases: - values: ["begin"] runner-options: ['verifier-only', 'verifier-config'] - values: ["mid"] runner-options: ['verifier-only', 'verifier-config'] - values: ["end"] runner-options: ['verifier-only', 'verifier-config'] - values: ["quit"] runner-options: ['verifier-only', 'verifier-config'] - values: ["catch_E1_begin"] - values: ["catch_E1_mid"] - values: ["catch_E1_end"] runner-options: ['verifier-only', 'verifier-config'] - values: ["catch_E2_begin"] - values: ["catch_E2_mid"] - values: ["catch_E2_end"] runner-options: ['verifier-only', 'verifier-config'] - values: ["outside"] - file-name: "invalid_acc_value" isa: verification: - acc_type runner-options: ['verifier-failure', 'verifier-config'] tags: [verifier] description: Check 'jlt' instruction with invalid accumulator value header-template: [] code-template: | .record panda.Object .record panda.String .record panda.Class .record R {} .function void R.ctor(R a0) { return.void } .function i32 main() { %s movi v1, 1 jlt v1, ok ldai 1 return ok: check-type: exit-positive cases: - values: - lda.null - values: - initobj R.ctor - values: - lda.str "test" - values: - lda.type panda.Object - values: - | # movi v0, 10 newarr v0, v0, i32[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, f64[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, R[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, panda.Class[][] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, panda.String[] lda.obj v0 - values: - ldai.64 0 - values: - ldai.64 1 - values: - ldai.64 0x7fffffffffffffff - values: - ldai.64 0xffffffffffffffff - values: - ldai.64 0x8000000000000000 - values: - | # fldai 0x00000000 # Positive zero (+0.0) - values: - | # fldai 0x80000000 # Negative zero (-0.0) - values: - | # fldai 0x00000001 # Minimal positive value (1.4012985e-45) - values: - | # fldai 0x80000001 # Maximal negative value (-1.4012985e-45) - values: - | # fldai 0x7f7fffff # Maximal positive value (3.4028235e38) - values: - | # fldai 0xff7fffff # Minimal negative value (-3.4028235e38) - values: - | # fldai 0x7f800000 # Positive infinity - values: - | # fldai 0xff800000 # Negative infinity - values: - | # fldai 0x7fc00000 # NaN - values: - | # fldai.64 0x0000000000000000 # Positive zero (+0.0, hexadecimal representation is `0x0000000000000000`) - values: - | # fldai.64 0x8000000000000000 # Negative zero (-0.0, hexadecimal representation is `0x8000000000000000`) - values: - | # fldai.64 0x0000000000000001 # Minimal positive value (4.9E-324, hexadecimal representation is `0x0000000000000001`) - values: - | # fldai.64 0x8000000000000001 # Maximal negative value (-4.9E-324, hexadecimal representation is `0x8000000000000001`) - values: - | # fldai.64 0x7fefffffffffffff # Maximal positive value (1.7976931348623157e308, hexadecimal representation is `0x7fefffffffffffff`) - values: - | # fldai.64 0xffefffffffffffff # Minimal negative value (-1.7976931348623157e308, hexadecimal representation is `0xffefffffffffffff`) - values: - | # fldai.64 0x7ff0000000000000 # Positive infinity (hexadecimal representation is `0x7ff0000000000000`) - values: - | # fldai.64 0xfff0000000000000 # Negative infinity (hexadecimal representation is `0xfff0000000000000`) - values: - | # fldai.64 0x7ff8000000000000 # NaN - file-name: "invalid_v_value" isa: verification: - v1_type runner-options: ['verifier-failure', 'verifier-config'] tags: [verifier] description: Check 'jlt' instruction with invalid v register value header-template: [] code-template: | .record panda.Object .record panda.String .record panda.Class .record R {} .function void R.ctor(R a0) { return.void } .function i32 main() { %s ldai 1 jlt v1, ok ldai 1 return ok: check-type: exit-positive cases: - values: - mov.null v1 - values: - | # initobj R.ctor sta.obj v1 - values: - | # lda.str "test" sta.obj v1 - values: - | # lda.type panda.Object sta.obj v1 - values: - | # movi v0, 10 newarr v1, v0, i32[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, f64[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, R[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, panda.Class[][] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, panda.String[] lda.obj v1 - values: - movi.64 v1, 0 - values: - movi.64 v1, 1 - values: - movi.64 v1, 0x7fffffffffffffff - values: - movi.64 v1, 0xffffffffffffffff - values: - movi.64 v1, 0x8000000000000000 - values: - | # fmovi v1, 0x00000000 # Positive zero (+0.0) - values: - | # fmovi v1, 0x80000000 # Negative zero (-0.0) - values: - | # fmovi v1, 0x00000001 # Minimal positive value (1.4012985e-45) - values: - | # fmovi v1, 0x80000001 # Maximal negative value (-1.4012985e-45) - values: - | # fmovi v1, 0x7f7fffff # Maximal positive value (3.4028235e38) - values: - | # fmovi v1, 0xff7fffff # Minimal negative value (-3.4028235e38) - values: - | # fmovi v1, 0x7f800000 # Positive infinity - values: - | # fmovi v1, 0xff800000 # Negative infinity - values: - | # fmovi v1, 0x7fc00000 # NaN - values: - | # fmovi.64 v1, 0x0000000000000000 # Positive zero (+0.0, hexadecimal representation is `0x0000000000000000`) - values: - | # fmovi.64 v1, 0x8000000000000000 # Negative zero (-0.0, hexadecimal representation is `0x8000000000000000`) - values: - | # fmovi.64 v1, 0x0000000000000001 # Minimal positive value (4.9E-324, hexadecimal representation is `0x0000000000000001`) - values: - | # fmovi.64 v1, 0x8000000000000001 # Maximal negative value (-4.9E-324, hexadecimal representation is `0x8000000000000001`) - values: - | # fmovi.64 v1, 0x7fefffffffffffff # Maximal positive value (1.7976931348623157e308, hexadecimal representation is `0x7fefffffffffffff`) - values: - | # fmovi.64 v1, 0xffefffffffffffff # Minimal negative value (-1.7976931348623157e308, hexadecimal representation is `0xffefffffffffffff`) - values: - | # fmovi.64 v1, 0x7ff0000000000000 # Positive infinity (hexadecimal representation is `0x7ff0000000000000`) - values: - | # fmovi.64 v1, 0xfff0000000000000 # Negative infinity (hexadecimal representation is `0xfff0000000000000`) - values: - | # fmovi.64 v1, 0x7ff8000000000000 # NaN - file-name: "invalid_both_acc_and_v_value" isa: verification: - v1_type - acc_type runner-options: ['verifier-failure', 'verifier-config'] tags: [verifier] description: Check 'jlt' instruction with invalid accumulator and v register value header-template: [] code-template: | .record panda.Object .record panda.String .record panda.Class .record R {} .function void R.ctor(R a0) { return.void } .function i32 main() { *s %s jlt v1, ok ldai 1 return ok: check-type: exit-positive template-cases: - values: - lda.null - values: - initobj R.ctor - values: - lda.str "test" - values: - lda.type panda.Object - values: - | # movi v0, 10 newarr v0, v0, i32[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, f64[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, R[] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, panda.Class[][] lda.obj v0 - values: - | # movi v0, 10 newarr v0, v0, panda.String[] lda.obj v0 - values: - ldai.64 0 - values: - ldai.64 1 - values: - ldai.64 0x7fffffffffffffff - values: - ldai.64 0xffffffffffffffff - values: - ldai.64 0x8000000000000000 - values: - | # fldai 0x00000000 # Positive zero (+0.0) - values: - | # fldai 0x80000000 # Negative zero (-0.0) - values: - | # fldai 0x00000001 # Minimal positive value (1.4012985e-45) - values: - | # fldai 0x80000001 # Maximal negative value (-1.4012985e-45) - values: - | # fldai 0x7f7fffff # Maximal positive value (3.4028235e38) - values: - | # fldai 0xff7fffff # Minimal negative value (-3.4028235e38) - values: - | # fldai 0x7f800000 # Positive infinity - values: - | # fldai 0xff800000 # Negative infinity - values: - | # fldai 0x7fc00000 # NaN - values: - | # fldai.64 0x0000000000000000 # Positive zero (+0.0, hexadecimal representation is `0x0000000000000000`) - values: - | # fldai.64 0x8000000000000000 # Negative zero (-0.0, hexadecimal representation is `0x8000000000000000`) - values: - | # fldai.64 0x0000000000000001 # Minimal positive value (4.9E-324, hexadecimal representation is `0x0000000000000001`) - values: - | # fldai.64 0x8000000000000001 # Maximal negative value (-4.9E-324, hexadecimal representation is `0x8000000000000001`) - values: - | # fldai.64 0x7fefffffffffffff # Maximal positive value (1.7976931348623157e308, hexadecimal representation is `0x7fefffffffffffff`) - values: - | # fldai.64 0xffefffffffffffff # Minimal negative value (-1.7976931348623157e308, hexadecimal representation is `0xffefffffffffffff`) - values: - | # fldai.64 0x7ff0000000000000 # Positive infinity (hexadecimal representation is `0x7ff0000000000000`) - values: - | # fldai.64 0xfff0000000000000 # Negative infinity (hexadecimal representation is `0xfff0000000000000`) - values: - | # fldai.64 0x7ff8000000000000 # NaN cases: - values: - mov.null v1 - values: - | # initobj R.ctor sta.obj v1 - values: - | # lda.str "test" sta.obj v1 - values: - | # lda.type panda.Object sta.obj v1 - values: - | # movi v0, 10 newarr v1, v0, i32[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, f64[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, R[] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, panda.Class[][] lda.obj v1 - values: - | # movi v0, 10 newarr v1, v0, panda.String[] lda.obj v1 - values: - movi.64 v1, 0 - values: - movi.64 v1, 1 - values: - movi.64 v1, 0x7fffffffffffffff - values: - movi.64 v1, 0xffffffffffffffff - values: - movi.64 v1, 0x8000000000000000 - values: - | # fmovi v1, 0x00000000 # Positive zero (+0.0) - values: - | # fmovi v1, 0x80000000 # Negative zero (-0.0) - values: - | # fmovi v1, 0x00000001 # Minimal positive value (1.4012985e-45) - values: - | # fmovi v1, 0x80000001 # Maximal negative value (-1.4012985e-45) - values: - | # fmovi v1, 0x7f7fffff # Maximal positive value (3.4028235e38) - values: - | # fmovi v1, 0xff7fffff # Minimal negative value (-3.4028235e38) - values: - | # fmovi v1, 0x7f800000 # Positive infinity - values: - | # fmovi v1, 0xff800000 # Negative infinity - values: - | # fmovi v1, 0x7fc00000 # NaN - values: - | # fmovi.64 v1, 0x0000000000000000 # Positive zero (+0.0, hexadecimal representation is `0x0000000000000000`) - values: - | # fmovi.64 v1, 0x8000000000000000 # Negative zero (-0.0, hexadecimal representation is `0x8000000000000000`) - values: - | # fmovi.64 v1, 0x0000000000000001 # Minimal positive value (4.9E-324, hexadecimal representation is `0x0000000000000001`) - values: - | # fmovi.64 v1, 0x8000000000000001 # Maximal negative value (-4.9E-324, hexadecimal representation is `0x8000000000000001`) - values: - | # fmovi.64 v1, 0x7fefffffffffffff # Maximal positive value (1.7976931348623157e308, hexadecimal representation is `0x7fefffffffffffff`) - values: - | # fmovi.64 v1, 0xffefffffffffffff # Minimal negative value (-1.7976931348623157e308, hexadecimal representation is `0xffefffffffffffff`) - values: - | # fmovi.64 v1, 0x7ff0000000000000 # Positive infinity (hexadecimal representation is `0x7ff0000000000000`) - values: - | # fmovi.64 v1, 0xfff0000000000000 # Negative infinity (hexadecimal representation is `0xfff0000000000000`) - values: - | # fmovi.64 v1, 0x7ff8000000000000 # NaN - file-name: "valid_values" isa: description: > Transfer execution to an instruction at offset bytes from the beginning of the current instruction if signed 32-bit integers in accumulator and register compare as specified. Offset is sign extended to the size of instruction address. description: Check 'jlt' instruction with valid values in registers. header-template: [] code-template: | .function i32 main() { ldai %s movi v1, %s jlt v1, lbl ldai %s return lbl: ldai %s check-type: no-check cases: - values: [-2147483648, -2147483648, 0, 1] - values: [-2147483648, -1, 1, 0] - values: [-2147483648, 0, 1, 0] - values: [-2147483648, 1, 1, 0] - values: [-2147483648, 2147483647, 1, 0] - values: [-1, -2147483648, 0, 1] - values: [-1, -1, 0, 1] - values: [-1, 0, 1, 0] - values: [-1, 1, 1, 0] - values: [-1, 2147483647, 1, 0] - values: [0, -2147483648, 0, 1] - values: [0, -1, 0, 1] - values: [0, 0, 0, 1] - values: [0, 1, 1, 0] - values: [0, 2147483647, 1, 0] - values: [1, -2147483648, 0, 1] - values: [1, -1, 0, 1] - values: [1, 0, 0, 1] - values: [1, 1, 0, 1] - values: [1, 2147483647, 1, 0] - values: [2147483647, -2147483648, 0, 1] - values: [2147483647, -1, 0, 1] - values: [2147483647, 0, 0, 1] - values: [2147483647, 1, 0, 1] - values: [2147483647, 2147483647, 0, 1] - file-name: "valid_offset_values" isa: description: > Transfer execution to an instruction at offset bytes from the beginning of the current instruction if signed 32-bit integers in accumulator and register compare as specified. Offset is sign extended to the size of instruction address. description: Check 'jlt' instruction with valid offset values. header-template: [] code-template: | .function i32 main() { ldai 1 movi v1, 2 %s ldai 1 # 2-byte instruction return # 1-byte instruction quit: check-type: exit-positive cases: - description: Same instruction jump, offset imm8, 0 bytes values: - | # ldai 10 lbl: jlt v1, lbl ldai 0 return tags: [tsan] bugid: ['3828'] - description: Max forward jump for imm8, 3 + 120 + 1 + 3 = 127 bytes values: - | # jlt v1, quit # 3-byte instruction movi.64 v0, 0 ##*12 neg # 1-byte instruction tags: [tsan] - description: Max backward jump for imm8, 3 + 120 + 2 + 2 + 1 = 128 bytes values: - | # jmp lbl2 lbl1: jmp quit # 3-byte instruction movi.64 v0, 0 ##*12 ldai 1 # 2-byte instruction ldai 1 # 2-byte instruction return # 1-byte instruction lbl2: jlt v1, lbl1 - description: Max forward jump for imm16, 32760 + 4 + 3 = 32767 bytes values: - | # jlt v1, quit # 4-byte instruction movi.64 v0, 0 ##*3276 - description: Beyond max forward jump for imm16, 40000 + 4 + 3 = 40007 bytes. Converted to jgt + jmp by compiler. values: - | # jlt v1, quit # 4-byte instruction movi.64 v0, 0 ##*4000 - description: Max backward jump for imm16, 5 + 32760 + 3 = 32768 bytes values: - | # jmp lbl2 lbl1: jmp quit # 5-byte instruction movi.64 v0, 0 ##*3276 ldai 1 return lbl2: jlt v1, lbl1 - description: Beyond max backward jump for imm16, 5 + 40000 = 40005 bytes. Converted to jgt + jmp by compiler. values: - | # jmp lbl2 lbl1: jmp quit # 5-byte instruction movi.64 v0, 0 ##*4000 ldai 1 return lbl2: jlt v1, lbl1 - description: Chain of forward jumps values: - | # jlt v1, lbl1 ldai 2 return lbl1: jlt v1, lbl2 ldai 3 return lbl2: jlt v1, lbl3 ldai 4 return lbl3: jlt v1, lbl4 ldai 5 return lbl4: jlt v1, quit tags: [tsan] - description: Chain of backward jumps values: - | # jmp lbl1 lbl6: jmp quit lbl5: jlt v1, lbl6 ldai 5 return lbl4: jlt v1, lbl5 ldai 4 return lbl3: jlt v1, lbl4 ldai 3 return lbl2: jlt v1, lbl3 ldai 2 return lbl1: jlt v1, lbl2 tags: [tsan]