OSDN Git Service

* optabs.c (no_conflict_move_test): Check if a result of a
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
index 6f5716e..31212cb 100644 (file)
@@ -59,7 +59,7 @@ optab optab_table[OTI_MAX];
 rtx libfunc_table[LTI_MAX];
 
 /* Tables of patterns for converting one mode to another.  */
-convert_optab convert_optab_table[CTI_MAX];
+convert_optab convert_optab_table[COI_MAX];
 
 /* Contains the optab used for each rtx code.  */
 optab code_to_optab[NUM_RTX_CODE + 1];
@@ -349,8 +349,8 @@ optab_for_tree_code (enum tree_code code, tree type)
    this may or may not be TARGET.  */
 
 rtx
-expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0, 
-                  rtx op1, rtx op2, rtx target, int unsignedp) 
+expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
+                  rtx op1, rtx op2, rtx target, int unsignedp)
 {
   int icode = (int) ternary_optab->handlers[(int) mode].insn_code;
   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
@@ -377,7 +377,7 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
   if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
     xop0 = convert_modes (mode0,
                           GET_MODE (op0) != VOIDmode
-                          ? GET_MODE (op0) 
+                          ? GET_MODE (op0)
                           : mode,
                           xop0, unsignedp);
 
@@ -397,23 +397,23 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
 
   /* Now, if insn's predicates don't allow our operands, put them into
      pseudo regs.  */
-  
+
   if (!insn_data[icode].operand[1].predicate (xop0, mode0)
-      && mode0 != VOIDmode) 
+      && mode0 != VOIDmode)
     xop0 = copy_to_mode_reg (mode0, xop0);
-  
+
   if (!insn_data[icode].operand[2].predicate (xop1, mode1)
       && mode1 != VOIDmode)
     xop1 = copy_to_mode_reg (mode1, xop1);
-    
+
   if (!insn_data[icode].operand[3].predicate (xop2, mode2)
       && mode2 != VOIDmode)
     xop2 = copy_to_mode_reg (mode2, xop2);
-    
+
   pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
-    
+
   emit_insn (pat);
-  return temp; 
+  return temp;
 }
 
 
@@ -998,6 +998,28 @@ expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
   return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
 }
 
+
+/* Return whether OP0 and OP1 should be swapped when expanding a commutative
+   binop.  Order them according to commutative_operand_precedence and, if
+   possible, try to put TARGET first.  */
+static bool
+swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
+{
+  int op0_prec = commutative_operand_precedence (op0);
+  int op1_prec = commutative_operand_precedence (op1);
+
+  if (op0_prec < op1_prec)
+    return true;
+
+  if (op0_prec > op1_prec)
+    return false;
+
+  /* With equal precedence, both orders are ok, but try to put the
+     target first.  */
+  return target && rtx_equal_p (op1, target);
+}
+
+
 /* Generate code to perform an operation specified by BINOPTAB
    on operands OP0 and OP1, with result having machine-mode MODE.
 
@@ -1030,21 +1052,6 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   class = GET_MODE_CLASS (mode);
 
-  if (flag_force_mem)
-    {
-      /* Load duplicate non-volatile operands once.  */
-      if (rtx_equal_p (op0, op1) && ! volatile_refs_p (op0))
-       {
-         op0 = force_not_mem (op0);
-         op1 = op0;
-       }
-      else
-       {
-         op0 = force_not_mem (op0);
-         op1 = force_not_mem (op1);
-       }
-    }
-
   /* If subtracting an integer constant, convert this into an addition of
      the negated constant.  */
 
@@ -1075,10 +1082,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
   /* Record where to delete back to if we backtrack.  */
   last = get_last_insn ();
 
