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