1#include <stdio.h>
2#include <config.h>
3
4double foo = -1.0;
5double FRT1;
6double FRT2;
7int base256(int val)
8{
9/* interpret the  bitstream representing val as a base 256 number for testing
10 * the parity instrs
11 */
12   int sum = 0;
13   int scale = 1;
14   int i;
15
16   for (i = 0; i < 8; i++) {
17      int bit = val & 1;
18      sum = sum + bit * scale;
19      val <<= 1;
20      scale *= 256;
21   }
22   return sum;
23}
24
25void test_parity_instrs()
26{
27   unsigned long long_word;
28   unsigned int word;
29   int i, parity;
30
31   for (i = 0; i < 50; i++) {
32      word = base256(i);
33      long_word = word;
34      __asm__ volatile ("prtyd %0, %1":"=r" (parity):"r"(long_word));
35      printf("prtyd (%x) => parity=%x\n", i, parity);
36      __asm__ volatile ("prtyw %0, %1":"=r" (parity):"r"(word));
37      printf("prtyw (%x) => parity=%x\n", i, parity);
38   }
39}
40
41void test_lfiwax()
42{
43   unsigned long base;
44   float foo_s;
45
46   typedef struct {
47#if defined(VGP_ppc64le_linux)
48      unsigned int lo;
49      unsigned int hi;
50#else
51      unsigned int hi;
52      unsigned int lo;
53#endif
54   } int_pair_t;
55
56   int_pair_t *ip;
57   foo_s = -1024.0;
58   base = (unsigned long) &foo_s;
59
60   __asm__ volatile ("lfiwax %0, 0, %1":"=f" (FRT1):"r"(base));
61   ip = (int_pair_t *) & FRT1;
62   printf("lfiwax (%f) => FRT=(%x, %x)\n", foo_s, ip->hi, ip->lo);
63
64
65}
66
67
68
69/* lfdp FPp, DS(RA) : load float double pair
70** FPp	= leftmost 64 bits stored at DS(RA)
71** FPp+1= rightmost 64 bits stored at DS(RA)
72** FPp must be an even float register
73**
74** The [st|l]fdp[x] instructions were put into the "Floating-Point.Phased-Out"
75** category in ISA 2.06 (i.e., POWER7 timeframe).  If valgrind and its
76** testsuite are built with -mcpu=power7 (or later), then the assembler will
77** not recognize those phased out instructions.
78**
79*/
80void test_double_pair_instrs()
81{
82#ifdef HAVE_AS_PPC_FPPO
83   typedef struct {
84      double hi;
85      double lo;
86   } dbl_pair_t;
87
88   /* the following decls are for alignment */
89   int i;
90   dbl_pair_t dbl_pair[3];      /* must be quad word aligned */
91   unsigned long base;
92   unsigned long offset;
93
94   for (i = 0; i < 3; i++) {
95      dbl_pair[i].hi = -1024.0 + i;
96      dbl_pair[i].lo = 1024.0 + i + 1;
97   }
98
99   __asm__ volatile ("lfdp 10, %0"::"m" (dbl_pair[0]));
100   __asm__ volatile ("fmr %0, 10":"=d" (FRT1));
101   __asm__ volatile ("fmr %0, 11":"=d" (FRT2));
102   printf("lfdp (%lf, %lf) => F_hi=%lf, F_lo=%lf\n",
103          dbl_pair[0].hi, dbl_pair[0].lo, FRT1, FRT2);
104
105
106   FRT1 = 2.2048;
107   FRT2 = -4.1024;
108   __asm__ volatile ("fmr 10, %0"::"d" (FRT1));
109   __asm__ volatile ("fmr 11, %0"::"d" (FRT2));
110   __asm__ volatile ("stfdp 10, %0"::"m" (dbl_pair[1]));
111   printf("stfdp (%lf, %lf) => F_hi=%lf, F_lo=%lf\n",
112          FRT1, FRT2, dbl_pair[1].hi, dbl_pair[1].lo);
113
114   FRT1 = 0.0;
115   FRT2 = -1.0;
116   base = (unsigned long) &dbl_pair;
117   offset = (unsigned long) &dbl_pair[1] - base;
118   __asm__ volatile ("ori 20, %0, 0"::"r" (base));
119   __asm__ volatile ("ori 21, %0, 0"::"r" (offset));
120   __asm__ volatile ("lfdpx 10, 20, 21");
121   __asm__ volatile ("fmr %0, 10":"=d" (FRT1));
122   __asm__ volatile ("fmr %0, 11":"=d" (FRT2));
123   printf("lfdpx (%lf, %lf) => F_hi=%lf, F_lo=%lf\n",
124          dbl_pair[1].hi, dbl_pair[1].lo, FRT1, FRT2);
125
126   FRT1 = 8.2048;
127   FRT2 = -16.1024;
128   base = (unsigned long) &dbl_pair;
129   offset = (unsigned long) &dbl_pair[2] - base;
130   __asm__ volatile ("ori 20, %0, 0"::"r" (base));
131   __asm__ volatile ("ori 21, %0, 0"::"r" (offset));
132   __asm__ volatile ("fmr 10, %0 "::"d" (FRT1));
133   __asm__ volatile ("fmr 11, %0 "::"d" (FRT2));
134   __asm__ volatile ("stfdpx 10, 20, 21");
135   printf("stfdpx (%lf, %lf) => F_hi=%lf, F_lo=%lf\n",
136          FRT1, FRT2, dbl_pair[2].hi, dbl_pair[2].lo);
137#endif
138}
139
140
141/* The contents of FRB with bit set 0 set to bit 0 of FRA copied into FRT */
142void test_fcpsgn()
143{
144   double A[] = {
145      10.101010,
146      -0.0,
147      0.0,
148      -10.101010
149   };
150
151   double B[] = {
152      11.111111,
153      -0.0,
154      0.0,
155      -11.111111
156   };
157
158   double FRT, FRA, FRB;
159   int i, j;
160
161   for (i = 0; i < 4; i++) {
162      FRA = A[i];
163      for (j = 0; j < 4; j++) {
164         FRB = B[j];
165         __asm__ volatile ("fcpsgn %0, %1, %2":"=f" (FRT):"f"(FRA),
166                           "f"(FRB));
167         printf("fcpsgn sign=%f, base=%f => %f\n", FRA, FRB, FRT);
168      }
169   }
170}
171
172/* b0 may be non-zero in lwarx/ldarx Power6 instrs */
173void test_reservation()
174{
175
176   unsigned long long RT;
177   unsigned long base;
178   unsigned long offset;
179   long arrL[] __attribute__ ((aligned (8))) = { 0xdeadbeef00112233ULL, 0xbad0beef44556677ULL, 0xbeefdead8899aabbULL, 0xbeef0badccddeeffULL };
180   int arrI[] __attribute__ ((aligned (4))) = { 0xdeadbeef, 0xbad0beef, 0xbeefdead, 0xbeef0bad };
181
182
183   base = (unsigned long) &arrI;
184   offset = ((unsigned long) &arrI[1]) - base;
185   __asm__ volatile ("ori 20, %0, 0"::"r" (base));
186   __asm__ volatile ("ori 21, %0, 0"::"r" (offset));
187   __asm__ volatile ("lwarx %0, 20, 21, 1":"=r" (RT));
188   printf("lwarx => 0x%llx\n", RT);
189
190#ifdef __powerpc64__
191   base = (unsigned long) &arrL;
192   offset = ((unsigned long) &arrL[1]) - base;
193   __asm__ volatile ("ori 20, %0, 0"::"r" (base));
194   __asm__ volatile ("ori 21, %0, 0"::"r" (offset));
195   __asm__ volatile ("ldarx %0, 20, 21, 1":"=r" (RT));
196   printf("ldarx => 0x%llx\n", RT);
197#endif
198
199}
200
201int main(void)
202{
203   (void) test_reservation();
204   test_fcpsgn();
205   (void) test_double_pair_instrs();
206   test_lfiwax();
207   test_parity_instrs();
208   return 0;
209}
210