1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h>
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdint.h>
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifndef __powerpc64__
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef uint32_t HWord_t;
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef uint64_t HWord_t;
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef void (*test_func_t)();
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef struct test_table {
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   test_func_t func;
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   char *name;
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} test_table_t;
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic uint32_t values[] = {
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0x6efbcfdf,
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0xd16c2fd4,
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0xf9dc1743,
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0xa5aa0bd4,
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0x6c8f0c14,
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0x69a24188,
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   0x53b57f1b,
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r27 asm("r27");
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r28 asm("r28");
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r29 asm("r29");
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r30 asm("r30");
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r31 asm("r31");
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovregister HWord_t r14 asm("r14");
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovHWord_t temp[5];
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifdef __powerpc64__
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define SAVE_REGS(addr)                       \
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(                              \
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	std   27, 0(%0)   \n"                   \
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	std   28, 8(%0)   \n"                   \
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	std   29, 16(%0)  \n"                   \
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	std   30, 24(%0)  \n"                   \
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	std   31, 32(%0)  \n"                   \
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ::"b"(addr))
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define RESTORE_REGS(addr)                    \
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(                              \
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	ld    27, 0(%0)   \n"                   \
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	ld    28, 8(%0)   \n"                   \
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	ld    29, 16(%0)  \n"                   \
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	ld    30, 24(%0)  \n"                   \
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	ld    31, 32(%0)  \n"                   \
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ::"b"(addr))
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else /* !__powerpc64__ */
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define SAVE_REGS(addr)                       \
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(                              \
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	stw   27, 0(%0)   \n"                   \
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	stw   28, 4(%0)   \n"                   \
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	stw   29, 8(%0)   \n"                   \
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	stw   30, 12(%0)  \n"                   \
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	stw   31, 16(%0)  \n"                   \
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ::"b"(addr))
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define RESTORE_REGS(addr)                    \
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(                              \
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   27, 0(%0)   \n"                   \
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   28, 4(%0)   \n"                   \
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   29, 8(%0)   \n"                   \
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   30, 12(%0)  \n"                   \
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   31, 16(%0)  \n"                   \
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ::"b"(addr))
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif /* __powerpc64__ */
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * gcc is not happy if we modify r31 (the frame pointer) behind its back
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * so we omit it
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void __attribute__((optimize("-fomit-frame-pointer"))) test_lmw(void)
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   r14 = (HWord_t)values;
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* save r27 - r31 */
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SAVE_REGS(temp);
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* load r27 - r31 */
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      "	lmw	%r27, 0(%r14)	\n");
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifdef __powerpc64__
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("lmw => %08x %08x %08x %08x %08x\n",
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          r27, r28, r29, r30, r31);
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /*
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * test load multiple with nonzero immediate offset
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * load the last two values into r30 - r31.
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * r27 - r29 should remain the same
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    */
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      "	lmw	%r30, 20(%r14)	\n");
108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifdef __powerpc64__
110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("lmw => %08x %08x %08x %08x %08x\n",
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          r27, r28, r29, r30, r31);
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* restore r27 - r31 */
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   RESTORE_REGS(temp);
118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*
121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * gcc is not happy if we modify r31 (the frame pointer) behind its back
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * so we omit it
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void __attribute__((optimize("-fomit-frame-pointer"))) test_stmw(void)
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   uint32_t result[7] = { 0 };
127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int i;
128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SAVE_REGS(temp);
130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifdef __powerpc64__
132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(
133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   27, 0(%0)   \n"                   \
134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   28, 4(%0)   \n"                   \
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   29, 8(%0)   \n"                   \
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   30, 12(%0)  \n"                   \
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   "	lwz   31, 16(%0)  \n"                   \
138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ::"b"(values));
139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   RESTORE_REGS(values);
141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   r14 = (HWord_t)&result;
144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* store r27 - r31 */
146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(
147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      "	stmw	%r27, 0(%r14)	\n");
148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("stmw => ");
150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      printf("%08x ", result[i]);
152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("\n");
154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /*
156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * test store multiple with nonzero immediate offset
157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * store r30 - r31 into the last two places in the array
158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * the rest of the array should remain the same
159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    */
160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   asm volatile(
161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      "	stmw	%r30, 20(%r14)	\n");
162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("stmw => ");
164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      printf("%08x ", result[i]);
166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("\n");
168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   RESTORE_REGS(temp);
170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic test_table_t all_tests[] = {
173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { &test_lmw,
174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "Test Load Multiple instruction" },
175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { &test_stmw,
176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "Test Store Multiple instruction" },
177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   { NULL, NULL },
178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint main(void)
181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   test_func_t func;
183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int i = 0;
184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while ((func = all_tests[i].func)) {
186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      (*func)();
187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      i++;
188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return 0;
191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
192