#include <stdio.h> #include <stdint.h> #ifndef __powerpc64__ typedef uint32_t HWord_t; #else typedef uint64_t HWord_t; #endif typedef void (*test_func_t)(); typedef struct test_table { test_func_t func; char *name; } test_table_t; static uint32_t values[] = { 0x6efbcfdf, 0xd16c2fd4, 0xf9dc1743, 0xa5aa0bd4, 0x6c8f0c14, 0x69a24188, 0x53b57f1b, }; register HWord_t r27 asm("r27"); register HWord_t r28 asm("r28"); register HWord_t r29 asm("r29"); register HWord_t r30 asm("r30"); register HWord_t r31 asm("r31"); register HWord_t r14 asm("r14"); HWord_t temp[5]; #ifdef __powerpc64__ #define SAVE_REGS(addr) \ asm volatile( \ " std 27, 0(%0) \n" \ " std 28, 8(%0) \n" \ " std 29, 16(%0) \n" \ " std 30, 24(%0) \n" \ " std 31, 32(%0) \n" \ ::"b"(addr)) #define RESTORE_REGS(addr) \ asm volatile( \ " ld 27, 0(%0) \n" \ " ld 28, 8(%0) \n" \ " ld 29, 16(%0) \n" \ " ld 30, 24(%0) \n" \ " ld 31, 32(%0) \n" \ ::"b"(addr)) #else /* !__powerpc64__ */ #define SAVE_REGS(addr) \ asm volatile( \ " stw 27, 0(%0) \n" \ " stw 28, 4(%0) \n" \ " stw 29, 8(%0) \n" \ " stw 30, 12(%0) \n" \ " stw 31, 16(%0) \n" \ ::"b"(addr)) #define RESTORE_REGS(addr) \ asm volatile( \ " lwz 27, 0(%0) \n" \ " lwz 28, 4(%0) \n" \ " lwz 29, 8(%0) \n" \ " lwz 30, 12(%0) \n" \ " lwz 31, 16(%0) \n" \ ::"b"(addr)) #endif /* __powerpc64__ */ /* * gcc is not happy if we modify r31 (the frame pointer) behind its back * so we omit it */ static void __attribute__((optimize("-fomit-frame-pointer"))) test_lmw(void) { r14 = (HWord_t)values; /* save r27 - r31 */ SAVE_REGS(temp); /* load r27 - r31 */ asm volatile( " lmw %r27, 0(%r14) \n"); #ifdef __powerpc64__ printf("lmw => %016lx %016lx %016lx %016lx %016lx\n", #else printf("lmw => %08x %08x %08x %08x %08x\n", #endif r27, r28, r29, r30, r31); /* * test load multiple with nonzero immediate offset * load the last two values into r30 - r31. * r27 - r29 should remain the same */ asm volatile( " lmw %r30, 20(%r14) \n"); #ifdef __powerpc64__ printf("lmw => %016lx %016lx %016lx %016lx %016lx\n", #else printf("lmw => %08x %08x %08x %08x %08x\n", #endif r27, r28, r29, r30, r31); /* restore r27 - r31 */ RESTORE_REGS(temp); } /* * gcc is not happy if we modify r31 (the frame pointer) behind its back * so we omit it */ static void __attribute__((optimize("-fomit-frame-pointer"))) test_stmw(void) { uint32_t result[7] = { 0 }; int i; SAVE_REGS(temp); #ifdef __powerpc64__ asm volatile( " lwz 27, 0(%0) \n" \ " lwz 28, 4(%0) \n" \ " lwz 29, 8(%0) \n" \ " lwz 30, 12(%0) \n" \ " lwz 31, 16(%0) \n" \ ::"b"(values)); #else RESTORE_REGS(values); #endif r14 = (HWord_t)&result; /* store r27 - r31 */ asm volatile( " stmw %r27, 0(%r14) \n"); printf("stmw => "); for (i = 0; i < sizeof(result) / sizeof(result[0]); i++) printf("%08x ", result[i]); printf("\n"); /* * test store multiple with nonzero immediate offset * store r30 - r31 into the last two places in the array * the rest of the array should remain the same */ asm volatile( " stmw %r30, 20(%r14) \n"); printf("stmw => "); for (i = 0; i < sizeof(result) / sizeof(result[0]); i++) printf("%08x ", result[i]); printf("\n"); RESTORE_REGS(temp); } static test_table_t all_tests[] = { { &test_lmw, "Test Load Multiple instruction" }, { &test_stmw, "Test Store Multiple instruction" }, { NULL, NULL }, }; /* * gcc is not happy if we modify r31 (the frame pointer) behind its back * so we omit it */ int __attribute__((optimize("-fomit-frame-pointer"))) main(void) { test_func_t func; int i = 0; while ((func = all_tests[i].func)) { (*func)(); i++; } return 0; }