GCC-3.4.6源代码学习笔记(10续2)

1.6.3.1.1.1.2.              右移

右移的操作是类似的。同样在下面的函数中,参数ll是被移位数的低位部分,而hl是高位部分,count则是要移动的位数,必须为正数,计算结果存放在lvhv中,arith非零指明是进行算术右移,否则为逻辑右移。

 

428  void

429  rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,    in fold-const.c

430                HOST_WIDE_INT count, unsigned int prec,

431                unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,

432                int arith)

433  {

434    unsigned HOST_WIDE_INT signmask;

435 

436    signmask = (arith

437               ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))

438               : 0);

439 

440  #ifdef SHIFT_COUNT_TRUNCATED

441    if (SHIFT_COUNT_TRUNCATED)

442      count %= prec;

443  #endif

444 

445    if (count >= 2 * HOST_BITS_PER_WIDE_INT)

446    {

447      /* Shifting by the host word size is undefined according to the

448        ANSI standard, so we must handle this as a special case.  */

449      *hv = 0;

450      *lv = 0;

451    }

452    else if (count >= HOST_BITS_PER_WIDE_INT)

453    {

454      *hv = 0;

455      *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);

456    }

457    else

458    {

459      *hv = (unsigned HOST_WIDE_INT) h1 >> count;

460      *lv = ((l1 >> count)

461        | ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));

462    }

463 

464    /* Zero / sign extend all bits that are beyond the precision.  */

465 

466    if (count >= (HOST_WIDE_INT)prec)

467    {

468      *hv = signmask;

469      *lv = signmask;

470    }

471    else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT)

472      ;

473    else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)

474    {

475      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));

476      *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);

477    }

478    else

479    {

480      *hv = signmask;

481      *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));

482      *lv |= signmask << (prec - count);

483    }

484  }

 

对于向右移位,移位空出的有效位需要被符号位填充,所下图所示。因此signmask有不同的产生方法。对于算术右移和有符号数,hl填充了0xf (符号位扩展),437行的表达式 (unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1) 的值是1,取反后是-1(其2进制补码为0xff..ff)。而对于逻辑右移或者无符号数,signmask则为0

GCC-3.4.6源代码学习笔记(10续2)_第1张图片

 

4向右移位前

 

 

 

5向右移位后,空出的有效位须被符号位填充

1.6.3.1.1.1.3.              循环移位

另一种移位是循环移位,从一端移出的位从另一端移入。下图显示了实际的处理过程。

 

 

 

6循环移位

 

 

 

491  void

492  lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, in fold-const.c

493               HOST_WIDE_INT count, unsigned int prec,

494               unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)

495  {

496    unsigned HOST_WIDE_INT s1l, s2l;

497    HOST_WIDE_INT s1h, s2h;

498 

499    count %= prec;

500    if (count < 0)

501      count += prec;

502 

503    lshift_double (l1, h1, count, prec, &s1l, &s1h, 0);

504    rshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);

505    *lv = s1l | s2l;

506    *hv = s1h | s2h;

507  }

 

注意当count是负数是,做的就是循环左移,否则为循环右移。

 

 

你可能感兴趣的:(GCC-3.4.6源代码学习笔记(10续2))