File: shift_ndep.c

package info (click to toggle)
valgrind 1%3A3.12.0~svn20160714-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 120,428 kB
  • ctags: 70,855
  • sloc: ansic: 674,645; exp: 26,134; xml: 21,574; asm: 7,570; cpp: 7,567; makefile: 7,380; sh: 6,188; perl: 5,855; haskell: 195
file content (42 lines) | stat: -rw-r--r-- 1,371 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "tests/asm.h"
#include <stdio.h>

/* Test whether a shift by zero properly preserves the CC_NDEP thunk. */

/* Check whether the carry flag is properly preserved by a variable
   shift when the shift amount happens to be zero. */
int shift_ndep( void )
{
  char shift_amt = 0;
  int x = -2;
  /* First we set the carry flag. Then we increment %x, which sets
     CC_OP to X86G_CC_OP_INCL and stores the carry (1) in
     CC_NDEP. Then we left shift %x by a variable amount that happens
     to be zero, which should leave both %x and all the flags
     unchanged. Then we add-with-carry 0 to %x, which (assuming the
     carry is still set as it should be) increments %x again. Thus the
     expected final value for x is -2 + 1 + 1 = 0.

     If instead the shift clears CC_NDEP (as it would legally do if
     the shift amount were non-zero), this will be interpeted as
     clearing the carry bit, so the adc will be a no-op and the final
     value of %x will instead be -1.
  */
  asm (
       "stc"                    "\n\t"
       "inc %[x]"               "\n\t"
       "shl %[shift_amt], %[x]" "\n\t"
       "adc $0, %[x]"           "\n\t"
       : [x] "+r" (x) : [shift_amt] "c" (shift_amt));
  return x;
}

int main ( void )
{
  int r = shift_ndep();
  if (r == 0)
    printf("Passed (%d).\n", r);
  else
    printf("Failed (%d).\n", r);
  return 0;
}