[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-bugs-dist
Subject:    [Bug 243404] Port to zSeries
From:       Florian Krohm <britzel () acm ! org>
Date:       2011-02-15 4:23:14
Message-ID: 20110215042314.8980B7CE7C () immanuel ! kde ! org
[Download RAW message or body]

https://bugs.kde.org/show_bug.cgi?id=243404





--- Comment #46 from Florian Krohm <britzel acm org>  2011-02-15 05:23:03 ---
(In reply to comment #42)
> 
> +s390_irgen_FLOGR: "Note, that the Iop_Shl64 and
> +      Iop_Shr64 semantics will preserve the value-to-be-shifted if the
> +      shift-amount equals or is larger than the width of
> value-to-be-shifted"
> Wrong reason: The IR definition says that the behavior of these primops is
> undefined in out of range shift cases -- regardless of what your
> back end might do with them.
> 

OK, here is an updated version of s390_irgrn_FLOGR that avoids the undefined
behaviour.

HChar *
s390_irgen_FLOGR(UChar r1, UChar r2)
{
   IRTemp input    = newTemp(Ity_I64);
   IRTemp not_zero = newTemp(Ity_I64);
   IRTemp tmpnum   = newTemp(Ity_I64);
   IRTemp num      = newTemp(Ity_I64);
   IRTemp shift_amount = newTemp(Ity_I8);

   /* We use the "count leading zeroes" operator because the number of
      leading zeroes is identical with the bit position of the first '1' bit.
      However, that operator does not work when the input value is zero.
      Therefore, we set the LSB of the input value to 1 and use Clz64 on
      the modified value. If input == 0, then the result is 64. Otherwise,
      the result of Clz64 is what we want. */

   assign(input, get_gpr_dw0(r2));
   assign(not_zero, binop(Iop_Or64, mkexpr(input), mkU64(1)));
   assign(tmpnum, unop(Iop_Clz64, mkexpr(not_zero)));

   /* num = (input == 0) ? 64 : tmpnum */
   assign(num, mkite(binop(Iop_CmpEQ64, mkexpr(input), mkU64(0)),
                     /* == 0 */ mkU64(64),
                     /* != 0 */ mkexpr(tmpnum)));

   put_gpr_dw0(r1, mkexpr(num));

   /* Set the leftmost '1' bit of the input value to zero. The general scheme
      is to first shift the input value by NUM + 1 bits to the left which
      causes the leftmost '1' bit to disappear. Then we shift logically to
      the right by NUM + 1 bits. Because the semantics of Iop_Shl64 and
      Iop_Shr64 are undefined if the shift-amount is greater than or equal to
      the width of the value-to-be-shifted, we need to special case 
      NUM + 1 >= 64. This is equivalent to INPUT != 0 && INPUT != 1.
      For both such INPUT values the result will be 0. */

   assign(shift_amount, unop(Iop_64to8, binop(Iop_Add64, mkexpr(num),
                          mkU64(1))));

   put_gpr_dw0(r1 + 1,
           mkite(binop(Iop_CmpLE64U, mkexpr(input), mkU64(1)),
             /* == 0 || == 1*/ mkU64(0),
             /* otherwise */
             binop(Iop_Shr64,
               binop(Iop_Shl64, mkexpr(input),
                 mkexpr(shift_amount)),
               mkexpr(shift_amount))));

   /* Compare the original value as an unsigned integer with 0. */
   s390_cc_thunk_put2(S390_CC_OP_UNSIGNED_COMPARE, input,
                      mktemp(Ity_I64, mkU64(0)), False);

   return "flogr";
}

-- 
Configure bugmail: https://bugs.kde.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all bug changes.
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic