1typedef unsigned long long uint64_t;
2void abort (void);
3
4#define BASE 0x1234567812345678ull
5
6#define DEF_BBIT_TAKEN(BRANCH_IF, BIT)					\
7  int bbit_is_taken_##BRANCH_IF##_##BIT (volatile uint64_t *p)		\
8  {									\
9    int ret;								\
10    asm (".set push				\n\t"			\
11	 ".set noreorder			\n\t"			\
12	 "bbit" #BRANCH_IF " %1, " #BIT ", 1f	\n\t"			\
13	 "nop					\n\t"			\
14	 "li %0, 0				\n\t"			\
15	 "b 2f					\n\t"			\
16	 "nop					\n\t"			\
17	 "1:					\n\t"			\
18	 "li %0, 1				\n\t"			\
19	 "2:					\n\t"			\
20	 ".set pop"							\
21	 : "=r"(ret) : "r"(*p));					\
22    return ret;								\
23  }									\
24  volatile uint64_t taken_##BRANCH_IF##_##BIT =				\
25    BASE & (~(1ull << BIT)) | ((uint64_t) BRANCH_IF << BIT);		\
26  volatile uint64_t not_taken_##BRANCH_IF##_##BIT =			\
27    BASE & (~(1ull << BIT)) | (((uint64_t) !BRANCH_IF) << BIT);
28
29DEF_BBIT_TAKEN (0, 10);
30DEF_BBIT_TAKEN (0, 36);
31DEF_BBIT_TAKEN (1, 20);
32DEF_BBIT_TAKEN (1, 49);
33
34#define EXPECT(X) if (!(X)) abort ();
35
36main ()
37{
38  EXPECT (bbit_is_taken_0_10 (&taken_0_10));
39  EXPECT (!bbit_is_taken_0_10 (&not_taken_0_10));
40
41  EXPECT (bbit_is_taken_0_36 (&taken_0_36));
42  EXPECT (!bbit_is_taken_0_36 (&not_taken_0_36));
43
44  EXPECT (bbit_is_taken_1_20 (&taken_1_20));
45  EXPECT (!bbit_is_taken_1_20 (&not_taken_1_20));
46
47  EXPECT (bbit_is_taken_1_49 (&taken_1_49));
48  EXPECT (!bbit_is_taken_1_49 (&not_taken_1_49));
49}
50