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