1.6.3.1.1.1.2. 右移
右移的操作是类似的。同样在下面的函数中,参数ll是被移位数的低位部分,而hl是高位部分,count则是要移动的位数,必须为正数,计算结果存放在lv和hv中,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。
图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是负数是,做的就是循环左移,否则为循环右移。