#include #include double foo = -1.0; double FRT1; double FRT2; int base256(int val) { /* interpret the bitstream representing val as a base 256 number for testing * the parity instrs */ int sum = 0; int scale = 1; int i; for (i = 0; i < 8; i++) { int bit = val & 1; sum = sum + bit * scale; val <<= 1; scale *= 256; } return sum; } void test_parity_instrs() { unsigned int word; int i, parity; for (i = 0; i < 50; i++) { word = base256(i); #ifdef __powerpc64__ unsigned long long_word = word; __asm__ volatile ("prtyd %0, %1":"=r" (parity):"r"(long_word)); printf("prtyd (%x) => parity=%x\n", i, parity); #endif __asm__ volatile ("prtyw %0, %1":"=r" (parity):"r"(word)); printf("prtyw (%x) => parity=%x\n", i, parity); } } void test_lfiwax() { unsigned long base; // unsigned long offset; typedef struct { unsigned int hi; unsigned int lo; } int_pair_t; int_pair_t *ip; foo = -1024.0; base = (unsigned long) &foo; __asm__ volatile ("lfiwax %0, 0, %1":"=f" (FRT1):"r"(base)); ip = (int_pair_t *) & FRT1; printf("lfiwax (%f) => FRT=(%x, %x)\n", foo, ip->hi, ip->lo); } /* lfdp FPp, DS(RA) : load float double pair ** FPp = leftmost 64 bits stored at DS(RA) ** FPp+1= rightmost 64 bits stored at DS(RA) ** FPp must be an even float register ** ** The [st|l]fdp[x] instructions were put into the "Floating-Point.Phased-Out" ** category in ISA 2.06 (i.e., POWER7 timeframe). If valgrind and its ** testsuite are built with -mcpu=power7 (or later), then the assembler will ** not recognize those phased out instructions. */ void test_double_pair_instrs() { #ifdef HAVE_AS_PPC_FPPO typedef struct { double hi; double lo; } dbl_pair_t; /* the following decls are for alignment */ int i; dbl_pair_t dbl_pair[3]; /* must be quad word aligned */ unsigned long base; unsigned long offset; for (i = 0; i < 3; i++) { dbl_pair[i].hi = -1024.0 + i; dbl_pair[i].lo = 1024.0 + i + 1; } __asm__ volatile ("lfdp 10, %0"::"m" (dbl_pair[0])); __asm__ volatile ("fmr %0, 10":"=d" (FRT1)); __asm__ volatile ("fmr %0, 11":"=d" (FRT2)); printf("lfdp (%lf, %lf) => F_hi=%lf, F_lo=%lf\n", dbl_pair[0].hi, dbl_pair[0].lo, FRT1, FRT2); FRT1 = 2.2048; FRT2 = -4.1024; __asm__ volatile ("fmr 10, %0"::"d" (FRT1)); __asm__ volatile ("fmr 11, %0"::"d" (FRT2)); __asm__ volatile ("stfdp 10, %0"::"m" (dbl_pair[1])); printf("stfdp (%lf, %lf) => F_hi=%lf, F_lo=%lf\n", FRT1, FRT2, dbl_pair[1].hi, dbl_pair[1].lo); FRT1 = 0.0; FRT2 = -1.0; base = (unsigned long) &dbl_pair; offset = (unsigned long) &dbl_pair[1] - base; __asm__ volatile ("ori 20, %0, 0"::"r" (base)); __asm__ volatile ("ori 21, %0, 0"::"r" (offset)); __asm__ volatile ("lfdpx 10, 20, 21"); __asm__ volatile ("fmr %0, 10":"=d" (FRT1)); __asm__ volatile ("fmr %0, 11":"=d" (FRT2)); printf("lfdpx (%lf, %lf) => F_hi=%lf, F_lo=%lf\n", dbl_pair[1].hi, dbl_pair[1].lo, FRT1, FRT2); FRT1 = 8.2048; FRT2 = -16.1024; base = (unsigned long) &dbl_pair; offset = (unsigned long) &dbl_pair[2] - base; __asm__ volatile ("ori 20, %0, 0"::"r" (base)); __asm__ volatile ("ori 21, %0, 0"::"r" (offset)); __asm__ volatile ("fmr 10, %0 "::"d" (FRT1)); __asm__ volatile ("fmr 11, %0 "::"d" (FRT2)); __asm__ volatile ("stfdpx 10, 20, 21"); printf("stfdpx (%lf, %lf) => F_hi=%lf, F_lo=%lf\n", FRT1, FRT2, dbl_pair[2].hi, dbl_pair[2].lo); #endif } /* The contents of FRB with bit set 0 set to bit 0 of FRA copied into FRT */ void test_fcpsgn() { double A[] = { 10.101010, -0.0, 0.0, -10.101010 }; double B[] = { 11.111111, -0.0, 0.0, -11.111111 }; double FRT, FRA, FRB; int i, j; for (i = 0; i < 4; i++) { FRA = A[i]; for (j = 0; j < 4; j++) { FRB = B[j]; __asm__ volatile ("fcpsgn %0, %1, %2":"=f" (FRT):"f"(FRA), "f"(FRB)); printf("fcpsgn sign=%f, base=%f => %f\n", FRA, FRB, FRT); } } } /* b0 may be non-zero in lwarx/ldarx Power6 instrs */ void test_reservation() { int RT; unsigned long base; unsigned long offset; long arr[4] = { 0xdeadbeef, 0xbad0beef, 0xbeefdead, 0xbeef0bad }; base = (unsigned long) &arr; offset = (unsigned long) &arr[1] - base; __asm__ volatile ("ori 20, %0, 0"::"r" (base)); __asm__ volatile ("ori 21, %0, 0"::"r" (offset)); __asm__ volatile ("lwarx %0, 20, 21, 1":"=r" (RT)); printf("lwarx => %x\n", RT); #ifdef __powerpc64__ offset = (unsigned long) &arr[1] - base; __asm__ volatile ("ori 21, %0, 0"::"r" (offset)); __asm__ volatile ("ldarx %0, 20, 21, 1":"=r" (RT)); printf("ldarx => %x\n", RT); #endif } int main(void) { (void) test_reservation(); test_fcpsgn(); (void) test_double_pair_instrs(); test_lfiwax(); test_parity_instrs(); return 0; }