-  /* If operation is commutative,
-     try to make the first operand a register.
-     Even better, try to make it the same as the target.
-     Also try to make the last operand a constant.  */
+  /* If operation is commutative, canonicalize the order of the operands.  */
   if (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
       || binoptab == smul_widen_optab
       || binoptab == umul_widen_optab
@@ -1086,13 +1090,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
       || binoptab == umul_highpart_optab)
     {
       commutative_op = 1;
-
-      if (((target == 0 || REG_P (target))
-          ? ((REG_P (op1)
-              && !REG_P (op0))
-             || target == op1)
-          : rtx_equal_p (op1, target))
-         || GET_CODE (op0) == CONST_INT)
+      if (swap_commutative_operands_with_target (target, op0, op1))
        {
          temp = op1;
          op1 = op0;
@@ -1199,7 +1197,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       if (temp != 0)
        {
-         if (GET_MODE_CLASS (mode) == MODE_INT)
+         if (GET_MODE_CLASS (mode) == MODE_INT
+             && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+                                        GET_MODE_BITSIZE (GET_MODE (temp))))
            return gen_lowpart (mode, temp);
          else
            return convert_to_mode (mode, temp, unsignedp);
@@ -1246,7 +1246,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
                                 unsignedp, OPTAB_DIRECT);
            if (temp)
              {
-               if (class != MODE_INT)
+               if (class != MODE_INT
+                    || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+                                               GET_MODE_BITSIZE (wider_mode)))
                  {
                    if (target == 0)
                      target = gen_reg_rtx (mode);
@@ -1774,7 +1776,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
                                   unsignedp, methods);
              if (temp)
                {
-                 if (class != MODE_INT)
+                 if (class != MODE_INT
+                     || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+                                                GET_MODE_BITSIZE (wider_mode)))
                    {
                      if (target == 0)
                        target = gen_reg_rtx (mode);
@@ -1871,9 +1875,6 @@ expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
 
   class = GET_MODE_CLASS (mode);
 
-  if (flag_force_mem)
-    op0 = force_not_mem (op0);
-
   if (!targ0)
     targ0 = gen_reg_rtx (mode);
   if (!targ1)
@@ -1966,12 +1967,6 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
 
   class = GET_MODE_CLASS (mode);
 
-  if (flag_force_mem)
-    {
-      op0 = force_not_mem (op0);
-      op1 = force_not_mem (op1);
-    }
-
   /* If we are inside an appropriately-short loop and we are optimizing,
      force expensive constants into a register.  */
   if (CONSTANT_P (op0) && optimize
@@ -2210,7 +2205,7 @@ expand_parity (enum machine_mode mode, rtx op0, rtx target)
   return 0;
 }
 
-/* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain 
+/* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain
    conditions, VAL may already be a SUBREG against which we cannot generate
    a further SUBREG.  In this case, we expect forcing the value into a
    register will work around the situation.  */
@@ -2300,7 +2295,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
        {
          rtx targ_piece = operand_subword (target, i, 1, mode);
          rtx op0_piece = operand_subword_force (op0, i, mode);
-       
+
          if (i == word)
            {
              temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
@@ -2358,9 +2353,6 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
 
   class = GET_MODE_CLASS (mode);
 
-  if (flag_force_mem)
-    op0 = force_not_mem (op0);
-
   if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
     {
       int icode = (int) unoptab->handlers[(int) mode].insn_code;
@@ -2875,7 +2867,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
        {
          rtx targ_piece = operand_subword (target, i, 1, mode);
          rtx op0_piece = operand_subword_force (op0, i, mode);
-       
+
          if (i == word)
            {
              if (!op0_is_abs)
@@ -2922,7 +2914,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
   return target;
 }
 
-/* Expand the C99 copysign operation.  OP0 and OP1 must be the same 
+/* Expand the C99 copysign operation.  OP0 and OP1 must be the same
    scalar floating point mode.  Return NULL if we do not know how to
    expand the operation inline.  */
 
@@ -2987,19 +2979,12 @@ emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
 
   temp = target;
 
-  /* Sign and zero extension from memory is often done specially on
-     RISC machines, so forcing into a register here can pessimize
-     code.  */
-  if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
-    op0 = force_not_mem (op0);
-
   /* Now, if insn does not accept our operands, put them into pseudos.  */
 
   if (!insn_data[icode].operand[1].predicate (op0, mode0))
     op0 = copy_to_mode_reg (mode0, op0);
 
-  if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp))
-      || (flag_force_mem && MEM_P (temp)))
+  if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
     temp = gen_reg_rtx (GET_MODE (temp));
 
   pat = GEN_FCN (icode) (temp, op0);
@@ -3019,9 +3004,10 @@ struct no_conflict_data
   bool must_stay;
 };
 
-/* Called via note_stores by emit_no_conflict_block.  Set P->must_stay
-   if the currently examined clobber / store has to stay in the list of
-   insns that constitute the actual no_conflict block.  */
+/* Called via note_stores by emit_no_conflict_block and emit_libcall_block.
+   Set P->must_stay if the currently examined clobber / store has to stay
+   in the list of insns that constitute the actual no_conflict block /
+   libcall block.  */
 static void
 no_conflict_move_test (rtx dest, rtx set, void *p0)
 {
@@ -3036,13 +3022,20 @@ no_conflict_move_test (rtx dest, rtx set, void *p0)
     return;
   /* If this insn sets / clobbers a register that feeds one of the insns
      already in the list, this insn has to stay too.  */
-  else if (reg_mentioned_p (dest, PATTERN (p->first))
+  else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
+          || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
           || reg_used_between_p (dest, p->first, p->insn)
           /* Likewise if this insn depends on a register set by a previous
-             insn in the list.  */
+             insn in the list, or if it sets a result (presumably a hard
+             register) that is set or clobbered by a previous insn.
+             N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
+             SET_DEST perform the former check on the address, and the latter
+             check on the MEM.  */
           || (GET_CODE (set) == SET
               && (modified_in_p (SET_SRC (set), p->first)
-                  || modified_between_p (SET_SRC (set), p->first, p->insn))))
+                  || modified_in_p (SET_DEST (set), p->first)
+                  || modified_between_p (SET_SRC (set), p->first, p->insn)
+                  || modified_between_p (SET_DEST (set), p->first, p->insn))))
     p->must_stay = true;
 }
 
