# 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.

definitions: []
tests:
  - file-name: "fadd2"
    isa:
      title: Two address floating-point binary operation on accumulator
      description: >
        Perform specified floating-point binary operation on accumulator and register and store result into accumulator.
        The results of instructions correspond IEEE-754 arithmetic rules.
      exceptions:
          - x_none
    commands:
      - file-name: "op_vs_8_nan"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: Any operation with NaN results to NaN value.
        check-type: check-acc-nan-f32
        tags: ['irtoc_ignore']
        code-template: |
          #
              fldai %s
              fmovi v0, *s
          # Sum of any value and NaN is NaN
              fadd2 v0
        description: >
          Check fadd2 results in NaN when acc or v0 is NaN
        template-cases:
          - values:
              # NaN
              - "0x7FC00000"
          - values:
              # NaN representation
              - "0xFFFFFFFF"
          - values:
              # Positive zero
              # +0.0d
              - "0"
            exclude: [hasval]
          - values:
              # Negative zero
              # -0.0d
              - "0x80000000"
            exclude: [hasval]
          - values:
              # 1d
              - "0x3ff00000"
            exclude: [hasval]
          - values:
              # -1d
              - "0xbff00000"
            exclude: [hasval]
          - values:
              # +Inf
              - "0x7f800000"
            exclude: [hasval]
          - values:
              # -Inf
              - "0xff800000"
            exclude: [hasval]
          - values:
              # +max
              - "0x7fefffff"
            exclude: [hasval]
          - values:
              # -max
              - "0xffefffff"
            exclude: [hasval]
          - values:
              # +min
              - "0x00000001"
            exclude: [hasval]
          - values:
              # -min
              - "0x80000001"
            exclude: [hasval]
          - values:
              # Some FP value
              - "9.9e-30"
            exclude: [hasval]
          - values:
              # Some FP value
              - "-0.000000001"
            exclude: [hasval]
        cases:
          - values:
              # NaN
              - "0x7fc00000"
          - values:
              # NaN representation
              - "0xFFFFFFFF"
          - values:
              # Positive zero
              # +0.0d
              - "0"
            id: hasval
          - values:
              # Negative zero
              # -0.0d
              - "0x80000000"
            id: hasval
          - values:
              # 1d
              - "0x3ff00000"
            id: hasval
          - values:
              # -1d
              - "0xbff00000"
            id: hasval
          - values:
              # +Inf
              - "0x7f800000"
            id: hasval
          - values:
              # -Inf
              - "0xff800000"
            id: hasval
          - values:
              # +max
              - "0x7f7fffff"
            id: hasval
          - values:
              # -max
              - "0xff7fffff"
            id: hasval
          - values:
              # +min
              - "0x00000001"
            id: hasval
          - values:
              # -min
              - "0x80000001"
            id: hasval
          - values:
              # Some FP value
              - "9.9e-30"
            id: hasval
          - values:
              # Some FP value
              - "-0.000000001"
            id: hasval

      - file-name: "op_vs_8_pinf"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
            The sum of two infinities of the same sign or the difference of two infinities of opposite sign is infinity.
            The sign of result matches the sign of accumulator value.
            The sum or the difference of infinity and any finite value is infinity.
            The sign of result matches the sign of infinity.
        check-type: check-positive
        tags: ['irtoc_ignore']
        code-template: |
            #
                fldai 0x7f800000 # +Inf
                fmovi v0, %s
            # Sum of +Inf and value
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        description: Check fadd2 with positive Inf and various values (Inf, min, max, numbers).
        cases:
          - values:
              # +0.0d
              - "0"
              - "0x7f800000"
          - values:
              # -0.0d
              - "0x80000000"
              - "0x7f800000"
          - values:
              # 1d
              - "0x3ff00000"
              - "0x7f800000"
          - values:
              # -1d
              - "0xbff00000"
              - "0x7f800000"
          - values:
              # +Inf
              - "0x7f800000"
              - "0x7f800000"
          - values:
              # +max
              - "0x7f7fffff"
              - "0x7f800000"
          - values:
              # -max
              - "0xff7fffff"
              - "0x7f800000"
          - values:
              # +min
              - "0x00000001"
              - "0x7f800000"
          - values:
              # -min
              - "0x80000001"
              - "0x7f800000"
          - values:
              # Some FP value, 3.1415927
              - "0x40490fdb"
              - "0x7f800000"
          - values:
              - "123456780"
              - "0x7f800000"

      - file-name: "op_vs_8_ninf"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
            The sum of two infinities of the same sign or the difference of two infinities of opposite sign is infinity.
            The sign of result matches the sign of accumulator value.
            The sum or the difference of infinity and any finite value is infinity.
            The sign of result matches the sign of infinity.
        check-type: check-positive
        tags: ['irtoc_ignore']
        # TODO update template to use Hexadecimal value for -Inf
        code-template: |
            #
                fldai 0xff800000 # -Inf
                fmovi v0, %s
            # Sum of -Inf and value
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        description: Check fadd2 with negative Inf and various values (Inf, min, max, numbers).
        cases:
            - values:
                # +0.0d
                - "0"
                # -Inf
                - "0xff800000"
            - values:
                # -0.0d
                - "0x80000000"
                # -Inf
                - "0xff800000"
            - values:
                # 1d
                - "0x3ff00000"
                # -Inf
                - "0xff800000"
            - values:
                # -1d
                - "0xbff00000"
                # -Inf
                - "0xff800000"
            - values:
                # -Inf
                - "0xff800000"
                # -Inf
                - "0xff800000"
            - values:
                # +max
                - "0x7f7fffff"
                # -Inf
                - "0xff800000"
            - values:
                # -max
                - "0xff7fffff"
                # -Inf
                - "0xff800000"
            - values:
                # +min
                - "0x00000001"
                # -Inf
                - "0xff800000"
            - values:
                # -min
                - "0x80000001"
                # -Inf
                - "0xff800000"
            - values:
                # Some FP value, 3.1415927
                - "0x40490fdb"
                # -Inf
                - "0xff800000"
            - values:
                - "1234567890"
                # -Inf
                - "0xff800000"

      - file-name: "op_vs_8_inf_nan"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
            The sum of opposite infinities or the difference of the same sign infinities is NaN.
        check-type: check-acc-nan-f32
        tags: ['irtoc_ignore']
        code-template: |
            #
                fldai %s
                fmovi v0, %s
            # Sum of opposite Inf-s
                fadd2 v0
        description: Check fadd2 with +Inf and -Inf is NaN.
        cases:
          - values:
              - "0x7f700000"
              - "0x7fc00000"
          - values:
              - "0xff800000"
              - "0x7fc00000"

      - file-name: "op_vs_8_pzero"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
              The sum or the difference of infinity and any finite value is infinity.
              The sign of result matches the sign of infinity.
              The sum or the difference of zeros is zero.
              Exceptions are the sum of two negative zeros and the difference of negative and positive zero - the result is negative zero.
        check-type: check-positive
        tags: ['irtoc_ignore']
        description: Check fadd2 with positive zero and various values (Inf, min, max, numbers).
        code-template: |
            #
                fldai 0.0 #
                fmovi v0, %s
                mov v1, v0
            # Sum of +0.0 and value
                fadd2 v0
                fcmpg v1
        cases:
            - values:
                # +0.0d
                - "0"
            - values:
                # -0.0d
                - "0x80000000"
            - values:
                # 1d
                - "1"
            - values:
                # -1d
                - "-1"
            - values:
                # +Inf
                - "0x7f800000"
            - values:
                # -Inf
                - "0xff800000"
            - values:
                # +max
                - "0x7f7fffff"
            - values:
                # -max
                - "0xff7fffff"
            - values:
                # +min
                - "0x00000001"

            - values:
                # -min
                - "0x80000001"
            - values:
                - "3.1415927"
            - values:
                - "1234567890"

      - file-name: "op_vs_8_nzero"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
              The sum or the difference of infinity and any finite value is infinity.
              The sign of result matches the sign of infinity.
              The sum or the difference of zeros is zero.
              Exceptions are the sum of two negative zeros and the difference of negative and positive zero - the result is negative zero.
        check-type: check-positive
        tags: ['irtoc_ignore']
        description: Check fadd2 with negative zero and various values (Inf, min, max, numbers).
        code-template: |
            #
                fldai -0.0 #
                fmovi v0, %s
                mov v1, v0
            # Sum of -0.0 and value
                fadd2 v0
                fcmpg v1
        cases:
          # Comment this case, since it is incorrect.
          # It seems the better way to compare -0.0 and -0.0 is to convert it to -Inf
          # - case-template: |
          #     #
          #         fldai -0.0 #
          #         fmovi v0, -0.0
          #     # Sum of -0.0 and -0.0 should be -0.0
          #         fadd2 v0
          #         fmovi v1, -0.0
          #         cmp v1 # compare as binary values, due to +0.0 == -0.0, but 0x80000000 != 0x00000000
          - values:
              # 1d
              - "1"
          - values:
              - "-1"
          - values:
              # +Inf
              - "0x7f800000"
          - values:
              # -Inf
              - "0xff800000"
          - values:
              # +max
              - "0x7f7fffff"
          - values:
              # -max
              - "0xff7fffff"
          - values:
              # +min
              - "0x00000001"
          - values:
              # -min
              - "0x80000001"
          - values:
              - "3.1415927"
          - values:
              - "1234567890"

      - file-name: "op_vs_8_pone"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
            The sum or the difference of infinity and any finite value is infinity.
            The sign of result matches the sign of infinity.
        tags: ['irtoc_ignore']
        check-type: check-positive
        description: Check fadd2 with +1 and various values (Inf, min, max, numbers).
        code-template: |
            #
                fldai 1.0 #
                fmovi v0, %s
            # Sum of 1.0 and value
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        cases:
          - values:
              # +0.0d
              - "0"
              - "1.0"
          - values:
              # -0.0d
              - "0x80000000"
              - "1.0"
          - values:
              - "1.0"
              - "2.0"
          - values:
              - "-1.0"
              - "0"
          - values:
              # +Inf
              - "0x7f800000"
              - "0x7f800000"
          - values:
              # -Inf
              - "0xff800000"
              # -Inf
              - "0xff800000"
          - values:
              # +max
              - "0x7f7fffff"
              - "0x7f7fffff"
          - values:
              # -max
              - "0xff7fffff"
              # -max
              - "0xff7fffff"
          - values:
              # +min
              - "0x00000001"
              - "1.0"
          - values:
              # -min
              - "0x80000001"
              - "1.0"
          - values:
              # Some FP value, 3.1415927
              - "3.1415927"
              - "4.141593"
          - values:
              # Some FP value
              - "1234.4321"
              - "1235.4321"

      - file-name: "op_vs_8_none"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
            The sum or the difference of infinity and any finite value is infinity.
            The sign of result matches the sign of infinity.
        check-type: check-positive
        tags: ['irtoc_ignore']
        description: Check fadd2 with -1 and various values (Inf, min, max, numbers).
        code-template: |
            #
                fldai -1.0 #
                fmovi v0, %s
            # Sum of -1.0 and value
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        cases:
          - values:
              # +0.0d
              - "0"
              - "-1"
          - values:
              # -0.0d
              - "0x80000000"
              - "-1"
          - values:
              # 1d
              - "1"
              - "0"
          - values:
              # -1d
              - "-1"
              - "-2"
          - values:
              # +Inf
              - "0x7f800000"
              - "0x7f800000"
          - values:
              # -Inf
              - "0xff800000"
              # -Inf
              - "0xff800000"
          - values:
              # +max
              - "0x7f7fffff"
              - "0x7f7fffff"
          - values:
              # -max
              - "0xff7fffff"
              # -max
              - "0xff7fffff"
          - values:
              # +min
              - "0x00000001"
              # -1d
              - "-1"
          - values:
              # -min
              - "0x80000001"
              # -1d
              - "-1"
          - values:
              # Some FP value, 3.1415927
              - "3.1415927"
              - "2.1415927"
          - values:
              # Some FP value
              - "1234.4321"
              - "1233.4321"

      - file-name: "op_vs_8"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
          description: >
              The sum or the difference of zeros is zero.
              Exceptions are the sum of two negative zeros and the difference of negative and positive zero - the result is negative zero.
        check-type: check-positive
        tags: ['irtoc_ignore']
        description: Check fadd2 with various values.
        code-template: |
            #
                fldai %s #
                fmovi v0, %s
            # Sum of -1.0 and value
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        cases:
            - values:
                - "0.0"
                - "0.0"
                - "0.0"
            - values:
                - "0.0"
                - "-0.0"
                - "0.0"
            - values:
                - "-0.0"
                - "0.0"
                - "0.0"
            - values:
                - "-0.0"
                - "-0.0"
                - "0.0"
            - values:
                - "1.0"
                - "-1.0"
                - "0.0"
            - values:
                - "-1.0"
                - "1.0"
                - "0.0"
            - values:
                - "1.0e30"
                - "1.0e30"
                - "2.0e30"
            - values:
                - "1.0e-30"
                - "1.0e-30"
                - "2.0e-30"
            - values:
                - "1.0e+30"
                - "1.0e-30"
                - "1.0e+30"
            - values:
                - "-1.0e30"
                - "-1.0e30"
                - "-2.0e30"
            - values:
                - "-1.0e-30"
                - "-1.0e-30"
                - "-2.0e-30"
            - values:
                - "-1.0e+30"
                - "-1.0e-30"
                - "-1.0e+30"
            - values:
                - "3.1415927"
                - "3.1415927"
                - "6.2831854"
            - values:
                - "3.1415927e20"
                - "3.1415927e20"
                - "6.2831854e20"
