1#include <stdio.h>
2#include "opcodes.h"
3
4/* The FLOGR insn reads from register R2 and writes to register R1 and
5   R1 + 1. So we need to distinguish three cases:
6
7   (1) All three registers R1, R1 + 1, and R2 are distinct
8   (2) R2 == R1
9   (3) R2 == R1 + 1
10
11   These are tested by flogr1, flogr2, and flogr3, respectively. */
12
13/* Call FLOGR on INPUT. The results are returned through the parms. */
14
15/* R2 != R1 && R2 != R1 + 1 */
16void
17flogr1(unsigned long input, unsigned long *bitpos, unsigned long *modval,
18       unsigned int *cc)
19{
20   unsigned int psw;
21   register unsigned long value asm("4") = input;
22
23   asm volatile ( FLOGR(2,4)
24                  "ipm   %[psw]\n\t"
25                  "stg   2, %[bitpos]\n\t"
26                  "stg   3, %[modval]\n\t"
27                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
28                    [psw]"=d"(psw)
29                  : [val] "d"(value)
30                  : "2", "3", "cc");
31
32   *cc = psw >> 28;
33#if 0
34   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
35          value, *bitpos, *modval, *cc);
36#endif
37}
38
39/* R2 == R1 */
40void
41flogr2(unsigned long input, unsigned long *bitpos, unsigned long *modval,
42       unsigned int *cc)
43{
44   unsigned int psw;
45   register unsigned long value asm("2") = input;
46
47   asm volatile ( FLOGR(2,2)
48                  "ipm   %[psw]\n\t"
49                  "stg   2, %[bitpos]\n\t"
50                  "stg   3, %[modval]\n\t"
51                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
52                    [psw]"=d"(psw), [val] "+d"(value)
53                  :
54                  : "3", "cc");
55
56   *cc = psw >> 28;
57#if 0
58   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
59          value, *bitpos, *modval, *cc);
60#endif
61}
62
63/* R2 == R1 + 1 */
64void
65flogr3(unsigned long input, unsigned long *bitpos, unsigned long *modval,
66       unsigned int *cc)
67{
68   unsigned int psw;
69   register unsigned long value asm("3") = input;
70
71   asm volatile ( FLOGR(2,3)
72                  "ipm   %[psw]\n\t"
73                  "stg   2, %[bitpos]\n\t"
74                  "stg   3, %[modval]\n\t"
75                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
76                    [psw]"=d"(psw), [val] "+d"(value)
77                  :
78                  : "2", "cc");
79
80   *cc = psw >> 28;
81#if 0
82   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
83          value, *bitpos, *modval, *cc);
84#endif
85}
86
87void
88runtest(void (*func)(unsigned long, unsigned long *, unsigned long *,
89                     unsigned int *))
90{
91   unsigned long bitpos, modval, value;
92   unsigned int cc;
93   int i;
94
95   /* Value 0 is special */
96   value = 0;
97   func(value, &bitpos, &modval, &cc);
98   if (modval != 0)  fprintf(stderr, "modval is wrong for %lx\n", value);
99   if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value);
100   if (cc != 0)      fprintf(stderr, "cc is wrong for %lx\n", value);
101
102   /* Test with exactly 1 bit set */
103   for (i = 0; i < 64; ++i) {
104     value = 1ull << i;
105     func(value, &bitpos, &modval, &cc);
106     if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value);
107     if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
108     if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
109   }
110
111   /* Test with all bits 1 right from first 1 bit */
112   for (i = 1; i < 64; ++i) {
113     value = 1ull << i;
114     value = value | (value - 1);
115     func(value, &bitpos, &modval, &cc);
116     if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value);
117     if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
118     if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
119   }
120}
121
122
123int main()
124{
125   runtest(flogr1);
126   runtest(flogr2);
127   runtest(flogr3);
128
129   return 0;
130}
131