@@ -3262,23 +3255,27 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
       next = NEXT_INSN (insn);
 
       if (set != 0 && REG_P (SET_DEST (set))
-         && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
-         && (insn == insns
-             || ((! INSN_P(insns)
-                  || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
-                 && ! reg_used_between_p (SET_DEST (set), insns, insn)
-                 && ! modified_in_p (SET_SRC (set), insns)
-                 && ! modified_between_p (SET_SRC (set), insns, insn))))
+         && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
        {
-         if (PREV_INSN (insn))
-           NEXT_INSN (PREV_INSN (insn)) = next;
-         else
-           insns = next;
+         struct no_conflict_data data;
+
+         data.target = const0_rtx;
+         data.first = insns;
+         data.insn = insn;
+         data.must_stay = 0;
+         note_stores (PATTERN (insn), no_conflict_move_test, &data);
+         if (! data.must_stay)
+           {
+             if (PREV_INSN (insn))
+               NEXT_INSN (PREV_INSN (insn)) = next;
+             else
+               insns = next;
 
-         if (next)
-           PREV_INSN (next) = PREV_INSN (insn);
+             if (next)
+               PREV_INSN (next) = PREV_INSN (insn);
 
-         add_insn (insn);
+             add_insn (insn);
+           }
        }
 
       /* Some ports use a loop to copy large arguments onto the stack.
@@ -3415,21 +3412,6 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
 
   class = GET_MODE_CLASS (mode);
 
-  if (mode != BLKmode && flag_force_mem)
-    {
-      /* Load duplicate non-volatile operands once.  */
-      if (rtx_equal_p (x, y) && ! volatile_refs_p (x))
-       {
-         x = force_not_mem (x);
-         y = x;
-       }
-      else
-       {
-         x = force_not_mem (x);
-         y = force_not_mem (y);
-       }
-    }
-
   /* If we are inside an appropriately-short loop and we are optimizing,
      force expensive constants into a register.  */
   if (CONSTANT_P (x) && optimize
@@ -3475,6 +3457,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
          if (cmp_code == CODE_FOR_nothing)
            cmp_code = cmpstr_optab[cmp_mode];
          if (cmp_code == CODE_FOR_nothing)
+           cmp_code = cmpstrn_optab[cmp_mode];
+         if (cmp_code == CODE_FOR_nothing)
            continue;
 
          /* Must make sure the size fits the insn's mode.  */
@@ -3916,12 +3900,6 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
   if (icode == CODE_FOR_nothing)
     return 0;
 
-  if (flag_force_mem)
-    {
-      op2 = force_not_mem (op2);
-      op3 = force_not_mem (op3);
-    }
-
   if (!target)
     target = gen_reg_rtx (mode);
 
@@ -4050,12 +4028,6 @@ emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
   if (icode == CODE_FOR_nothing)
     return 0;
 
-  if (flag_force_mem)
-    {
-      op2 = force_not_mem (op2);
-      op3 = force_not_mem (op3);
-    }
-
   if (!target)
     target = gen_reg_rtx (mode);
 
@@ -4379,9 +4351,6 @@ expand_float (rtx to, rtx from, int unsignedp)
       rtx temp;
       REAL_VALUE_TYPE offset;
 
-      if (flag_force_mem)
-       from = force_not_mem (from);
-
       /* Look for a usable floating mode FMODE wider than the source and at
         least as wide as the target.  Using FMODE will avoid rounding woes
         with unsigned values greater than the signed maximum value.  */
@@ -4489,9 +4458,6 @@ expand_float (rtx to, rtx from, int unsignedp)
       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
        from = convert_to_mode (SImode, from, unsignedp);
 
-      if (flag_force_mem)
-       from = force_not_mem (from);
-
       libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
       gcc_assert (libfunc);
 
@@ -4609,9 +4575,6 @@ expand_fix (rtx to, rtx from, int unsignedp)
          lab1 = gen_label_rtx ();
          lab2 = gen_label_rtx ();
 
-         if (flag_force_mem)
-           from = force_not_mem (from);
-
          if (fmode != GET_MODE (from))
            from = convert_to_mode (fmode, from, 0);
 
@@ -4678,9 +4641,6 @@ expand_fix (rtx to, rtx from, int unsignedp)
       libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
       gcc_assert (libfunc);
 
-      if (flag_force_mem)
-       from = force_not_mem (from);
-
       start_sequence ();
 
       value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
@@ -5162,9 +5122,10 @@ init_optabs (void)
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
       movmem_optab[i] = CODE_FOR_nothing;
-      clrmem_optab[i] = CODE_FOR_nothing;
       cmpstr_optab[i] = CODE_FOR_nothing;
+      cmpstrn_optab[i] = CODE_FOR_nothing;
       cmpmem_optab[i] = CODE_FOR_nothing;
+      setmem_optab[i] = CODE_FOR_nothing;
 
       sync_add_optab[i] = CODE_FOR_nothing;
       sync_sub_optab[i] = CODE_FOR_nothing;
@@ -5346,7 +5307,7 @@ debug_optab_libfuncs (void)
       }
 
   /* Dump the conversion optabs.  */
