1 #include <stdio.h>
2 #include <stdint.h>
3
4 #ifndef __powerpc64__
5 typedef uint32_t HWord_t;
6 #else
7 typedef uint64_t HWord_t;
8 #endif
9
10 typedef void (*test_func_t)();
11
12 typedef struct test_table {
13 test_func_t func;
14 char *name;
15 } test_table_t;
16
17 static uint32_t values[] = {
18 0x6efbcfdf,
19 0xd16c2fd4,
20 0xf9dc1743,
21 0xa5aa0bd4,
22 0x6c8f0c14,
23 0x69a24188,
24 0x53b57f1b,
25 };
26
27 register HWord_t r27 asm("r27");
28 register HWord_t r28 asm("r28");
29 register HWord_t r29 asm("r29");
30 register HWord_t r30 asm("r30");
31 register HWord_t r31 asm("r31");
32
33 register HWord_t r14 asm("r14");
34
35 HWord_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 */
test_lmw(void)83 static 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 */
test_stmw(void)124 static 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
172 static 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
180 /*
181 * gcc is not happy if we modify r31 (the frame pointer) behind its back
182 * so we omit it
183 */
main(void)184 int __attribute__((optimize("-fomit-frame-pointer"))) main(void)
185 {
186 test_func_t func;
187 int i = 0;
188
189 while ((func = all_tests[i].func)) {
190 (*func)();
191 i++;
192 }
193
194 return 0;
195 }
196