text: /*
   * Copyright (C) 2019 Intel Corporation. All rights reserved.
   * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
   */
  
  #include "simd_bitwise_ops.h"
  #include "../aot_emit_exception.h"
  #include "../../aot/aot_runtime.h"
  
  static bool
  v128_bitwise_two_component(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             V128Bitwise bitwise_op)
  {
      LLVMValueRef vector1, vector2, result;
  
      POP_V128(vector2);
      POP_V128(vector1);
  
      switch (bitwise_op) {
          case V128_AND:
              if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
                                          "and"))) {
                  HANDLE_FAILURE("LLVMBuildAnd");
                  goto fail;
              }
              break;
          case V128_OR:
              if (!(result =
                        LLVMBuildOr(comp_ctx->builder, vector1, vector2, "or"))) {
                  HANDLE_FAILURE("LLVMBuildAnd");
                  goto fail;
              }
              break;
          case V128_XOR:
              if (!(result = LLVMBuildXor(comp_ctx->builder, vector1, vector2,
                                          "xor"))) {
                  HANDLE_FAILURE("LLVMBuildAnd");
                  goto fail;
              }
              break;
          case V128_ANDNOT:
          {
              /* v128.and(a, v128.not(b)) */
              if (!(vector2 = LLVMBuildNot(comp_ctx->builder, vector2, "not"))) {
                  HANDLE_FAILURE("LLVMBuildNot");
                  goto fail;
              }
  
              if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
                                          "and"))) {
                  HANDLE_FAILURE("LLVMBuildAnd");
                  goto fail;
              }
  
              break;
          }
          default:
              bh_assert(0);
              goto fail;
      }
  
      PUSH_V128(result);
      return true;
  fail:
      return false;
  }
  
  static bool
  v128_bitwise_not(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  {
      LLVMValueRef vector, result;
  
      POP_V128(vector);
  
      if (!(result = LLVMBuildNot(comp_ctx->builder, vector, "not"))) {
          HANDLE_FAILURE("LLVMBuildNot");
          goto fail;
      }
  
      PUSH_V128(result);
      return true;
  fail:
      return false;
  }
  
  /* v128.or(v128.and(v1, c), v128.and(v2, v128.not(c))) */
  static bool
  v128_bitwise_bitselect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  {
      LLVMValueRef vector1, vector2, vector3, result;
  
      POP_V128(vector3);
      POP_V128(vector2);
      POP_V128(vector1);
  
      if (!(vector1 =
                LLVMBuildAnd(comp_ctx->builder, vector1, vector3, "a_and_c"))) {
          HANDLE_FAILURE("LLVMBuildAdd");
          goto fail;
      }
  
      if (!(vector3 = LLVMBuildNot(comp_ctx->builder, vector3, "not_c"))) {
          HANDLE_FAILURE("LLVMBuildNot");
          goto fail;
      }
  
      if (!(vector2 =
                LLVMBuildAnd(comp_ctx->builder, vector2, vector3, "b_and_c"))) {
          HANDLE_FAILURE("LLVMBuildAdd");
          goto fail;
      }
  
      if (!(result =
                LLVMBuildOr(comp_ctx->builder, vector1, vector2, "a_or_b"))) {
          HANDLE_FAILURE("LLVMBuildOr");
          goto fail;
      }
  
      PUSH_V128(result);
  
      return true;
  fail:
      return false;
  }
  
  bool
  aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx,
                                AOTFuncContext *func_ctx, V128Bitwise bitwise_op)
  {
      switch (bitwise_op) {
          case V128_AND:
          case V128_OR:
          case V128_XOR:
          case V128_ANDNOT:
              return v128_bitwise_two_component(comp_ctx, func_ctx, bitwise_op);
          case V128_NOT:
              return v128_bitwise_not(comp_ctx, func_ctx);
          case V128_BITSELECT:
              return v128_bitwise_bitselect(comp_ctx, func_ctx);
          default:
              bh_assert(0);
              return false;
      }
  }
  