You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
4.6 KiB
195 lines
4.6 KiB
#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; |
|
}
|
|
|