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