-  for (i = 0; i < (int) CTI_MAX; ++i)
+  for (i = 0; i < (int) COI_MAX; ++i)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       for (k = 0; k < NUM_MACHINE_MODES; ++k)
        {
@@ -5441,7 +5402,7 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
     case GE_EXPR:
       code = unsignedp ? GEU : GE;
       break;
-      
+
     case UNORDERED_EXPR:
       code = UNORDERED;
       break;
@@ -5487,10 +5448,10 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
      ensures that condition is a relational operation.  */
   gcc_assert (COMPARISON_CLASS_P (cond));
 
-  rcode = get_rtx_code (TREE_CODE (cond), unsignedp); 
+  rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
   t_op0 = TREE_OPERAND (cond, 0);
   t_op1 = TREE_OPERAND (cond, 1);
-  
+
   /* Expand operands.  */
   rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), 1);
   rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), 1);
@@ -5498,7 +5459,7 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
   if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
       && GET_MODE (rtx_op0) != VOIDmode)
     rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
-  
+
   if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
       && GET_MODE (rtx_op1) != VOIDmode)
     rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
@@ -5507,8 +5468,8 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
 }
 
 /* Return insn code for VEC_COND_EXPR EXPR.  */
-  
-static inline enum insn_code 
+
+static inline enum insn_code
 get_vcond_icode (tree expr, enum machine_mode mode)
 {
   enum insn_code icode = CODE_FOR_nothing;
@@ -5545,11 +5506,11 @@ expand_vec_cond_expr (tree vec_cond_expr, rtx target)
   if (icode == CODE_FOR_nothing)
     return 0;
 
-  if (!target)
+  if (!target || !insn_data[icode].operand[0].predicate (target, mode))
     target = gen_reg_rtx (mode);
 
   /* Get comparison rtx.  First expand both cond expr operands.  */
-  comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0), 
+  comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
                                   unsignedp, icode);
   cc_op0 = XEXP (comparison, 0);
   cc_op1 = XEXP (comparison, 1);
