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