1.6.3.1.1.1.2. Right shift
For the right shift, it is similar handling. Again, paramter ll is the lower part of the number being shifted, and hl is the high part, while count is the bits to shift. Then lv and hv hold the result. And arith if nonzero indicates it is arithmetic shifting; otherwise is logical shift.
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 }
For right shift, the bits vacated by the shift should be signed extended, just as below figure shows. So signmask is generated in different way. For arithmetic shifting and signed number, the hl is filled with 0xf (the sign extended); at line 437, expression (unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1) produces 1, and -1 by negating (it is 0xf..f in 2 compliement coding). While for logical shift or unsigned number, signmask is 0.
figure 4 Before right shift
figure 5 After right shift, bits vacated should be signed extended
1.6.3.1.1.1.2. Rotate shift
Other type of shift is rotate shift, the bits shifted out enter at othe side. The handling is demonstrated as below figure.
figure 6 rotate shift handling
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 }
Note that if count is negative, it is rotate left shift; otherwise it is rotate right shift.