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