#            - values:
#              # TODO add test cases for maximal and minimal FP value in decimal scientific literal

      - file-name: "op_vs_8_max"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
        check-type: check-positive
        tags: ['irtoc_ignore']
        code-template: |
            #
                fldai %s
                fmovi v0, %s
            # Sum of two values
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        description: Check fadd2 with various max values.
        cases:
          - values:
              # +max
              - "0x7f7fffff"
              # +max
              - "0x7f7fffff"
              # +Inf
              - "0x7f800000"
          - values:
              # -max
              - "0xff7fffff"
              # -max
              - "0xff7fffff"
              # -Inf
              - "0xff800000"
          - values:
              # +max
              - "0x7f7fffff"
              # -max
              - "0xff7fffff"
              - "0"
          - values:
              # +max
              - "0x7f7fffff"
              # 1d
              - "0x3ff00000"
              # +max
              - "0x7f7fffff"
          - values:
              # +max
              - "0x7f7fffff"
              - "-1.0"
              # +max
              - "0x7f7fffff"
          - values:
              # -max
              - "0xff7fffff"
              - "1"
              # -max
              - "0xff7fffff"
          - values:
              # -max
              - "0xff7fffff"
              - "-1.0"
              # -max
              - "0xff7fffff"

      - file-name: "incorrect_reg"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
        check-type: none
        runner-options: [compile-failure]
        description: Check fadd2 with incorrect register numbers.
        code-template: |
          #
              fadd2 %s
        cases:
          - values: [v256]
          - values: [v65535]
          - values: [a0]
          - values: [a255]
          - values: ['null']
          - values: [0]
          - values: [1.1]
          - values: ['2.2']

      - file-name: "reg_number"
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
        check-type: none
        runner-options: [compile-only]
        description: Check fadd2 with correct register numbers.
        code-template: |
          #
              fadd2 %s
        cases:
          - values: [v0]
          - values: [v16]
          - values: [v128]
          - values: [v255]

      - file-name: "calc"
        isa:
            instructions:
              - sig: fadd2 v:in:f32
                acc: inout:f32
                format: [op_v_8]
        check-type: check-positive
        description: Check fadd2 with various values.
        tags: ['tsan', 'irtoc_ignore']
        code-template: |
            #
                fldai %s
                fmovi v0, %s
                fadd2 v0
                fmovi v1, %s
                fcmpg v1
        cases:
            - values:
                - "-0.150508"
                - "0.189967"
                - "0.039459005"
            - values:
                - "0.099515"
                - "0.037194"
                - "0.136709"
            - values:
                - "0.038831"
                - "-0.466269"
                - "-0.427438"
            - values:
                - "-0.117858"
                - "-0.410644"
                - "-0.528502"
            - values:
                - "0.233251"
                - "0.093035"
                - "0.32628602"
            - values:
                - "-0.363069"
                - "-0.188132"
                - "-0.551201"
            - values:
                - "0.100352"
                - "0.235968"
                - "0.33631998"
            - values:
                - "-0.223127"
                - "-0.218416"
                - "-0.44154298"
            - values:
                - "0.185290"
                - "0.484167"
                - "0.669457"
            - values:
                - "-0.475417"
                - "0.082336"
                - "-0.39308098"
            - values:
                - "2.75991e-36"
                - "-1.94471e-36"
                - "8.151998e-37"
            - values:
                - "2.514854e14"
                - "1.918314e15"
                - "2.16979936e15"
            - values:
                - "-9.871449e19"
                - "4.913647e20"
                - "3.926502e20"
            - values:
                - "4.636161e-8"
                - "-6.780937e-9"
                - "3.9580673e-8"
            - values:
                - "-2.55497e19"
                - "4.064694e19"
                - "1.509724e19"

      - file-name: "type"
        isa:
            instructions:
              - sig: fadd2 v:in:f32
                acc: inout:f32
                format: [op_v_8]
            verification:
              - acc_type
              - v1_type
        tags: ['verifier']
        runner-options: ['verifier-failure', 'verifier-config']
        header-template: []
        code-template: |
          #
          .record A {}
          .record B {}
          .record panda.String <external>
          .record panda.Object <external>
          .function i32 main() {
              %s
              *s
              fadd2 v0
        check-type: exit-positive
        description: Check 'fadd2' with incorrect register and accumulator type.
        template-cases:
          - values:
              - movi v0, 0
          - values:
              - movi.64 v0, 0
          - values:
              - fmovi v0, 0
            exclude: [val]
          - values:
              - fmovi.64 v0, 0
          - values:
              - |
                #
                    lda.type B
                    sta.obj v0
          - values:
              - |
                #
                    lda.type B[]
                    sta.obj v0
          - values:
              - |
                #
                    lda.type panda.String
                    sta.obj v0
          - values:
              - |
                #
                    lda.str "string"
                    sta.obj v0
          - values:
              - |
                #
                    movi v0, 10
                    newarr v0, v0, i32[]
          - values:
              - mov.null v0

        cases:
          - values:
              - ldai 0
          - values:
              - ldai.64 0
          - values:
              - fldai 0
            id: val
          - values:
              - fldai.64 0
          - values:
              - |
                #
                    lda.type A
          - values:
              - |
                #
                    lda.type A[]
          - values:
              - |
                #
                    lda.type panda.String
          - values:
              - |
                #
                    lda.str "string"
          - values:
              - |
                #
                    movi v1, 10
                    newarr v1, v1, f32[]
                    lda.obj v1
          - values:
              - lda.null

      - file-name: uninitialized_regs
        isa:
          instructions:
            - sig: fadd2 v:in:f32
              acc: inout:f32
              format: [op_v_8]
        description: Check 'fadd2' with uninitialized register and accumulator.
        tags: ['verifier']
        runner-options: ['verifier-failure', 'verifier-config']
        code-template: |
            #
                %s
                *s
                fadd2 %s
        check-type: exit-positive
        template-cases:
          - values:
              - ''
              - v0
          - values:
              - fmovi v0, 0
              - v0
            exclude: [init]
          - values:
              - ''
              - v7
          - values:
              - ''
              - v15
          - values:
              - fmovi v15, 0
              - v15
            exclude: [init]
          - values:
              - ''
              - v128
          - values:
              - fmovi v128, 0
              - v128
            exclude: [init]
          - values:
              - ''
              - v255
          - values:
              - fmovi v255, 0
              - v255
            exclude: [init]
        cases:
          - values:
              - ''
          - values:
              - fldai 0
            id: init