@@ -5567,7 +5528,7 @@ expand_vec_cond_expr (tree vec_cond_expr, rtx target)
     rtx_op2 = force_reg (mode, rtx_op2);
 
   /* Emit instruction! */
-  emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2, 
+  emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
                              comparison, cc_op0,  cc_op1));
 
   return target;
@@ -5693,8 +5654,8 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
        }
     }
 
-  /* Without an appropriate setcc instruction, use a set of branches to 
-     get 1 and 0 stored into target.  Presumably if the target has a 
+  /* Without an appropriate setcc instruction, use a set of branches to
+     get 1 and 0 stored into target.  Presumably if the target has a
      STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt.  */
 
   label0 = gen_label_rtx ();
@@ -5787,7 +5748,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
 }
 
 /* This function generates the atomic operation MEM CODE= VAL.  In this
-   case, we do not care about any resulting value.  Returns NULL if we 
+   case, we do not care about any resulting value.  Returns NULL if we
    cannot generate the operation.  */
 
 rtx
@@ -5840,7 +5801,7 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
        val = convert_modes (mode, GET_MODE (val), val, 1);
       if (!insn_data[icode].operand[1].predicate (val, mode))
        val = force_reg (mode, val);
-      
+
       insn = GEN_FCN (icode) (mem, val);
       if (insn)
        {
@@ -5878,7 +5839,7 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
 
 /* This function generates the atomic operation MEM CODE= VAL.  In this
    case, we do care about the resulting value: if AFTER is true then
-   return the value MEM holds after the operation, if AFTER is false 
+   return the value MEM holds after the operation, if AFTER is false
    then return the value MEM holds before the operation.  TARGET is an
    optional place for the result value to be stored.  */
 
@@ -5973,7 +5934,7 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
        val = convert_modes (mode, GET_MODE (val), val, 1);
       if (!insn_data[icode].operand[2].predicate (val, mode))
        val = force_reg (mode, val);
-      
+
       insn = GEN_FCN (icode) (target, mem, val);
       if (insn)
        {
@@ -6038,7 +5999,7 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
 /* This function expands a test-and-set operation.  Ideally we atomically
    store VAL in MEM and return the previous value in MEM.  Some targets
    may not support this operation and only support VAL with the constant 1;
-   in this case while the return value will be 0/1, but the exact value 
+   in this case while the return value will be 0/1, but the exact value
    stored in MEM is target defined.  TARGET is an option place to stick
    the return value.  */