shift_ndep.c revision 1b6def82d703a18802c74d9f9a7a9cc35f82ad6a
1#include "tests/asm.h"
2#include <stdio.h>
3
4/* Test whether a shift by zero properly preserves the CC_NDEP thunk. */
5
6/* Check whether the carry flag is properly preserved by a variable
7   shift when the shift amount happens to be zero. */
8int shift_ndep( void )
9{
10  char shift_amt = 0;
11  int x = -2;
12  /* First we set the carry flag. Then we increment %x, which sets
13     CC_OP to X86G_CC_OP_INCL and stores the carry (1) in
14     CC_NDEP. Then we left shift %x by a variable amount that happens
15     to be zero, which should leave both %x and all the flags
16     unchanged. Then we add-with-carry 0 to %x, which (assuming the
17     carry is still set as it should be) increments %x again. Thus the
18     expected final value for x is -2 + 1 + 1 = 0.
19
20     If instead the shift clears CC_NDEP (as it would legally do if
21     the shift amount were non-zero), this will be interpeted as
22     clearing the carry bit, so the adc will be a no-op and the final
23     value of %x will instead be -1.
24  */
25  asm (
26       "stc"                    "\n\t"
27       "inc %[x]"               "\n\t"
28       "shl %[shift_amt], %[x]" "\n\t"
29       "adc $0, %[x]"           "\n\t"
30       : [x] "+r" (x) : [shift_amt] "c" (shift_amt));
31  return x;
32}
33
34int main ( void )
35{
36  int r = shift_ndep();
37  if (r == 0)
38    printf("Passed (%d).\n", r);
39  else
40    printf("Failed (%d).\n", r);
41  return 0;
42}
43