| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 1 | /* ===-- ctzsi2.c - Implement __ctzsi2 -------------------------------------=== | 
 | 2 |  * | 
 | 3 |  *                     The LLVM Compiler Infrastructure | 
 | 4 |  * | 
| Howard Hinnant | 9ad441f | 2010-11-16 22:13:33 +0000 | [diff] [blame] | 5 |  * This file is dual licensed under the MIT and the University of Illinois Open | 
 | 6 |  * Source Licenses. See LICENSE.TXT for details. | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 7 |  * | 
 | 8 |  * ===----------------------------------------------------------------------=== | 
 | 9 |  * | 
 | 10 |  * This file implements __ctzsi2 for the compiler_rt library. | 
 | 11 |  * | 
 | 12 |  * ===----------------------------------------------------------------------=== | 
 | 13 |  */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 14 |  | 
 | 15 | #include "int_lib.h" | 
 | 16 |  | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 17 | /* Returns: the number of trailing 0-bits */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 18 |  | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 19 | /* Precondition: a != 0 */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 20 |  | 
| Anton Korobeynikov | 1c5f89b | 2011-04-19 17:52:09 +0000 | [diff] [blame] | 21 | COMPILER_RT_ABI si_int | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 22 | __ctzsi2(si_int a) | 
 | 23 | { | 
 | 24 |     su_int x = (su_int)a; | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 25 |     si_int t = ((x & 0x0000FFFF) == 0) << 4;  /* if (x has no small bits) t = 16 else 0 */ | 
 | 26 |     x >>= t;           /* x = [0 - 0xFFFF] + higher garbage bits */ | 
 | 27 |     su_int r = t;       /* r = [0, 16]  */ | 
 | 28 |     /* return r + ctz(x) */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 29 |     t = ((x & 0x00FF) == 0) << 3; | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 30 |     x >>= t;           /* x = [0 - 0xFF] + higher garbage bits */ | 
 | 31 |     r += t;            /* r = [0, 8, 16, 24] */ | 
 | 32 |     /* return r + ctz(x) */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 33 |     t = ((x & 0x0F) == 0) << 2; | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 34 |     x >>= t;           /* x = [0 - 0xF] + higher garbage bits */ | 
 | 35 |     r += t;            /* r = [0, 4, 8, 12, 16, 20, 24, 28] */ | 
 | 36 |     /* return r + ctz(x) */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 37 |     t = ((x & 0x3) == 0) << 1; | 
 | 38 |     x >>= t; | 
| Edward O'Callaghan | 37a6a45 | 2009-08-07 20:30:09 +0000 | [diff] [blame] | 39 |     x &= 3;            /* x = [0 - 3] */ | 
 | 40 |     r += t;            /* r = [0 - 30] and is even */ | 
 | 41 |     /* return r + ctz(x) */ | 
 | 42 |  | 
 | 43 | /*  The branch-less return statement below is equivalent | 
 | 44 |  *  to the following switch statement: | 
 | 45 |  *     switch (x) | 
 | 46 |  *    { | 
 | 47 |  *     case 0: | 
 | 48 |  *         return r + 2; | 
 | 49 |  *     case 2: | 
 | 50 |  *         return r + 1; | 
 | 51 |  *     case 1: | 
 | 52 |  *     case 3: | 
 | 53 |  *         return r; | 
 | 54 |  *     } | 
 | 55 |  */ | 
| Daniel Dunbar | b3a6901 | 2009-06-26 16:47:03 +0000 | [diff] [blame] | 56 |     return r + ((2 - (x >> 1)) & -((x & 1) == 0)); | 
 | 57 | } |