1#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 180/* 181 * gcc is not happy if we modify r31 (the frame pointer) behind its back 182 * so we omit it 183 */ 184int __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