14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_IC_IC_BINARY_OP_H_
174514f5e3Sopenharmony_ci#define ECMASCRIPT_IC_IC_BINARY_OP_H_
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/ic/profile_type_info.h"
204514f5e3Sopenharmony_ci#include "ecmascript/interpreter/slow_runtime_stub.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
224514f5e3Sopenharmony_ci#include "ecmascript/property_attributes.h"
234514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h"
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_cinamespace panda::ecmascript {
264514f5e3Sopenharmony_cienum class BinaryType : uint8_t {
274514f5e3Sopenharmony_ci    NUMBER,
284514f5e3Sopenharmony_ci    NUMBER_GEN,
294514f5e3Sopenharmony_ci    STRING,
304514f5e3Sopenharmony_ci    STRING_GEN,
314514f5e3Sopenharmony_ci    GENERIC,
324514f5e3Sopenharmony_ci};
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ciclass ICBinaryOP {
354514f5e3Sopenharmony_cipublic:
364514f5e3Sopenharmony_ci    static inline JSTaggedValue AddWithTSType(JSThread *thread, JSTaggedValue left,
374514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
384514f5e3Sopenharmony_ci    {
394514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, AddWithTSType);
404514f5e3Sopenharmony_ci        BinaryType addType = static_cast<BinaryType>(argType.GetInt());
414514f5e3Sopenharmony_ci        switch (addType) {
424514f5e3Sopenharmony_ci            // Support cases, such as: int + double, int + int, double + double
434514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
444514f5e3Sopenharmony_ci                double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
454514f5e3Sopenharmony_ci                double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
464514f5e3Sopenharmony_ci                double ret = a0Double + a1Double;
474514f5e3Sopenharmony_ci                return JSTaggedValue(ret);
484514f5e3Sopenharmony_ci            }
494514f5e3Sopenharmony_ci            // Support cases, such as: number + null, undefined + null, boolean + number, etc.
504514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN: {
514514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
524514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
534514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, leftValue));
544514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
554514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, rightValue));
564514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci                JSTaggedNumber taggedValueA0 = JSTaggedValue::ToNumber(thread, primitiveA0);
594514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
604514f5e3Sopenharmony_ci                JSTaggedNumber taggedValueA1 = JSTaggedValue::ToNumber(thread, primitiveA1);
614514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
624514f5e3Sopenharmony_ci                double a0Double = taggedValueA0.GetNumber();
634514f5e3Sopenharmony_ci                double a1Double = taggedValueA1.GetNumber();
644514f5e3Sopenharmony_ci                return JSTaggedValue(a0Double + a1Double);
654514f5e3Sopenharmony_ci            }
664514f5e3Sopenharmony_ci            // Support case: string + string.
674514f5e3Sopenharmony_ci            case BinaryType::STRING: {
684514f5e3Sopenharmony_ci                JSHandle<EcmaString> stringA0 = JSHandle<EcmaString>(JSHandle<JSTaggedValue>(thread, left));
694514f5e3Sopenharmony_ci                JSHandle<EcmaString> stringA1 = JSHandle<EcmaString>(JSHandle<JSTaggedValue>(thread, right));
704514f5e3Sopenharmony_ci                EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1);
714514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
724514f5e3Sopenharmony_ci                return JSTaggedValue(ret);
734514f5e3Sopenharmony_ci            }
744514f5e3Sopenharmony_ci            // Support cases, such as: string + null, string + object, string + boolean, string + number, etc.
754514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN: {
764514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
774514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
784514f5e3Sopenharmony_ci                if (left.IsString()) {
794514f5e3Sopenharmony_ci                    JSHandle<EcmaString> stringA0 = JSHandle<EcmaString>(leftValue);
804514f5e3Sopenharmony_ci                    JSHandle<EcmaString> stringA1 = JSTaggedValue::ToString(thread, rightValue);
814514f5e3Sopenharmony_ci                    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
824514f5e3Sopenharmony_ci                    EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1);
834514f5e3Sopenharmony_ci                    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
844514f5e3Sopenharmony_ci                    return JSTaggedValue(ret);
854514f5e3Sopenharmony_ci                } else {
864514f5e3Sopenharmony_ci                    JSHandle<EcmaString> stringA0 = JSTaggedValue::ToString(thread, leftValue);
874514f5e3Sopenharmony_ci                    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
884514f5e3Sopenharmony_ci                    JSHandle<EcmaString> stringA1 = JSHandle<EcmaString>(rightValue);
894514f5e3Sopenharmony_ci                    EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1);
904514f5e3Sopenharmony_ci                    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
914514f5e3Sopenharmony_ci                    return JSTaggedValue(ret);
924514f5e3Sopenharmony_ci                }
934514f5e3Sopenharmony_ci            }
944514f5e3Sopenharmony_ci            // Some special cases, such as: object + undefined, object + boolean, etc.
954514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
964514f5e3Sopenharmony_ci                JSTaggedValue res = SlowRuntimeStub::Add2(thread, left, right);
974514f5e3Sopenharmony_ci                return res;
984514f5e3Sopenharmony_ci            }
994514f5e3Sopenharmony_ci            default: {
1004514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
1014514f5e3Sopenharmony_ci                UNREACHABLE();
1024514f5e3Sopenharmony_ci            }
1034514f5e3Sopenharmony_ci        }
1044514f5e3Sopenharmony_ci    }
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_ci    static inline JSTaggedValue SubWithTSType(JSThread *thread, JSTaggedValue left,
1074514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
1084514f5e3Sopenharmony_ci    {
1094514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, SubWithTSType);
1104514f5e3Sopenharmony_ci        BinaryType subType = static_cast<BinaryType>(argType.GetInt());
1114514f5e3Sopenharmony_ci        switch (subType) {
1124514f5e3Sopenharmony_ci            // Support int or number
1134514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
1144514f5e3Sopenharmony_ci                double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
1154514f5e3Sopenharmony_ci                double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
1164514f5e3Sopenharmony_ci                double ret = a0Double - a1Double;
1174514f5e3Sopenharmony_ci                return JSTaggedValue(ret);
1184514f5e3Sopenharmony_ci            }
1194514f5e3Sopenharmony_ci            // Support cases, such as: string like '2333', boolean, null
1204514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
1214514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
1224514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
1234514f5e3Sopenharmony_ci                JSTaggedNumber number0 = JSTaggedValue::ToNumber(thread, leftValue);
1244514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1254514f5e3Sopenharmony_ci                JSTaggedNumber number1 = JSTaggedValue::ToNumber(thread, rightValue);
1264514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1274514f5e3Sopenharmony_ci                auto ret = number0 - number1;
1284514f5e3Sopenharmony_ci                return JSTaggedValue(ret);
1294514f5e3Sopenharmony_ci            }
1304514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN:
1314514f5e3Sopenharmony_ci            case BinaryType::STRING:
1324514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN:
1334514f5e3Sopenharmony_ci            default: {
1344514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
1354514f5e3Sopenharmony_ci                UNREACHABLE();
1364514f5e3Sopenharmony_ci            }
1374514f5e3Sopenharmony_ci        }
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci    static inline JSTaggedValue MulWithTSType(JSThread *thread, JSTaggedValue left,
1404514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
1414514f5e3Sopenharmony_ci    {
1424514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, MulWithTSType);
1434514f5e3Sopenharmony_ci        BinaryType mulType = static_cast<BinaryType>(argType.GetInt());
1444514f5e3Sopenharmony_ci        switch (mulType) {
1454514f5e3Sopenharmony_ci            // Support int or number
1464514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
1474514f5e3Sopenharmony_ci                return JSTaggedValue(left.GetNumber() * right.GetNumber());
1484514f5e3Sopenharmony_ci            }
1494514f5e3Sopenharmony_ci            // Support cases, such as: string like '2333', boolean, null
1504514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
1514514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
1524514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
1534514f5e3Sopenharmony_ci                // 6. Let lnum be ToNumber(leftValue).
1544514f5e3Sopenharmony_ci                JSTaggedNumber primitiveA = JSTaggedValue::ToNumber(thread, leftValue);
1554514f5e3Sopenharmony_ci                // 7. ReturnIfAbrupt(lnum).
1564514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1574514f5e3Sopenharmony_ci                // 8. Let rnum be ToNumber(rightValue).
1584514f5e3Sopenharmony_ci                JSTaggedNumber primitiveB = JSTaggedValue::ToNumber(thread, rightValue);
1594514f5e3Sopenharmony_ci                // 9. ReturnIfAbrupt(rnum).
1604514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1614514f5e3Sopenharmony_ci                // 12.6.3.1 Applying the * Operator
1624514f5e3Sopenharmony_ci                return primitiveA * primitiveB;
1634514f5e3Sopenharmony_ci            }
1644514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN:
1654514f5e3Sopenharmony_ci            case BinaryType::STRING:
1664514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN:
1674514f5e3Sopenharmony_ci            default: {
1684514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
1694514f5e3Sopenharmony_ci                UNREACHABLE();
1704514f5e3Sopenharmony_ci            }
1714514f5e3Sopenharmony_ci        }
1724514f5e3Sopenharmony_ci    }
1734514f5e3Sopenharmony_ci
1744514f5e3Sopenharmony_ci    static inline JSTaggedValue DivWithTSType(JSThread *thread, JSTaggedValue left,
1754514f5e3Sopenharmony_ci                                             JSTaggedValue right, JSTaggedValue argType)
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, DivWithTSType);
1784514f5e3Sopenharmony_ci        BinaryType divType = static_cast<BinaryType>(argType.GetInt());
1794514f5e3Sopenharmony_ci        switch (divType) {
1804514f5e3Sopenharmony_ci            // Support int or number
1814514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
1824514f5e3Sopenharmony_ci                double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
1834514f5e3Sopenharmony_ci                double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
1844514f5e3Sopenharmony_ci                if (UNLIKELY(dRight == 0.0)) {
1854514f5e3Sopenharmony_ci                    if (dLeft == 0.0 || std::isnan(dLeft)) {
1864514f5e3Sopenharmony_ci                        return JSTaggedValue(base::NAN_VALUE);
1874514f5e3Sopenharmony_ci                    }
1884514f5e3Sopenharmony_ci                    uint64_t flagBit = ((base::bit_cast<uint64_t>(dLeft)) ^ (base::bit_cast<uint64_t>(dRight))) &
1894514f5e3Sopenharmony_ci                                        base::DOUBLE_SIGN_MASK;
1904514f5e3Sopenharmony_ci                    return JSTaggedValue(base::bit_cast<double>(
1914514f5e3Sopenharmony_ci                        flagBit ^ (base::bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
1924514f5e3Sopenharmony_ci                }
1934514f5e3Sopenharmony_ci                return JSTaggedValue(dLeft / dRight);
1944514f5e3Sopenharmony_ci            }
1954514f5e3Sopenharmony_ci            // Support special cases, such as: string like '2333', boolean, null
1964514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
1974514f5e3Sopenharmony_ci                auto res = SlowRuntimeStub::Div2(thread, left, right);
1984514f5e3Sopenharmony_ci                return res;
1994514f5e3Sopenharmony_ci            }
2004514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN:
2014514f5e3Sopenharmony_ci            case BinaryType::STRING:
2024514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN:
2034514f5e3Sopenharmony_ci            default: {
2044514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
2054514f5e3Sopenharmony_ci                UNREACHABLE();
2064514f5e3Sopenharmony_ci            }
2074514f5e3Sopenharmony_ci        }
2084514f5e3Sopenharmony_ci    }
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ci    static inline JSTaggedValue ModWithTSType(JSThread *thread, JSTaggedValue left,
2114514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
2124514f5e3Sopenharmony_ci    {
2134514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, ModWithTSType);
2144514f5e3Sopenharmony_ci        BinaryType modType = static_cast<BinaryType>(argType.GetInt());
2154514f5e3Sopenharmony_ci        switch (modType) {
2164514f5e3Sopenharmony_ci            // Support int or number
2174514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
2184514f5e3Sopenharmony_ci                double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
2194514f5e3Sopenharmony_ci                double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
2204514f5e3Sopenharmony_ci                if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
2214514f5e3Sopenharmony_ci                    return JSTaggedValue(base::NAN_VALUE);
2224514f5e3Sopenharmony_ci                }
2234514f5e3Sopenharmony_ci                if (dLeft == 0.0 || std::isinf(dRight)) {
2244514f5e3Sopenharmony_ci                    return JSTaggedValue(dLeft);
2254514f5e3Sopenharmony_ci                }
2264514f5e3Sopenharmony_ci                return JSTaggedValue(std::fmod(dLeft, dRight));
2274514f5e3Sopenharmony_ci            }
2284514f5e3Sopenharmony_ci            // Support special cases, such as: string like '2333', boolean, null
2294514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
2304514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
2314514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
2324514f5e3Sopenharmony_ci                JSTaggedNumber leftNumber = JSTaggedValue::ToNumber(thread, leftValue);
2334514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2344514f5e3Sopenharmony_ci                double dLeft = leftNumber.GetNumber();
2354514f5e3Sopenharmony_ci                JSTaggedNumber rightNumber = JSTaggedValue::ToNumber(thread, rightValue);
2364514f5e3Sopenharmony_ci                RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2374514f5e3Sopenharmony_ci                double dRight = rightNumber.GetNumber();
2384514f5e3Sopenharmony_ci                // 12.6.3.3 Applying the % Operator
2394514f5e3Sopenharmony_ci                if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
2404514f5e3Sopenharmony_ci                    return JSTaggedValue(base::NAN_VALUE);
2414514f5e3Sopenharmony_ci                }
2424514f5e3Sopenharmony_ci                if ((dLeft == 0.0) || std::isinf(dRight)) {
2434514f5e3Sopenharmony_ci                    return JSTaggedValue(dLeft);
2444514f5e3Sopenharmony_ci                }
2454514f5e3Sopenharmony_ci                return JSTaggedValue(std::fmod(dLeft, dRight));
2464514f5e3Sopenharmony_ci            }
2474514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN:
2484514f5e3Sopenharmony_ci            case BinaryType::STRING:
2494514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN:
2504514f5e3Sopenharmony_ci            default: {
2514514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
2524514f5e3Sopenharmony_ci                UNREACHABLE();
2534514f5e3Sopenharmony_ci            }
2544514f5e3Sopenharmony_ci        }
2554514f5e3Sopenharmony_ci    }
2564514f5e3Sopenharmony_ci
2574514f5e3Sopenharmony_ci    static inline void GetBitOPDate(JSThread *thread, JSTaggedValue left, JSTaggedValue right,
2584514f5e3Sopenharmony_ci                                    int32_t &opNumber0, int32_t &opNumber1, BinaryType opType)
2594514f5e3Sopenharmony_ci    {
2604514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, GetBitOPDate);
2614514f5e3Sopenharmony_ci        switch (opType) {
2624514f5e3Sopenharmony_ci            case BinaryType::NUMBER: {
2634514f5e3Sopenharmony_ci                opNumber0 =
2644514f5e3Sopenharmony_ci                    left.IsInt() ? left.GetInt() :
2654514f5e3Sopenharmony_ci                                   base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
2664514f5e3Sopenharmony_ci                opNumber1 =
2674514f5e3Sopenharmony_ci                    right.IsInt() ? right.GetInt() :
2684514f5e3Sopenharmony_ci                                    base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
2694514f5e3Sopenharmony_ci                break;
2704514f5e3Sopenharmony_ci            }
2714514f5e3Sopenharmony_ci            // Support special cases, such as: string like '2333', boolean, null
2724514f5e3Sopenharmony_ci            case BinaryType::GENERIC: {
2734514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> leftValue(thread, left);
2744514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue> rightValue(thread, right);
2754514f5e3Sopenharmony_ci                JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread,
2764514f5e3Sopenharmony_ci                                                                                        leftValue.GetTaggedValue());
2774514f5e3Sopenharmony_ci                JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread,
2784514f5e3Sopenharmony_ci                                                                                         rightValue.GetTaggedValue());
2794514f5e3Sopenharmony_ci                opNumber0 = taggedNumber0.GetInt();
2804514f5e3Sopenharmony_ci                opNumber1 = taggedNumber1.GetInt();
2814514f5e3Sopenharmony_ci                break;
2824514f5e3Sopenharmony_ci            }
2834514f5e3Sopenharmony_ci            case BinaryType::NUMBER_GEN:
2844514f5e3Sopenharmony_ci            case BinaryType::STRING:
2854514f5e3Sopenharmony_ci            case BinaryType::STRING_GEN:
2864514f5e3Sopenharmony_ci            default: {
2874514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this branch is unreachable";
2884514f5e3Sopenharmony_ci                UNREACHABLE();
2894514f5e3Sopenharmony_ci            }
2904514f5e3Sopenharmony_ci        }
2914514f5e3Sopenharmony_ci        return;
2924514f5e3Sopenharmony_ci    }
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_ci    static inline JSTaggedValue ShlWithTSType(JSThread *thread, JSTaggedValue left,
2954514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
2964514f5e3Sopenharmony_ci    {
2974514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, ShlWithTSType);
2984514f5e3Sopenharmony_ci        BinaryType shlType = static_cast<BinaryType>(argType.GetInt());
2994514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3004514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3014514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, shlType);
3024514f5e3Sopenharmony_ci        uint32_t shift =
3034514f5e3Sopenharmony_ci                static_cast<uint32_t>(opNumber1) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
3044514f5e3Sopenharmony_ci        using unsigned_type = std::make_unsigned_t<int32_t>;
3054514f5e3Sopenharmony_ci        auto ret =
3064514f5e3Sopenharmony_ci            static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift);  // NOLINT(hicpp-signed-bitwise)
3074514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3084514f5e3Sopenharmony_ci    }
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci    static inline JSTaggedValue ShrWithTSType(JSThread *thread, JSTaggedValue left,
3114514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
3124514f5e3Sopenharmony_ci    {
3134514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, ShrWithTSType);
3144514f5e3Sopenharmony_ci        BinaryType shrType = static_cast<BinaryType>(argType.GetInt());
3154514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3164514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3174514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, shrType);
3184514f5e3Sopenharmony_ci        uint32_t shift =
3194514f5e3Sopenharmony_ci                static_cast<uint32_t>(opNumber1) & 0x1f;     // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
3204514f5e3Sopenharmony_ci        auto ret = static_cast<int32_t>(opNumber0 >> shift);  // NOLINT(hicpp-signed-bitwise)
3214514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3224514f5e3Sopenharmony_ci    }
3234514f5e3Sopenharmony_ci
3244514f5e3Sopenharmony_ci    static inline JSTaggedValue AshrWithTSType(JSThread *thread, JSTaggedValue left,
3254514f5e3Sopenharmony_ci                                               JSTaggedValue right, JSTaggedValue argType)
3264514f5e3Sopenharmony_ci    {
3274514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, AshrWithTSType);
3284514f5e3Sopenharmony_ci        BinaryType ashrType = static_cast<BinaryType>(argType.GetInt());
3294514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3304514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3314514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, ashrType);
3324514f5e3Sopenharmony_ci        uint32_t shift =
3334514f5e3Sopenharmony_ci                static_cast<uint32_t>(opNumber1) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
3344514f5e3Sopenharmony_ci        using unsigned_type = std::make_unsigned_t<uint32_t>;
3354514f5e3Sopenharmony_ci        auto ret =
3364514f5e3Sopenharmony_ci            static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift);  // NOLINT(hicpp-signed-bitwise)
3374514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3384514f5e3Sopenharmony_ci    }
3394514f5e3Sopenharmony_ci
3404514f5e3Sopenharmony_ci    static inline JSTaggedValue AndWithTSType(JSThread *thread, JSTaggedValue left,
3414514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
3424514f5e3Sopenharmony_ci    {
3434514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, AndWithTSType);
3444514f5e3Sopenharmony_ci        BinaryType andType = static_cast<BinaryType>(argType.GetInt());
3454514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3464514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3474514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, andType);
3484514f5e3Sopenharmony_ci        // NOLINT(hicpp-signed-bitwise)
3494514f5e3Sopenharmony_ci        auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
3504514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3514514f5e3Sopenharmony_ci    }
3524514f5e3Sopenharmony_ci
3534514f5e3Sopenharmony_ci    static inline JSTaggedValue OrWithTSType(JSThread *thread, JSTaggedValue left,
3544514f5e3Sopenharmony_ci                                             JSTaggedValue right, JSTaggedValue argType)
3554514f5e3Sopenharmony_ci    {
3564514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, OrWithTSType);
3574514f5e3Sopenharmony_ci        BinaryType orType = static_cast<BinaryType>(argType.GetInt());
3584514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3594514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3604514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, orType);
3614514f5e3Sopenharmony_ci        // NOLINT(hicpp-signed-bitwise)
3624514f5e3Sopenharmony_ci        auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
3634514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3644514f5e3Sopenharmony_ci    }
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ci    static inline JSTaggedValue XorWithTSType(JSThread *thread, JSTaggedValue left,
3674514f5e3Sopenharmony_ci                                              JSTaggedValue right, JSTaggedValue argType)
3684514f5e3Sopenharmony_ci    {
3694514f5e3Sopenharmony_ci        INTERPRETER_TRACE(thread, XorWithTSType);
3704514f5e3Sopenharmony_ci        BinaryType xorType = static_cast<BinaryType>(argType.GetInt());
3714514f5e3Sopenharmony_ci        int32_t opNumber0 = 0;
3724514f5e3Sopenharmony_ci        int32_t opNumber1 = 0;
3734514f5e3Sopenharmony_ci        GetBitOPDate(thread, left, right, opNumber0, opNumber1, xorType);
3744514f5e3Sopenharmony_ci        // NOLINT(hicpp-signed-bitwise)
3754514f5e3Sopenharmony_ci        auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
3764514f5e3Sopenharmony_ci        return JSTaggedValue(ret);
3774514f5e3Sopenharmony_ci    }
3784514f5e3Sopenharmony_ci};
3794514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
3804514f5e3Sopenharmony_ci
3814514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_IC_IC_BINARY_OP_H_
382