AM_CONDITIONAL(BUILD_DFP_TESTS, test x$ac_gcc_have_dfp_type = xyes)
+# isa 2.07 checking
+AC_MSG_CHECKING([that assembler knows ISA 2.07 ])
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+]], [[
+ __asm__ __volatile__("mtvsrd 1,2 ");
+]])], [
+ac_asm_have_isa_2_07=yes
+AC_MSG_RESULT([yes])
+], [
+ac_asm_have_isa_2_07=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(HAS_ISA_2_07, test x$ac_asm_have_isa_2_07 = xyes)
# Check for pthread_create@GLIBC2.0
AC_MSG_CHECKING([for pthread_create@GLIBC2.0()])
vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
+ volatile Bool have_isa_2_07;
Int r;
/* This is a kludge. Really we ought to back-convert saved_act
__asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
}
+ /* Check for ISA 2.07 support. */
+ have_isa_2_07 = True;
+ if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
+ have_isa_2_07 = False;
+ } else {
+ __asm__ __volatile__(".long 0x7c000166"); /* mtvsrd XT,RA */
+ }
+
/* determine dcbz/dcbzl sizes while we still have the signal
* handlers registered */
find_ppc_dcbz_sz(&vai);
vg_assert(r == 0);
r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
vg_assert(r == 0);
- VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
+ VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d ISA2.07 %d\n",
(Int)have_F, (Int)have_V, (Int)have_FX,
- (Int)have_GX, (Int)have_VX, (Int)have_DFP);
+ (Int)have_GX, (Int)have_VX, (Int)have_DFP,
+ (Int)have_isa_2_07);
/* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
if (have_V && !have_F)
have_V = False;
if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
+ if (have_isa_2_07) vai.hwcaps |= VEX_HWCAPS_PPC32_ISA2_07;
VG_(machine_get_cache_info)(&vai);
vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
+ volatile Bool have_isa_2_07;
Int r;
/* This is a kludge. Really we ought to back-convert saved_act
__asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
}
+ /* Check for ISA 2.07 support. */
+ have_isa_2_07 = True;
+ if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
+ have_isa_2_07 = False;
+ } else {
+ __asm__ __volatile__(".long 0x7c000166"); /* mtvsrd XT,RA */
+ }
+
/* determine dcbz/dcbzl sizes while we still have the signal
* handlers registered */
find_ppc_dcbz_sz(&vai);
VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
- VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
+ VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d ISA2.07 %d\n",
(Int)have_F, (Int)have_V, (Int)have_FX,
- (Int)have_GX, (Int)have_VX, (Int)have_DFP);
+ (Int)have_GX, (Int)have_VX, (Int)have_DFP,
+ (Int)have_isa_2_07);
/* on ppc64, if we don't even have FP, just give up. */
if (!have_F)
return False;
if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
+ if (have_isa_2_07) vai.hwcaps |= VEX_HWCAPS_PPC64_ISA2_07;
VG_(machine_get_cache_info)(&vai);
than a data steering operation. */
case Iop_NarrowBin32to16x8:
case Iop_NarrowBin16to8x16:
+ case Iop_NarrowBin64to32x4:
return assignNew('V', mce, Ity_V128,
binop(op, vatom1, vatom2));
{ DEFOP(Iop_QNarrowBin32Uto16Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowBin16to8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowBin32to16x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_NarrowBin64to32x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowUn16to8x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowUn32to16x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowUn64to32x2, UNDEF_UNKNOWN), },
test_dfp2.stdout.exp_Without_dcffix \
test_dfp3.stderr.exp test_dfp3.stdout.exp test_dfp3.vgtest \
test_dfp4.stderr.exp test_dfp4.stdout.exp test_dfp4.vgtest \
- test_dfp5.stderr.exp test_dfp5.stdout.exp test_dfp5.vgtest
+ test_dfp5.stderr.exp test_dfp5.stdout.exp test_dfp5.vgtest \
+ jm_vec_isa_2_07.stderr.exp jm_vec_isa_2_07.stdout.exp jm_vec_isa_2_07.vgtest \
+ test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest
+
check_PROGRAMS = \
allexec \
test_isa_2_06_part1 \
test_isa_2_06_part2 \
test_isa_2_06_part3 \
- test_dfp1 test_dfp2 test_dfp3 test_dfp4 test_dfp5
+ test_dfp1 test_dfp2 test_dfp3 test_dfp4 test_dfp5 \
+ test_isa_2_07_part1 \
+ test_isa_2_07_part2
AM_CFLAGS += @FLAG_M32@
DFP_FLAG =
endif
+if HAS_ISA_2_07
+BUILD_FLAGS_ISA_2_07 = -mcpu=power8
+ISA_2_07_FLAG = -DHAS_ISA_2_07
+else
+BUILD_FLAGS_ISA_2_07 =
+ISA_2_07_FLAG =
+endif
+
jm_insns_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames -maltivec \
@FLAG_M32@ $(ALTIVEC_FLAG)
test_dfp5_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
@FLAG_M32@ $(BUILD_FLAGS_DFP)
+
+test_isa_2_07_part1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(ISA_2_07_FLAG) \
+ @FLAG_M32@ $(BUILD_FLAGS_ISA_2_07)
+
+test_isa_2_07_part2_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(ISA_2_07_FLAG) \
+ @FLAG_M64@ $(BUILD_FLAGS_ISA_2_07)
--- /dev/null
+mfvsrd: 0102030405060708 => 0000000005060708
+mfvsrd: 090a0b0c0e0d0e0f => 000000000e0d0e0f
+mfvsrd: f1f2f3f4f5f6f7f8 => 00000000f5f6f7f8
+mfvsrd: f9fafbfcfefdfeff => 00000000fefdfeff
+
+mtvsrd: 0102030405060708 => 0000000005060708
+mtvsrd: 090a0b0c0e0d0e0f => 000000000e0d0e0f
+mtvsrd: f1f2f3f4f5f6f7f8 => 00000000f5f6f7f8
+mtvsrd: f9fafbfcfefdfeff => 00000000fefdfeff
+
+mtfprwa: 05060708 => 0000000005060708
+mtfprwa: 0e0d0e0f => 000000000e0d0e0f
+mtfprwa: f5f6f7f8 => fffffffff5f6f7f8
+mtfprwa: fefdfeff => fffffffffefdfeff
+
+vaddudm: 0102030405060708 @@ 0102030405060708, ==> 020406080a0c0e10
+ 090a0b0c0e0d0e0f @@ 090a0b0c0e0d0e0f, ==> 121416181c1a1c1e
+vaddudm: 0102030405060708 @@ f1f2f3f4f5f6f7f8, ==> f2f4f6f8fafcff00
+ 090a0b0c0e0d0e0f @@ f9fafbfcfefdfeff, ==> 030507090d0b0d0e
+vaddudm: f1f2f3f4f5f6f7f8 @@ 0102030405060708, ==> f2f4f6f8fafcff00
+ f9fafbfcfefdfeff @@ 090a0b0c0e0d0e0f, ==> 030507090d0b0d0e
+vaddudm: f1f2f3f4f5f6f7f8 @@ f1f2f3f4f5f6f7f8, ==> e3e5e7e9ebedeff0
+ f9fafbfcfefdfeff @@ f9fafbfcfefdfeff, ==> f3f5f7f9fdfbfdfe
+
+vpkudum: Inputs: 05060708 0e0d0e0f 05060708 0e0d0e0f
+ Output: 05060708 0e0d0e0f 05060708 0e0d0e0f
+vpkudum: Inputs: 05060708 0e0d0e0f f5f6f7f8 fefdfeff
+ Output: 05060708 0e0d0e0f f5f6f7f8 fefdfeff
+vpkudum: Inputs: f5f6f7f8 fefdfeff 05060708 0e0d0e0f
+ Output: f5f6f7f8 fefdfeff 05060708 0e0d0e0f
+vpkudum: Inputs: f5f6f7f8 fefdfeff f5f6f7f8 fefdfeff
+ Output: f5f6f7f8 fefdfeff f5f6f7f8 fefdfeff
+
+All done. Tested 5 different instructions
--- /dev/null
+prereq: ../../../tests/check_isa-2_07_cap
+prog: test_isa_2_07_part1 -a
--- /dev/null
+../ppc64/test_isa_2_07_part1.c
\ No newline at end of file
--- /dev/null
+../ppc64/test_isa_2_07_part2.c
\ No newline at end of file
--- /dev/null
+Test VSX vector and scalar single argument instructions
+#0: xscvdpspn conv(3fd8000000000000) = 3ec0000000000000
+#1: xscvdpspn conv(404f000000000000) = 4278000000000000
+#2: xscvdpspn conv(0018000000b77501) = 0000000000000000
+#3: xscvdpspn conv(7fe800000000051b) = 7f40000000000000
+#4: xscvdpspn conv(0123214569900000) = 0000000000000000
+#5: xscvdpspn conv(0000000000000000) = 0000000000000000
+#6: xscvdpspn conv(8000000000000000) = 8000000000000000
+#7: xscvdpspn conv(7ff0000000000000) = 7f80000000000000
+#8: xscvdpspn conv(fff0000000000000) = ff80000000000000
+#9: xscvdpspn conv(7ff7ffffffffffff) = 7fbfffff00000000
+#10: xscvdpspn conv(fff7ffffffffffff) = ffbfffff00000000
+#11: xscvdpspn conv(7ff8000000000000) = 7fc0000000000000
+#12: xscvdpspn conv(fff8000000000000) = ffc0000000000000
+#13: xscvdpspn conv(8008340000078000) = 8000000000000000
+#14: xscvdpspn conv(c0d0650f5a07b353) = c683287a00000000
+#15: xscvdpspn conv(41232585a9900000) = 49192c2d00000000
+#16: xscvdpspn conv(41382511a2000000) = 49c1288d00000000
+#17: xscvdpspn conv(40312ef5a9300000) = 418977ad00000000
+#18: xscvdpspn conv(40514bf5d2300000) = 428a5fae00000000
+#19: xscvdpspn conv(40976bf982440000) = 44bb5fcc00000000
+
+#0: xscvspdpn conv(3ec00000) = 3fd8000000000000
+#1: xscvspdpn conv(42780000) = 404f000000000000
+#2: xscvspdpn conv(00000000) = 0000000000000000
+#3: xscvspdpn conv(7f800000) = 7ff0000000000000
+#4: xscvspdpn conv(00000000) = 0000000000000000
+#5: xscvspdpn conv(00000000) = 0000000000000000
+#6: xscvspdpn conv(80000000) = 8000000000000000
+#7: xscvspdpn conv(7f800000) = 7ff0000000000000
+#8: xscvspdpn conv(ff800000) = fff0000000000000
+#9: xscvspdpn conv(7fffffff) = 7fffffffe0000000
+#10: xscvspdpn conv(ffffffff) = ffffffffe0000000
+#11: xscvspdpn conv(7fc00000) = 7ff8000000000000
+#12: xscvspdpn conv(ffc00000) = fff8000000000000
+#13: xscvspdpn conv(80000000) = 8000000000000000
+#14: xscvspdpn conv(c683287b) = c0d0650f60000000
+#15: xscvspdpn conv(49192c2d) = 41232585a0000000
+#16: xscvspdpn conv(49c1288d) = 41382511a0000000
+#17: xscvspdpn conv(418977ad) = 40312ef5a0000000
+#18: xscvspdpn conv(428a5faf) = 40514bf5e0000000
+#19: xscvspdpn conv(44bb5fcc) = 40976bf980000000
+
+Testcase PASSED
--- /dev/null
+prereq: ../../../tests/check_isa-2_07_cap
+prog: test_isa_2_07_part2
test_dfp2.stdout.exp_Without_dcffix \
test_dfp3.stderr.exp test_dfp3.stdout.exp test_dfp3.vgtest \
test_dfp4.stderr.exp test_dfp4.stdout.exp test_dfp4.vgtest \
- test_dfp5.stderr.exp test_dfp5.stdout.exp test_dfp5.vgtest
+ test_dfp5.stderr.exp test_dfp5.stdout.exp test_dfp5.vgtest \
+ jm_vec_isa_2_07.stderr.exp jm_vec_isa_2_07.stdout.exp jm_vec_isa_2_07.vgtest \
+ test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest
check_PROGRAMS = \
allexec \
- jm-insns lsw round std_reg_imm twi_tdi tw_td power6_bcmp power6_mf_gpr test_isa_2_06_part1 \
- test_isa_2_06_part2 test_isa_2_06_part3 test_dfp1 test_dfp2 test_dfp3 test_dfp4 test_dfp5
+ jm-insns lsw round std_reg_imm twi_tdi tw_td power6_bcmp \
+ power6_mf_gpr test_isa_2_06_part1 test_isa_2_06_part2 \
+ test_isa_2_06_part3 test_dfp1 test_dfp2 test_dfp3 test_dfp4 \
+ test_dfp5 test_isa_2_07_part1 test_isa_2_07_part2
AM_CFLAGS += @FLAG_M64@
AM_CXXFLAGS += @FLAG_M64@
DFP_FLAG =
endif
+if HAS_ISA_2_07
+BUILD_FLAGS_ISA_2_07 = -mcpu=power8
+ISA_2_07_FLAG = -DHAS_ISA_2_07
+else
+BUILD_FLAGS_ISA_2_07 =
+ISA_2_07_FLAG =
+endif
+
test_isa_2_06_part1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(VSX_FLAG) \
@FLAG_M64@ $(ALTIVEC_FLAG) $(BUILD_FLAG_VSX)
test_dfp5_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
@FLAG_M64@ $(BUILD_FLAGS_DFP)
+test_isa_2_07_part1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(ISA_2_07_FLAG) \
+ @FLAG_M64@ $(BUILD_FLAGS_ISA_2_07)
+
+test_isa_2_07_part2_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(ISA_2_07_FLAG) \
+ @FLAG_M64@ $(BUILD_FLAGS_ISA_2_07)
--- /dev/null
+mfvsrd: 0102030405060708 => 0102030405060708
+mfvsrd: 090a0b0c0e0d0e0f => 090a0b0c0e0d0e0f
+mfvsrd: f1f2f3f4f5f6f7f8 => f1f2f3f4f5f6f7f8
+mfvsrd: f9fafbfcfefdfeff => f9fafbfcfefdfeff
+
+mtvsrd: 0102030405060708 => 0102030405060708
+mtvsrd: 090a0b0c0e0d0e0f => 090a0b0c0e0d0e0f
+mtvsrd: f1f2f3f4f5f6f7f8 => f1f2f3f4f5f6f7f8
+mtvsrd: f9fafbfcfefdfeff => f9fafbfcfefdfeff
+
+mtfprwa: 05060708 => 0000000005060708
+mtfprwa: 0e0d0e0f => 000000000e0d0e0f
+mtfprwa: f5f6f7f8 => fffffffff5f6f7f8
+mtfprwa: fefdfeff => fffffffffefdfeff
+
+vaddudm: 0102030405060708 @@ 0102030405060708, ==> 020406080a0c0e10
+ 090a0b0c0e0d0e0f @@ 090a0b0c0e0d0e0f, ==> 121416181c1a1c1e
+vaddudm: 0102030405060708 @@ f1f2f3f4f5f6f7f8, ==> f2f4f6f8fafcff00
+ 090a0b0c0e0d0e0f @@ f9fafbfcfefdfeff, ==> 030507090d0b0d0e
+vaddudm: f1f2f3f4f5f6f7f8 @@ 0102030405060708, ==> f2f4f6f8fafcff00
+ f9fafbfcfefdfeff @@ 090a0b0c0e0d0e0f, ==> 030507090d0b0d0e
+vaddudm: f1f2f3f4f5f6f7f8 @@ f1f2f3f4f5f6f7f8, ==> e3e5e7e9ebedeff0
+ f9fafbfcfefdfeff @@ f9fafbfcfefdfeff, ==> f3f5f7f9fdfbfdfe
+
+vpkudum: Inputs: 05060708 0e0d0e0f 05060708 0e0d0e0f
+ Output: 05060708 0e0d0e0f 05060708 0e0d0e0f
+vpkudum: Inputs: 05060708 0e0d0e0f f5f6f7f8 fefdfeff
+ Output: 05060708 0e0d0e0f f5f6f7f8 fefdfeff
+vpkudum: Inputs: f5f6f7f8 fefdfeff 05060708 0e0d0e0f
+ Output: f5f6f7f8 fefdfeff 05060708 0e0d0e0f
+vpkudum: Inputs: f5f6f7f8 fefdfeff f5f6f7f8 fefdfeff
+ Output: f5f6f7f8 fefdfeff f5f6f7f8 fefdfeff
+
+All done. Tested 5 different instructions
--- /dev/null
+prereq: ../../../tests/check_isa-2_07_cap
+prog: test_isa_2_07_part1 -a
--- /dev/null
+
+/* HOW TO COMPILE:
+
+ * 32bit build:
+ gcc -Winline -Wall -g -O -mregnames -maltivec
+ * 64bit build:
+ gcc -Winline -Wall -g -O -mregnames -maltivec -m64
+
+
+ * jm_insns_isa_2_07.c:
+ * PPC tests for the ISA 2.07. This file is based on the
+ * jm-insns.c file for the new instructions in the ISA 2.07. The
+ * test structure has been kept the same as the original file to
+ * the extent possible.
+ *
+ * Copyright (C) 2013 IBM
+ *
+ * Authors: Carl Love <carll@us.ibm.com>
+ * Maynard Johnson <maynardj@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Operation details
+ * -----------------
+ *
+ * The 'loops' (e.g. int_loops) do the actual work:
+ * - loops over as many arguments as the insn needs (regs | imms)
+ * - sets up the environment (reset cr,xer, assign src regs...)
+ * - maybe modifies the asm instn to test different imm args
+ * - calls the test function
+ * - retrieves relevant register data (rD,cr,xer,...)
+ * - prints argument and result data.
+ *
+ * More specifically...
+ *
+ * all_tests[i] holds insn tests
+ * - of which each holds: {instn_test_arr[], description, flags}
+ *
+ * flags hold 3 instn classifiers: {family, type, arg_type}
+ *
+ * // The main test loop:
+ * do_tests( user_ctl_flags ) {
+ * foreach(curr_test = all_test[i]) {
+ *
+ * // flags are used to control what tests are run:
+ * if (curr_test->flags && !user_ctl_flags)
+ * continue;
+ *
+ * // a 'loop_family_arr' is chosen based on the 'family' flag...
+ * switch(curr_test->flags->family) {
+ * case x: loop_family_arr = int_loops;
+ * ...
+ * }
+ *
+ * // ...and the actual test_loop to run is found by indexing into
+ * // the loop_family_arr with the 'arg_type' flag:
+ * test_loop = loop_family[curr_test->flags->arg_type]
+ *
+ * // finally, loop over all instn tests for this test:
+ * foreach (instn_test = curr_test->instn_test_arr[i]) {
+ *
+ * // and call the test_loop with the current instn_test function,name
+ * test_loop( instn_test->func, instn_test->name )
+ * }
+ * }
+ * }
+ *
+ */
+
+
+/**********************************************************************/
+
+/* Uncomment to enable output of CR flags for float tests */
+//#define TEST_FLOAT_FLAGS
+
+/* Uncomment to enable debug output */
+//#define DEBUG_ARGS_BUILD
+//#define DEBUG_FILTER
+
+/**********************************************************************/
+#include <stdio.h>
+
+#ifdef HAS_ISA_2_07
+
+#include "config.h"
+#include <altivec.h>
+#include <stdint.h>
+
+#include <assert.h>
+#include <ctype.h> // isspace
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h> // getopt
+
+#if !defined (__TEST_PPC_H__)
+#define __TEST_PPC_H__
+
+#include "tests/sys_mman.h"
+#include "tests/malloc.h" // memalign16
+
+#define STATIC_ASSERT(e) sizeof(struct { int:-!(e); })
+
+/* Something of the same size as void*, so can be safely be coerced
+ * to/from a pointer type. Also same size as the host's gp registers.
+ * According to the AltiVec section of the GCC manual, the syntax does
+ * not allow the use of a typedef name as a type specifier in conjunction
+ * with the vector keyword, so typedefs uint[32|64]_t are #undef'ed here
+ * and redefined using #define.
+ */
+#undef uint32_t
+#undef uint64_t
+#define uint32_t unsigned int
+#define uint64_t unsigned long long int
+
+#ifndef __powerpc64__
+typedef uint32_t HWord_t;
+#else
+typedef uint64_t HWord_t;
+#endif /* __powerpc64__ */
+
+typedef uint64_t Word_t;
+
+enum {
+ compile_time_test1 = STATIC_ASSERT(sizeof(uint32_t) == 4),
+ compile_time_test2 = STATIC_ASSERT(sizeof(uint64_t) == 8),
+};
+
+#define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
+
+#define SET_CR(_arg) \
+ __asm__ __volatile__ ("mtcr %0" : : "b"(_arg) : ALLCR );
+
+#define SET_XER(_arg) \
+ __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
+
+#define GET_CR(_lval) \
+ __asm__ __volatile__ ("mfcr %0" : "=b"(_lval) )
+
+#define GET_XER(_lval) \
+ __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
+
+#define GET_CR_XER(_lval_cr,_lval_xer) \
+ do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
+
+#define SET_CR_ZERO \
+ SET_CR(0)
+
+#define SET_XER_ZERO \
+ SET_XER(0)
+
+#define SET_CR_XER_ZERO \
+ do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
+
+#define SET_FPSCR_ZERO \
+ do { double _d = 0.0; \
+ __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
+ } while (0)
+
+#define DEFAULT_VSCR 0x0
+
+static vector unsigned long long vec_out, vec_inA, vec_inB;
+
+/* XXXX these must all be callee-save regs! */
+register double f14 __asm__ ("fr14");
+register double f15 __asm__ ("fr15");
+register double f16 __asm__ ("fr16");
+register double f17 __asm__ ("fr17");
+register HWord_t r14 __asm__ ("r14");
+register HWord_t r17 __asm__ ("r17");
+
+typedef void (*test_func_t) (void);
+typedef struct _test test_t;
+typedef struct _test_table test_table_t;
+struct _test {
+ test_func_t func;
+ const char *name;
+};
+
+struct _test_table {
+ test_t *tests;
+ const char *name;
+ uint32_t flags;
+};
+
+typedef void (*test_loop_t) (const char *name, test_func_t func,
+ uint32_t flags);
+
+enum test_flags {
+ /* Nb arguments */
+ PPC_ONE_ARG = 0x00000001,
+ PPC_TWO_ARGS = 0x00000002,
+ PPC_THREE_ARGS = 0x00000003,
+ PPC_CMP_ARGS = 0x00000004, // family: compare
+ PPC_CMPI_ARGS = 0x00000005, // family: compare
+ PPC_TWO_I16 = 0x00000006, // family: arith/logical
+ PPC_SPECIAL = 0x00000007, // family: logical
+ PPC_LD_ARGS = 0x00000008, // family: ldst
+ PPC_LDX_ARGS = 0x00000009, // family: ldst
+ PPC_ST_ARGS = 0x0000000A, // family: ldst
+ PPC_STX_ARGS = 0x0000000B, // family: ldst
+ PPC_STQ_ARGS = 0x0000000C, // family: ldst, two args, imm
+ PPC_LDQ_ARGS = 0x0000000D, // family: ldst, two args, imm
+ PPC_STQX_ARGS = 0x0000000E, // family: ldst, three args
+ PPC_LDQX_ARGS = 0x0000000F, // family: ldst, three_args
+ PPC_NB_ARGS = 0x0000000F,
+ /* Type */
+ PPC_ARITH = 0x00000100,
+ PPC_LOGICAL = 0x00000200,
+ PPC_COMPARE = 0x00000300,
+ PPC_CROP = 0x00000400,
+ PPC_LDST = 0x00000500,
+ PPC_POPCNT = 0x00000600,
+ PPC_MOV = 0x00000A00,
+ PPC_TYPE = 0x00000F00,
+ /* Family */
+ PPC_INTEGER = 0x00010000,
+ PPC_FLOAT = 0x00020000,
+ PPC_405 = 0x00030000, // Leave so we keep numbering consistent
+ PPC_ALTIVEC = 0x00040000,
+ PPC_FALTIVEC = 0x00050000,
+ PPC_FAMILY = 0x000F0000,
+ /* Flags: these may be combined, so use separate bitfields. */
+ PPC_CR = 0x01000000,
+ PPC_XER_CA = 0x02000000,
+};
+
+#endif /* !defined (__TEST_PPC_H__) */
+
+/* -------------- END #include "test-ppc.h" -------------- */
+
+
+#if defined (DEBUG_ARGS_BUILD)
+#define AB_DPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)
+#else
+#define AB_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+#if defined (DEBUG_FILTER)
+#define FDPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)
+#else
+#define FDPRINTF(fmt, args...) do { } while (0)
+#endif
+
+#define unused __attribute__ (( unused ))
+
+typedef struct special {
+ const char *name;
+ void (*test_cb)(const char* name, test_func_t func,
+ unused uint32_t test_flags);
+} special_t;
+
+
+// VSX move instructions
+static void test_mfvsrd (void)
+{
+ __asm__ __volatile__ ("mfvsrd %0,%x1" : "=r" (r14) : "ws" (vec_inA));
+};
+
+static void test_mtvsrd (void)
+{
+ __asm__ __volatile__ ("mtvsrd %x0,%1" : "=ws" (vec_out) : "r" (r14));
+};
+
+static void test_mtfprwa (void)
+{
+ __asm__ __volatile__ ("mtfprwa %x0,%1" : "=ws" (vec_out) : "r" (r14));
+};
+
+static test_t tests_move_ops_spe[] = {
+ { &test_mfvsrd , "mfvsrd" },
+ { &test_mtvsrd , "mtvsrd" },
+ { &test_mtfprwa , "mtfprwa" },
+ { NULL, NULL }
+};
+
+/* Vector Double Word tests.
+ * NOTE: Since these are "vector" instructions versus VSX, we must use
+ * vector constraints. */
+static void test_vaddudm (void)
+{
+ __asm__ __volatile__ ("vaddudm %0, %1, %2" : "=v" (vec_out): "v" (vec_inA),"v" (vec_inB));
+}
+
+static void test_vpkudum (void)
+{
+ __asm__ __volatile__ ("vpkudum %0, %1, %2" : "=v" (vec_out): "v" (vec_inA),"v" (vec_inB));
+}
+
+static test_t tests_aa_dbl_ops_two[] = {
+ { &test_vaddudm , "vaddudm", },
+ { &test_vpkudum , "vpkudum", },
+ { NULL, NULL, },
+};
+
+static int verbose = 0;
+static int arg_list_size = 0;
+static unsigned long long * vdargs = NULL;
+#define NB_VDARGS 4
+
+static void build_vdargs_table (void)
+{
+ // Each VSX register holds two doubleword integer values
+ vdargs = memalign16(NB_VDARGS * sizeof(unsigned long long));
+ vdargs[0] = 0x0102030405060708ULL;
+ vdargs[1] = 0x090A0B0C0E0D0E0FULL;
+ vdargs[2] = 0xF1F2F3F4F5F6F7F8ULL;
+ vdargs[3] = 0xF9FAFBFCFEFDFEFFULL;
+}
+
+static int check_filter (char *filter)
+{
+ char *c;
+ int ret = 1;
+
+ if (filter != NULL) {
+ c = strchr(filter, '*');
+ if (c != NULL) {
+ *c = '\0';
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int check_name (const char* name, const char *filter,
+ int exact)
+{
+ int nlen, flen;
+ int ret = 0;
+
+ if (filter != NULL) {
+ for (; isspace(*name); name++)
+ continue;
+ FDPRINTF("Check '%s' againt '%s' (%s match)\n",
+ name, filter, exact ? "exact" : "starting");
+ nlen = strlen(name);
+ flen = strlen(filter);
+ if (exact) {
+ if (nlen == flen && memcmp(name, filter, flen) == 0)
+ ret = 1;
+ } else {
+ if (flen <= nlen && memcmp(name, filter, flen) == 0)
+ ret = 1;
+ }
+ } else {
+ ret = 1;
+ }
+ return ret;
+}
+
+
+typedef struct insn_sel_flags_t_struct {
+ int one_arg, two_args, three_args;
+ int arith, logical, compare, ldst;
+ int integer, floats, altivec, faltivec;
+ int cr;
+} insn_sel_flags_t;
+
+
+static void mfvs(const char* name, test_func_t func,
+ unused uint32_t test_flags)
+{
+ /* This test is for move instructions where the input is a scalar register
+ * and the destination is a vector register.
+ */
+ int i;
+ volatile Word_t result;
+
+ for (i=0; i < NB_VDARGS; i++) {
+ r14 = 0ULL;
+ vec_inA = (vector unsigned long long){ vdargs[i], 0ULL };
+
+ (*func)();
+ result = r14;
+ printf("%s: %016llx => %016llx\n", name, vdargs[i], result);
+ }
+}
+
+static void mtvs(const char* name, test_func_t func,
+ unused uint32_t test_flags)
+{
+ /* This test is for move instructions where the input is a scalar register
+ * and the destination is a vector register.
+ */
+ unsigned long long *dst;
+ int i;
+
+ for (i=0; i < NB_VDARGS; i++) {
+ r14 = vdargs[i];
+ vec_out = (vector unsigned long long){ 0ULL, 0ULL };
+
+ (*func)();
+ dst = (unsigned long long *) &vec_out;
+ printf("%s: %016llx => %016llx\n", name, vdargs[i], *dst);
+ }
+}
+
+static void mtvs2s(const char* name, test_func_t func,
+ unused uint32_t test_flags)
+{
+ /* This test is the mtvsrwa instruction.
+ */
+ unsigned long long *dst;
+ int i;
+
+ for (i=0; i < NB_VDARGS; i++) {
+ // Only the lower half of the vdarg doubleword arg will be used as input by mtvsrwa
+ unsigned int * src = (unsigned int *)&vdargs[i];
+ src++;
+ r14 = vdargs[i];
+ vec_out = (vector unsigned long long){ 0ULL, 0ULL };
+
+ (*func)();
+ // Only doubleword 0 is used in output
+ dst = (unsigned long long *) &vec_out;
+ printf("%s: %08x => %016llx\n", name, *src, *dst);
+ }
+}
+
+static void test_special (special_t *table,
+ const char* name, test_func_t func,
+ unused uint32_t test_flags)
+{
+ const char *tmp;
+ int i;
+
+ for (tmp = name; isspace(*tmp); tmp++)
+ continue;
+ for (i=0; table[i].name != NULL; i++) {
+ if (strcmp(table[i].name, tmp) == 0) {
+ (*table[i].test_cb)(name, func, test_flags);
+ return;
+ }
+ }
+ fprintf(stderr, "ERROR: no test found for op '%s'\n", name);
+}
+
+static special_t special_move_ops[] = {
+ {
+ "mfvsrd", /* move from vector to scalar reg */
+ &mfvs,
+ },
+ {
+ "mtvsrd", /* move from scalar to vector reg */
+ &mtvs,
+ },
+ {
+ "mtfprwa", /* (extended mnemonic for mtvsrwa) move from scalar to vector reg with two’s-complement */
+ &mtvs2s,
+ },
+};
+
+static void test_move_special(const char* name, test_func_t func,
+ uint32_t test_flags)
+{
+ test_special(special_move_ops, name, func, test_flags);
+}
+
+/* Vector Double Word tests */
+
+static void test_av_dint_two_args (const char* name, test_func_t func,
+ unused uint32_t test_flags)
+{
+
+ unsigned long long * dst;
+ unsigned int * dst_int;
+ int i,j;
+ int is_vpkudum;
+ if (strcmp(name, "vpkudum") == 0)
+ is_vpkudum = 1;
+ else
+ is_vpkudum = 0;
+
+ for (i = 0; i < NB_VDARGS; i+=2) {
+ vec_inA = (vector unsigned long long){ vdargs[i], vdargs[i+1] };
+ for (j = 0; j < NB_VDARGS; j+=2) {
+ vec_inB = (vector unsigned long long){ vdargs[j], vdargs[j+1] };
+ vec_out = (vector unsigned long long){ 0,0 };
+
+ (*func)();
+ dst_int = (unsigned int *)&vec_out;
+ dst = (unsigned long long*)&vec_out;
+
+ printf("%s: ", name);
+
+ if (is_vpkudum) {
+ printf("Inputs: %08llx %08llx %08llx %08llx\n", vdargs[i] & 0x00000000ffffffffULL,
+ vdargs[i+1] & 0x00000000ffffffffULL, vdargs[j] & 0x00000000ffffffffULL,
+ vdargs[j+1] & 0x00000000ffffffffULL);
+ printf(" Output: %08x %08x %08x %08x\n", dst_int[0], dst_int[1],
+ dst_int[2], dst_int[3]);
+ } else {
+ printf("%016llx @@ %016llx, ", vdargs[i], vdargs[j]);
+ printf(" ==> %016llx\n", dst[0]);
+ printf("\t%016llx @@ %016llx, ", vdargs[i+1], vdargs[j+1]);
+ printf(" ==> %016llx\n", dst[1]);
+ }
+ }
+ }
+}
+
+/* Used in do_tests, indexed by flags->nb_args
+ Elements correspond to enum test_flags::num args
+*/
+static test_loop_t altivec_mov_loops[] = {
+ &test_move_special,
+ NULL
+};
+
+static test_loop_t altivec_dint_loops[] = {
+ &test_av_dint_two_args,
+ NULL
+};
+
+static test_table_t all_tests[] = {
+ {
+ tests_move_ops_spe,
+ "PPC VSR special move insns",
+ PPC_ALTIVEC | PPC_MOV | PPC_ONE_ARG,
+ },
+ {
+ tests_aa_dbl_ops_two,
+ "PC altivec double word integer insns with two args",
+ PPC_ALTIVEC | PPC_ARITH | PPC_TWO_ARGS,
+ },
+ { NULL, NULL, 0x00000000, },
+};
+
+static void do_tests ( insn_sel_flags_t seln_flags,
+ char *filter)
+{
+ test_loop_t *loop;
+ test_t *tests;
+ int nb_args, type, family;
+ int i, j, n;
+ int exact;
+
+ exact = check_filter(filter);
+ n = 0;
+ for (i=0; all_tests[i].name != NULL; i++) {
+ nb_args = all_tests[i].flags & PPC_NB_ARGS;
+
+ /* Check number of arguments */
+ if ((nb_args == 1 && !seln_flags.one_arg) ||
+ (nb_args == 2 && !seln_flags.two_args) ||
+ (nb_args == 3 && !seln_flags.three_args)){
+ continue;
+ }
+ /* Check instruction type */
+ type = all_tests[i].flags & PPC_TYPE;
+ if ((type == PPC_ARITH && !seln_flags.arith) ||
+ (type == PPC_LOGICAL && !seln_flags.logical) ||
+ (type == PPC_COMPARE && !seln_flags.compare) ||
+ (type == PPC_LDST && !seln_flags.ldst) ||
+ (type == PPC_MOV && !seln_flags.ldst) ||
+ (type == PPC_POPCNT && !seln_flags.arith)) {
+ continue;
+ }
+
+ /* Check instruction family */
+ family = all_tests[i].flags & PPC_FAMILY;
+ if ((family == PPC_INTEGER && !seln_flags.integer) ||
+ (family == PPC_FLOAT && !seln_flags.floats) ||
+ (family == PPC_ALTIVEC && !seln_flags.altivec) ||
+ (family == PPC_FALTIVEC && !seln_flags.faltivec)) {
+ continue;
+ }
+ /* Check flags update */
+ if (((all_tests[i].flags & PPC_CR) && seln_flags.cr == 0) ||
+ (!(all_tests[i].flags & PPC_CR) && seln_flags.cr == 1))
+ continue;
+
+ /* All passed, do the tests */
+ tests = all_tests[i].tests;
+
+ loop = NULL;
+
+ /* Select the test loop */
+ switch (family) {
+ case PPC_INTEGER:
+ printf("Currently there are no integer tests enabled in this testsuite.\n");
+ break;
+
+ case PPC_FLOAT:
+ printf("Currently there are no float tests enabled in this testsuite.\n");
+ break;
+
+ case PPC_ALTIVEC:
+ switch (type) {
+ case PPC_MOV:
+ loop = &altivec_mov_loops[0];
+ break;
+ case PPC_ARITH:
+ loop = &altivec_dint_loops[0];
+ break;
+ default:
+ printf("No altivec test defined for type %x\n", type);
+ }
+ break;
+
+ case PPC_FALTIVEC:
+ printf("Currently there are no floating altivec tests in this testsuite.\n");
+ break;
+
+ default:
+ printf("ERROR: unknown insn family %08x\n", family);
+ continue;
+ }
+ if (1 || verbose > 0)
+ for (j=0; tests[j].name != NULL; j++) {
+ if (check_name(tests[j].name, filter, exact)) {
+ if (verbose > 1)
+ printf("Test instruction %s\n", tests[j].name);
+ if (loop != NULL)
+ (*loop)(tests[j].name, tests[j].func, all_tests[i].flags);
+ printf("\n");
+ n++;
+ }
+ }
+ if (verbose) printf("\n");
+ }
+ printf("All done. Tested %d different instructions\n", n);
+}
+
+
+static void usage (void)
+{
+ fprintf(stderr,
+ "Usage: jm-insns [OPTION]\n"
+ "\t-i: test integer instructions (default)\n"
+ "\t-f: test floating point instructions\n"
+ "\t-a: test altivec instructions\n"
+ "\t-A: test all (int, fp, altivec) instructions\n"
+ "\t-v: be verbose\n"
+ "\t-h: display this help and exit\n"
+ );
+}
+
+#endif
+
+int main (int argc, char **argv)
+{
+#ifdef HAS_ISA_2_07
+ /* Simple usage:
+ ./jm-insns -i => int insns
+ ./jm-insns -f => fp insns
+ ./jm-insns -a => av insns
+ ./jm-insns -A => int, fp and avinsns
+ */
+ char *filter = NULL;
+ insn_sel_flags_t flags;
+ int c;
+
+ // Args
+ flags.one_arg = 1;
+ flags.two_args = 1;
+ flags.three_args = 1;
+ // Type
+ flags.arith = 1;
+ flags.logical = 1;
+ flags.compare = 1;
+ flags.ldst = 1;
+ // Family
+ flags.integer = 0;
+ flags.floats = 0;
+ flags.altivec = 0;
+ flags.faltivec = 0;
+ // Flags
+ flags.cr = 2;
+
+ while ((c = getopt(argc, argv, "ifahvA")) != -1) {
+ switch (c) {
+ case 'i':
+ flags.integer = 1;
+ break;
+ case 'f':
+ flags.floats = 1;
+ break;
+ case 'a':
+ flags.altivec = 1;
+ flags.faltivec = 1;
+ break;
+ case 'A':
+ flags.integer = 1;
+ flags.floats = 1;
+ flags.altivec = 1;
+ flags.faltivec = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage();
+ fprintf(stderr, "Unknown argument: '%c'\n", c);
+ return 1;
+ }
+ }
+
+ arg_list_size = 0;
+
+ build_vdargs_table();
+ if (verbose > 1) {
+ printf("\nInstruction Selection:\n");
+ printf(" n_args: \n");
+ printf(" one_arg = %d\n", flags.one_arg);
+ printf(" two_args = %d\n", flags.two_args);
+ printf(" three_args = %d\n", flags.three_args);
+ printf(" type: \n");
+ printf(" arith = %d\n", flags.arith);
+ printf(" logical = %d\n", flags.logical);
+ printf(" compare = %d\n", flags.compare);
+ printf(" ldst = %d\n", flags.ldst);
+ printf(" family: \n");
+ printf(" integer = %d\n", flags.integer);
+ printf(" floats = %d\n", flags.floats);
+ printf(" altivec = %d\n", flags.altivec);
+ printf(" faltivec = %d\n", flags.faltivec);
+ printf(" cr update: \n");
+ printf(" cr = %d\n", flags.cr);
+ printf("\n");
+ }
+
+ do_tests( flags, filter );
+#else
+ printf("NO ISA 2.07 SUPPORT\n");
+#endif
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2013 IBM
+
+ Authors: Carl Love <carll@us.ibm.com>
+ Maynard Johnson <maynardj@us.ibm.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+
+ This program is based heavily on the test_isa_2_06_part*.c source files.
+ */
+
+#include <stdio.h>
+
+#ifdef HAS_ISA_2_07
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <altivec.h>
+#include <math.h>
+
+#ifndef __powerpc64__
+typedef uint32_t HWord_t;
+#else
+typedef uint64_t HWord_t;
+#endif /* __powerpc64__ */
+
+static int errors;
+register HWord_t r14 __asm__ ("r14");
+register HWord_t r15 __asm__ ("r15");
+register HWord_t r16 __asm__ ("r16");
+register HWord_t r17 __asm__ ("r17");
+register double f14 __asm__ ("fr14");
+register double f15 __asm__ ("fr15");
+register double f16 __asm__ ("fr16");
+register double f17 __asm__ ("fr17");
+
+static volatile unsigned int cond_reg;
+
+#define True 1
+#define False 0
+
+#define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
+
+#define SET_CR(_arg) \
+ __asm__ __volatile__ ("mtcr %0" : : "b"(_arg) : ALLCR );
+
+#define SET_XER(_arg) \
+ __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
+
+#define GET_CR(_lval) \
+ __asm__ __volatile__ ("mfcr %0" : "=b"(_lval) )
+
+#define GET_XER(_lval) \
+ __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
+
+#define GET_CR_XER(_lval_cr,_lval_xer) \
+ do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
+
+#define SET_CR_ZERO \
+ SET_CR(0)
+
+#define SET_XER_ZERO \
+ SET_XER(0)
+
+#define SET_CR_XER_ZERO \
+ do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
+
+#define SET_FPSCR_ZERO \
+ do { double _d = 0.0; \
+ __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
+ } while (0)
+
+
+typedef void (*test_func_t)(void);
+typedef struct vsx_logic_test logic_test_t;
+typedef struct ldst_test ldst_test_t;
+typedef struct xs_conv_test xs_conv_test_t;
+typedef struct vx_fp_test vx_fp_test_t;
+typedef struct vx_fp_test2 vx_fp_test2_t;
+typedef struct test_table test_table_t;
+
+typedef unsigned char Bool;
+
+
+/* These functions below that construct a table of floating point
+ * values were lifted from none/tests/ppc32/jm-insns.c.
+ */
+
+#if defined (DEBUG_ARGS_BUILD)
+#define AB_DPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)
+#else
+#define AB_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+static inline void register_farg (void *farg,
+ int s, uint16_t _exp, uint64_t mant)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)s << 63) | ((uint64_t)_exp << 52) | mant;
+ *(uint64_t *)farg = tmp;
+ AB_DPRINTF("%d %03x %013llx => %016llx %0e\n",
+ s, _exp, mant, *(uint64_t *)farg, *(double *)farg);
+}
+
+
+typedef struct fp_test_args {
+ int fra_idx;
+ int frb_idx;
+ int cr_flags;
+ unsigned long long dp_bin_result;
+} fp_test_args_t;
+
+static int nb_special_fargs;
+static double * spec_fargs;
+static float * spec_sp_fargs;
+
+static void build_special_fargs_table(void)
+{
+ /* The special floating point values created below are for
+ * use in the ftdiv tests for setting the fe_flag and fg_flag,
+ * but they can also be used for other tests (e.g., xscmpudp).
+ *
+ * Note that fl_flag is 'always '1' on ppc64 Linux.
+ *
+ Entry Sign Exp fraction Special value
+ 0 0 3fd 0x8000000000000ULL Positive finite number
+ 1 0 404 0xf000000000000ULL ...
+ 2 0 001 0x8000000b77501ULL ...
+ 3 0 7fe 0x800000000051bULL ...
+ 4 0 012 0x3214569900000ULL ...
+ 5 0 000 0x0000000000000ULL +0.0 (+zero)
+ 6 1 000 0x0000000000000ULL -0.0 (-zero)
+ 7 0 7ff 0x0000000000000ULL +infinity
+ 8 1 7ff 0x0000000000000ULL -infinity
+ 9 0 7ff 0x7FFFFFFFFFFFFULL +QNaN
+ 10 1 7ff 0x7FFFFFFFFFFFFULL -QNaN
+ 11 0 7ff 0x8000000000000ULL +SNaN
+ 12 1 7ff 0x8000000000000ULL -SNaN
+ 13 1 000 0x8340000078000ULL Denormalized val (zero exp and non-zero fraction)
+ 14 1 40d 0x0650f5a07b353ULL Negative finite number
+ */
+
+ uint64_t mant;
+ uint16_t _exp;
+ int s;
+ int j, i = 0;
+
+ if (spec_fargs)
+ return;
+
+ spec_fargs = malloc( 20 * sizeof(double) );
+ spec_sp_fargs = malloc( 20 * sizeof(float) );
+
+ // #0
+ s = 0;
+ _exp = 0x3fd;
+ mant = 0x8000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #1
+ s = 0;
+ _exp = 0x404;
+ mant = 0xf000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #2
+ s = 0;
+ _exp = 0x001;
+ mant = 0x8000000b77501ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #3
+ s = 0;
+ _exp = 0x7fe;
+ mant = 0x800000000051bULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #4
+ s = 0;
+ _exp = 0x012;
+ mant = 0x3214569900000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* Special values */
+ /* +0.0 : 0 0x000 0x0000000000000 */
+ // #5
+ s = 0;
+ _exp = 0x000;
+ mant = 0x0000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* -0.0 : 1 0x000 0x0000000000000 */
+ // #6
+ s = 1;
+ _exp = 0x000;
+ mant = 0x0000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* +infinity : 0 0x7FF 0x0000000000000 */
+ // #7
+ s = 0;
+ _exp = 0x7FF;
+ mant = 0x0000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* -infinity : 1 0x7FF 0x0000000000000 */
+ // #8
+ s = 1;
+ _exp = 0x7FF;
+ mant = 0x0000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* +QNaN : 0 0x7FF 0x7FFFFFFFFFFFF */
+ // #9
+ s = 0;
+ _exp = 0x7FF;
+ mant = 0x7FFFFFFFFFFFFULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* -QNaN : 1 0x7FF 0x7FFFFFFFFFFFF */
+ // #10
+ s = 1;
+ _exp = 0x7FF;
+ mant = 0x7FFFFFFFFFFFFULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* +SNaN : 0 0x7FF 0x8000000000000 */
+ // #11
+ s = 0;
+ _exp = 0x7FF;
+ mant = 0x8000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* -SNaN : 1 0x7FF 0x8000000000000 */
+ // #12
+ s = 1;
+ _exp = 0x7FF;
+ mant = 0x8000000000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* denormalized value */
+ // #13
+ s = 1;
+ _exp = 0x000;
+ mant = 0x8340000078000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* Negative finite number */
+ // #14
+ s = 1;
+ _exp = 0x40d;
+ mant = 0x0650f5a07b353ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ /* A few positive finite numbers ... */
+ // #15
+ s = 0;
+ _exp = 0x412;
+ mant = 0x32585a9900000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #16
+ s = 0;
+ _exp = 0x413;
+ mant = 0x82511a2000000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #17
+ s = 0;
+ _exp = 0x403;
+ mant = 0x12ef5a9300000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #18
+ s = 0;
+ _exp = 0x405;
+ mant = 0x14bf5d2300000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+ // #19
+ s = 0;
+ _exp = 0x409;
+ mant = 0x76bf982440000ULL;
+ register_farg(&spec_fargs[i++], s, _exp, mant);
+
+
+ nb_special_fargs = i;
+ for (j = 0; j < i; j++) {
+ spec_sp_fargs[j] = spec_fargs[j];
+ }
+}
+
+struct test_table
+{
+ test_func_t test_category;
+ char * name;
+};
+
+
+typedef enum {
+ SINGLE_TEST,
+ DOUBLE_TEST,
+ DOUBLE_TEST_SINGLE_RES
+} precision_type_t;
+
+typedef enum {
+ VX_FP_SMAS, // multiply add single precision result
+ VX_FP_SMSS, // multiply sub single precision result
+ VX_FP_SNMAS, // negative multiply add single precision result
+ VX_FP_SNMSS, // negative multiply sub single precision result
+ VX_FP_OTHER,
+ VX_CONV_WORD,
+ VX_ESTIMATE,
+ VX_CONV_TO_SINGLE,
+ VX_CONV_TO_DOUBLE,
+ VX_SCALAR_CONV_TO_WORD,
+ VX_DEFAULT
+} vx_fp_test_type;
+
+
+struct vx_fp_test2
+{
+ test_func_t test_func;
+ const char *name;
+ fp_test_args_t * targs;
+ int num_tests;
+ precision_type_t precision;
+ vx_fp_test_type test_type;
+ const char * op;
+};
+
+static vector unsigned int vec_out, vec_inB;
+
+static void test_xscvdpspn(void)
+{
+ __asm__ __volatile__ ("xscvdpspn %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
+}
+
+static void test_xscvspdpn(void)
+{
+ __asm__ __volatile__ ("xscvspdpn %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
+}
+static vx_fp_test2_t
+vsx_one_fp_arg_tests[] = {
+ { &test_xscvdpspn, "xscvdpspn", NULL, 20, DOUBLE_TEST, VX_CONV_TO_SINGLE, "conv"},
+ { &test_xscvspdpn, "xscvspdpn", NULL, 20, SINGLE_TEST, VX_CONV_TO_DOUBLE, "conv"},
+ { NULL, NULL, NULL, 0, 0, 0, NULL}
+};
+
+
+static void test_vsx_one_fp_arg(void)
+{
+ test_func_t func;
+ int k;
+ k = 0;
+ build_special_fargs_table();
+
+ while ((func = vsx_one_fp_arg_tests[k].test_func)) {
+ int idx, i;
+ vx_fp_test2_t test_group = vsx_one_fp_arg_tests[k];
+ /* size of source operands */
+ Bool dp = ((test_group.precision == DOUBLE_TEST) ||
+ (test_group.precision == DOUBLE_TEST_SINGLE_RES)) ? True : False;
+ /* size of result */
+ Bool is_sqrt = (strstr(test_group.name, "sqrt")) ? True : False;
+ Bool is_scalar = (strstr(test_group.name, "xs")) ? True : False;
+ Bool sparse_sp = False;
+ int stride = dp ? 2 : 4;
+ int loops = is_scalar ? 1 : stride;
+ stride = is_scalar ? 1: stride;
+
+ /* For conversions of single to double, the 128-bit input register is sparsely populated:
+ * |___ SP___|_Unused_|___SP___|__Unused__| // for vector op
+ * or
+ * |___ SP___|_Unused_|_Unused_|__Unused__| // for scalar op
+ *
+ * For the vector op case, we need to adjust stride from '4' to '2', since
+ * we'll only be loading two values per loop into the input register.
+ */
+ if (!dp && !is_scalar && test_group.test_type == VX_CONV_TO_DOUBLE) {
+ sparse_sp = True;
+ stride = 2;
+ }
+
+ for (i = 0; i < test_group.num_tests; i+=stride) {
+ unsigned int * pv;
+ void * inB;
+
+ pv = (unsigned int *)&vec_out;
+ // clear vec_out
+ for (idx = 0; idx < 4; idx++, pv++)
+ *pv = 0;
+
+ if (dp) {
+ int j;
+ unsigned long long * frB_dp, *dst_dp;
+ for (j = 0; j < loops; j++) {
+ inB = (void *)&spec_fargs[i + j];
+ // copy double precision FP into vector element i
+ memcpy(((void *)&vec_inB) + (j * 8), inB, 8);
+ }
+ // execute test insn
+ (*func)();
+ dst_dp = (unsigned long long *) &vec_out;
+ printf("#%d: %s ", i/stride, test_group.name);
+ for (j = 0; j < loops; j++) {
+ if (j)
+ printf("; ");
+ frB_dp = (unsigned long long *)&spec_fargs[i + j];
+ printf("%s(%016llx)", test_group.op, *frB_dp);
+ vx_fp_test_type type = test_group.test_type;
+ switch (type) {
+ case VX_SCALAR_CONV_TO_WORD:
+ printf(" = %016llx", dst_dp[j] & 0x00000000ffffffffULL);
+ break;
+ case VX_CONV_TO_SINGLE:
+ printf(" = %016llx", dst_dp[j] & 0xffffffff00000000ULL);
+ break;
+ default: // For VX_CONV_TO_DOUBLE and non-convert instructions . . .
+ printf(" = %016llx", dst_dp[j]);
+ }
+ }
+ printf("\n");
+ } else {
+ int j, skip_slot;
+ unsigned int * frB_sp, * dst_sp = NULL;
+ unsigned long long * dst_dp = NULL;
+ if (sparse_sp) {
+ skip_slot = 1;
+ loops = 2;
+ } else {
+ skip_slot = 0;
+ }
+ for (j = 0; j < loops; j++) {
+ inB = (void *)&spec_sp_fargs[i + j];
+ // copy single precision FP into vector element i
+
+ if (skip_slot && j > 0)
+ memcpy(((void *)&vec_inB) + ((j + j) * 4), inB, 4);
+ else
+ memcpy(((void *)&vec_inB) + (j * 4), inB, 4);
+ }
+ // execute test insn
+ (*func)();
+ if (test_group.test_type == VX_CONV_TO_DOUBLE)
+ dst_dp = (unsigned long long *) &vec_out;
+ else
+ dst_sp = (unsigned int *) &vec_out;
+ // print result
+ printf("#%d: %s ", i/stride, test_group.name);
+ for (j = 0; j < loops; j++) {
+ if (j)
+ printf("; ");
+ frB_sp = (unsigned int *)&spec_sp_fargs[i + j];
+ printf("%s(%08x)", test_group.op, *frB_sp);
+ if (test_group.test_type == VX_CONV_TO_DOUBLE)
+ printf(" = %016llx", dst_dp[j]);
+ else
+ /* Special case: Current VEX implementation for fsqrts (single precision)
+ * uses the same implementation as that used for double precision fsqrt.
+ * However, I've found that for xvsqrtsp, the result from that implementation
+ * may be off by the two LSBs. Generally, even this small inaccuracy can cause the
+ * output to appear very different if you end up with a carry. But for the given
+ * inputs in this testcase, we can simply mask out these bits.
+ */
+ printf(" = %08x", is_sqrt ? (dst_sp[j] & 0xfffffffc) : dst_sp[j]);
+ }
+ printf("\n");
+ }
+ }
+ k++;
+ printf( "\n" );
+ }
+}
+
+//----------------------------------------------------------
+
+static test_table_t all_tests[] = {
+ { &test_vsx_one_fp_arg,
+ "Test VSX vector and scalar single argument instructions"} ,
+ { NULL, NULL }
+};
+
+#endif
+
+int main(int argc, char *argv[])
+{
+
+#ifdef HAS_ISA_2_07
+ test_table_t aTest;
+ test_func_t func;
+ int i = 0;
+
+ while ((func = all_tests[i].test_category)) {
+ aTest = all_tests[i];
+ printf( "%s\n", aTest.name );
+ (*func)();
+ i++;
+ }
+ if (errors)
+ printf("Testcase FAILED with %d errors \n", errors);
+ else
+ printf("Testcase PASSED\n");
+
+#else
+ printf("NO ISA 2.07 SUPPORT\n");
+#endif
+ return 0;
+}
--- /dev/null
+Test VSX vector and scalar single argument instructions
+#0: xscvdpspn conv(3fd8000000000000) = 3ec0000000000000
+#1: xscvdpspn conv(404f000000000000) = 4278000000000000
+#2: xscvdpspn conv(0018000000b77501) = 0000000000000000
+#3: xscvdpspn conv(7fe800000000051b) = 7f40000000000000
+#4: xscvdpspn conv(0123214569900000) = 0000000000000000
+#5: xscvdpspn conv(0000000000000000) = 0000000000000000
+#6: xscvdpspn conv(8000000000000000) = 8000000000000000
+#7: xscvdpspn conv(7ff0000000000000) = 7f80000000000000
+#8: xscvdpspn conv(fff0000000000000) = ff80000000000000
+#9: xscvdpspn conv(7ff7ffffffffffff) = 7fbfffff00000000
+#10: xscvdpspn conv(fff7ffffffffffff) = ffbfffff00000000
+#11: xscvdpspn conv(7ff8000000000000) = 7fc0000000000000
+#12: xscvdpspn conv(fff8000000000000) = ffc0000000000000
+#13: xscvdpspn conv(8008340000078000) = 8000000000000000
+#14: xscvdpspn conv(c0d0650f5a07b353) = c683287a00000000
+#15: xscvdpspn conv(41232585a9900000) = 49192c2d00000000
+#16: xscvdpspn conv(41382511a2000000) = 49c1288d00000000
+#17: xscvdpspn conv(40312ef5a9300000) = 418977ad00000000
+#18: xscvdpspn conv(40514bf5d2300000) = 428a5fae00000000
+#19: xscvdpspn conv(40976bf982440000) = 44bb5fcc00000000
+
+#0: xscvspdpn conv(3ec00000) = 3fd8000000000000
+#1: xscvspdpn conv(42780000) = 404f000000000000
+#2: xscvspdpn conv(00000000) = 0000000000000000
+#3: xscvspdpn conv(7f800000) = 7ff0000000000000
+#4: xscvspdpn conv(00000000) = 0000000000000000
+#5: xscvspdpn conv(00000000) = 0000000000000000
+#6: xscvspdpn conv(80000000) = 8000000000000000
+#7: xscvspdpn conv(7f800000) = 7ff0000000000000
+#8: xscvspdpn conv(ff800000) = fff0000000000000
+#9: xscvspdpn conv(7fffffff) = 7fffffffe0000000
+#10: xscvspdpn conv(ffffffff) = ffffffffe0000000
+#11: xscvspdpn conv(7fc00000) = 7ff8000000000000
+#12: xscvspdpn conv(ffc00000) = fff8000000000000
+#13: xscvspdpn conv(80000000) = 8000000000000000
+#14: xscvspdpn conv(c683287b) = c0d0650f60000000
+#15: xscvspdpn conv(49192c2d) = 41232585a0000000
+#16: xscvspdpn conv(49c1288d) = 41382511a0000000
+#17: xscvspdpn conv(418977ad) = 40312ef5a0000000
+#18: xscvspdpn conv(428a5faf) = 40514bf5e0000000
+#19: xscvspdpn conv(44bb5fcc) = 40976bf980000000
+
+Testcase PASSED
--- /dev/null
+prereq: ../../../tests/check_isa-2_07_cap
+prog: test_isa_2_07_part2
#!/bin/sh
-# We use this script to check whether or not the processor supports Power ISA 2.06.
+# We use this script to check whether or not the processor supports Power ISA 2.06 or later.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+LD_SHOW_AUXV=1 $DIR/true | grep arch_2_06 > /dev/null 2>&1
-LD_SHOW_AUXV=1 /bin/true | grep arch_2_06 > /dev/null 2>&1
if [ "$?" -ne "0" ]; then
exit 1
else
--- /dev/null
+#!/bin/sh
+
+# We use this script to check whether or not the processor supports
+# Power ISA 2.07.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+LD_SHOW_AUXV=1 $DIR/true | grep arch_2_07 > /dev/null 2>&1
+
+if [ "$?" -ne "0" ]; then
+ exit 1
+else
+ exit 0
+fi