1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h>
2#include <stdint.h>
3
4#ifndef __powerpc64__
5typedef uint32_t HWord_t;
6#else
7typedef uint64_t HWord_t;
8#endif
9
10typedef void (*test_func_t)();
11
12typedef struct test_table {
13   test_func_t func;
14   char *name;
15} test_table_t;
16
17static uint32_t values[] = {
18   0x6efbcfdf,
19   0xd16c2fd4,
20   0xf9dc1743,
21   0xa5aa0bd4,
22   0x6c8f0c14,
23   0x69a24188,
24   0x53b57f1b,
25};
26
27register HWord_t r27 asm("r27");
28register HWord_t r28 asm("r28");
29register HWord_t r29 asm("r29");
30register HWord_t r30 asm("r30");
31register HWord_t r31 asm("r31");
32
33register HWord_t r14 asm("r14");
34
35HWord_t temp[5];
36
37#ifdef __powerpc64__
38
39#define SAVE_REGS(addr)                       \
40   asm volatile(                              \
41   "	std   27, 0(%0)   \n"                   \
42   "	std   28, 8(%0)   \n"                   \
43   "	std   29, 16(%0)  \n"                   \
44   "	std   30, 24(%0)  \n"                   \
45   "	std   31, 32(%0)  \n"                   \
46   ::"b"(addr))
47
48#define RESTORE_REGS(addr)                    \
49   asm volatile(                              \
50   "	ld    27, 0(%0)   \n"                   \
51   "	ld    28, 8(%0)   \n"                   \
52   "	ld    29, 16(%0)  \n"                   \
53   "	ld    30, 24(%0)  \n"                   \
54   "	ld    31, 32(%0)  \n"                   \
55   ::"b"(addr))
56
57#else /* !__powerpc64__ */
58
59#define SAVE_REGS(addr)                       \
60   asm volatile(                              \
61   "	stw   27, 0(%0)   \n"                   \
62   "	stw   28, 4(%0)   \n"                   \
63   "	stw   29, 8(%0)   \n"                   \
64   "	stw   30, 12(%0)  \n"                   \
65   "	stw   31, 16(%0)  \n"                   \
66   ::"b"(addr))
67
68#define RESTORE_REGS(addr)                    \
69   asm volatile(                              \
70   "	lwz   27, 0(%0)   \n"                   \
71   "	lwz   28, 4(%0)   \n"                   \
72   "	lwz   29, 8(%0)   \n"                   \
73   "	lwz   30, 12(%0)  \n"                   \
74   "	lwz   31, 16(%0)  \n"                   \
75   ::"b"(addr))
76
77#endif /* __powerpc64__ */
78
79/*
80 * gcc is not happy if we modify r31 (the frame pointer) behind its back
81 * so we omit it
82 */
83static void __attribute__((optimize("-fomit-frame-pointer"))) test_lmw(void)
84{
85   r14 = (HWord_t)values;
86
87   /* save r27 - r31 */
88   SAVE_REGS(temp);
89
90   /* load r27 - r31 */
91   asm volatile(
92      "	lmw	%r27, 0(%r14)	\n");
93
94#ifdef __powerpc64__
95   printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
96#else
97   printf("lmw => %08x %08x %08x %08x %08x\n",
98#endif
99          r27, r28, r29, r30, r31);
100
101   /*
102    * test load multiple with nonzero immediate offset
103    * load the last two values into r30 - r31.
104    * r27 - r29 should remain the same
105    */
106   asm volatile(
107      "	lmw	%r30, 20(%r14)	\n");
108
109#ifdef __powerpc64__
110   printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
111#else
112   printf("lmw => %08x %08x %08x %08x %08x\n",
113#endif
114          r27, r28, r29, r30, r31);
115
116   /* restore r27 - r31 */
117   RESTORE_REGS(temp);
118}
119
120/*
121 * gcc is not happy if we modify r31 (the frame pointer) behind its back
122 * so we omit it
123 */
124static void __attribute__((optimize("-fomit-frame-pointer"))) test_stmw(void)
125{
126   uint32_t result[7] = { 0 };
127   int i;
128
129   SAVE_REGS(temp);
130
131#ifdef __powerpc64__
132   asm volatile(
133   "	lwz   27, 0(%0)   \n"                   \
134   "	lwz   28, 4(%0)   \n"                   \
135   "	lwz   29, 8(%0)   \n"                   \
136   "	lwz   30, 12(%0)  \n"                   \
137   "	lwz   31, 16(%0)  \n"                   \
138   ::"b"(values));
139#else
140   RESTORE_REGS(values);
141#endif
142
143   r14 = (HWord_t)&result;
144
145   /* store r27 - r31 */
146   asm volatile(
147      "	stmw	%r27, 0(%r14)	\n");
148
149   printf("stmw => ");
150   for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
151      printf("%08x ", result[i]);
152
153   printf("\n");
154
155   /*
156    * test store multiple with nonzero immediate offset
157    * store r30 - r31 into the last two places in the array
158    * the rest of the array should remain the same
159    */
160   asm volatile(
161      "	stmw	%r30, 20(%r14)	\n");
162
163   printf("stmw => ");
164   for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
165      printf("%08x ", result[i]);
166
167   printf("\n");
168
169   RESTORE_REGS(temp);
170}
171
172static test_table_t all_tests[] = {
173   { &test_lmw,
174     "Test Load Multiple instruction" },
175   { &test_stmw,
176     "Test Store Multiple instruction" },
177   { NULL, NULL },
178};
179
180int main(void)
181{
182   test_func_t func;
183   int i = 0;
184
185   while ((func = all_tests[i].func)) {
186      (*func)();
187      i++;
188   }
189
190   return 0;
191}
192