s390: Add testcase for fixbr.
Patch by Andreas Arnez <arnez@linux.vnet.ibm.com>.
Part of fixing BZ #350290.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15629
349941 di_notify_mmap might create wrong start/size DebugInfoMapping
350062 vex x86->IR: 0x66 0xF 0x3A 0xB (ROUNDSD) on OS X
350202 Add limited param to 'monitor block_list'
+350290 s390x: Support instructions fixbr(a)
350809 Fix none/tests/async-sigs for Solaris
350811 Remove reference to --db-attach which has been removed.
350813 Memcheck/x86: enable handwritten assembly helpers for x86/Solaris too
=== VEX/s390x ==========================================================
-350290 s390x unsupported instruction fixbra
-
=== VEX general ========================================================
=== Syscalls/ioctls ====================================================
lcxbr,"load complement extended bfp",implemented,
lcdbr,"load complement long bfp",implemented,
lcebr,"load complement short bfp",implemented,
-fixbr,"load fp integer extended bfp","not implemented",
-fidbr,"load fp integer long bfp","implemented",
-fiebr,"load fp integer short bfp","implemented",
+fixbr,"load fp integer extended bfp",implemented,
+fidbr,"load fp integer long bfp",implemented,
+fiebr,"load fp integer short bfp",implemented,
lfpc,"load fpc",implemented,
lxdbr,"load lengthened long to extended bfp",implemented,
lxdb,"load lengthened long to extended bfp",implemented,
/* I32(rm) x D128 -> D128 */
return mkLazy2(mce, Ity_I128, vatom1, vatom2);
+ case Iop_RoundF128toInt:
+ /* I32(rm) x F128 -> F128 */
+ return mkLazy2(mce, Ity_I128, vatom1, vatom2);
+
case Iop_D64toI64S:
case Iop_D64toI64U:
case Iop_I64StoD64:
{ DEFOP(Iop_CosF64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_TanF64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
{ DEFOP(Iop_2xm1F64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
- { DEFOP(Iop_RoundF64toInt, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .tilegx = 0 },
- { DEFOP(Iop_RoundF32toInt, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1, .tilegx = 0 },
+ { DEFOP(Iop_RoundF128toInt, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .tilegx = 0 },
+ { DEFOP(Iop_RoundF64toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .tilegx = 0 },
+ { DEFOP(Iop_RoundF32toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1, .tilegx = 0 },
{ DEFOP(Iop_MAddF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .tilegx = 0 },
{ DEFOP(Iop_MSubF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .tilegx = 0 },
{ DEFOP(Iop_MAddF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1, .tilegx = 0 },
UNARY(Ity_F128, Ity_F128);
case Iop_SqrtF128:
+ case Iop_RoundF128toInt:
BINARY(ity_RMode,Ity_F128, Ity_F128);
case Iop_I32StoF128: UNARY(Ity_I32, Ity_F128);
INSN_TESTS += dfp-1 dfp-2 dfp-3 dfp-4 dfptest dfpext dfpconv srnmt pfpo
endif
if HAS_MLONG_DOUBLE_128
- INSN_TESTS += fpext
+ INSN_TESTS += fpext fixbr
endif
check_PROGRAMS = $(INSN_TESTS) \
ecag.stdout.exp-z10ec ecag.stdout.exp-z196 ecag.stdout.exp-zec12 \
ecag.stdout.exp-z13 \
op00.stderr.exp1 op00.stderr.exp2 op00.vgtest \
+ fixbr.vgtest fixbr.stderr.exp fixbr.stdout.exp \
fpext.vgtest fpext.stderr.exp fpext.stdout.exp \
fpext_fail.vgtest fpext_fail.stderr.exp fpext_fail.stdout.exp \
test.h opcodes.h add.h and.h div.h insert.h dfp_utils.h \
cu14_1_CFLAGS = $(AM_CFLAGS) -DM3=1
cu21_1_CFLAGS = $(AM_CFLAGS) -DM3=1
cu24_1_CFLAGS = $(AM_CFLAGS) -DM3=1
+fixbr_CFLAGS = $(AM_CFLAGS) @FLAG_MLONG_DOUBLE_128@
fpext_CFLAGS = $(AM_CFLAGS) @FLAG_MLONG_DOUBLE_128@
ex_clone_LDFLAGS = -lpthread
--- /dev/null
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include "opcodes.h"
+#include "rounding.h"
+
+/* Test "fixbr" with rounding mode given in insn (m3 field)
+ Covers all generally available rounding modes that can be mapped to
+ IRRoundingMode. As a consequence m3=1 which is "round to nearest with
+ ties away from 0" is not tested here.
+*/
+
+const char *
+rtext(unsigned m3_round)
+{
+ switch (m3_round) {
+ case 0: return "[-> per fpc]";
+ case 1: return "[-> nearest away]";
+ case 3: return "[-> prepare short]"; // floating point extension fac needed
+ case 4: return "[-> nearest even]";
+ case 5: return "[-> 0]";
+ case 6: return "[-> +inf]";
+ case 7: return "[-> -inf]";
+ }
+ assert(0);
+}
+
+#define round_to_int(value,round) \
+do { \
+ long double src = value; \
+ long double dst; \
+ \
+ __asm__ volatile ("fixbr %[dst]," #round ",%[src]\n\t" \
+ : [dst] "=f"(dst) \
+ : [src] "f"(src)); \
+ \
+ printf("fixbr %.5Lf\t-> %Lg %s\n", \
+ src, dst, rtext(round)); \
+} while (0)
+
+#define fixbr(value,round) round_to_int(value,round)
+
+void
+set_rounding_mode(unsigned mode)
+{
+ register unsigned r asm("1") = mode;
+ __asm__ volatile ( SFPC(1) : : "d"(r) );
+}
+
+
+int main(void)
+{
+ int j;
+ static const long double dval[] = {
+ 1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0,
+ };
+
+ assert(sizeof(long double) == 16);
+
+ /* f128 -> f128, round to int */
+ for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
+ set_rounding_mode(FPC_BFP_ROUND_ZERO);
+ fixbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
+ set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
+ fixbr(dval[j], M3_BFP_ROUND_ZERO);
+ fixbr(dval[j], M3_BFP_ROUND_POSINF);
+ fixbr(dval[j], M3_BFP_ROUND_NEGINF);
+ }
+
+ return 0;
+}
--- /dev/null
+fixbr 1.25000 -> 1 [-> nearest even]
+fixbr 1.25000 -> 1 [-> 0]
+fixbr 1.25000 -> 2 [-> +inf]
+fixbr 1.25000 -> 1 [-> -inf]
+fixbr 1.50000 -> 2 [-> nearest even]
+fixbr 1.50000 -> 1 [-> 0]
+fixbr 1.50000 -> 2 [-> +inf]
+fixbr 1.50000 -> 1 [-> -inf]
+fixbr 2.50000 -> 2 [-> nearest even]
+fixbr 2.50000 -> 2 [-> 0]
+fixbr 2.50000 -> 3 [-> +inf]
+fixbr 2.50000 -> 2 [-> -inf]
+fixbr 1.75000 -> 2 [-> nearest even]
+fixbr 1.75000 -> 1 [-> 0]
+fixbr 1.75000 -> 2 [-> +inf]
+fixbr 1.75000 -> 1 [-> -inf]
+fixbr -1.25000 -> -1 [-> nearest even]
+fixbr -1.25000 -> -1 [-> 0]
+fixbr -1.25000 -> -1 [-> +inf]
+fixbr -1.25000 -> -2 [-> -inf]
+fixbr -1.50000 -> -2 [-> nearest even]
+fixbr -1.50000 -> -1 [-> 0]
+fixbr -1.50000 -> -1 [-> +inf]
+fixbr -1.50000 -> -2 [-> -inf]
+fixbr -2.50000 -> -2 [-> nearest even]
+fixbr -2.50000 -> -2 [-> 0]
+fixbr -2.50000 -> -2 [-> +inf]
+fixbr -2.50000 -> -3 [-> -inf]
+fixbr -1.75000 -> -2 [-> nearest even]
+fixbr -1.75000 -> -1 [-> 0]
+fixbr -1.75000 -> -1 [-> +inf]
+fixbr -1.75000 -> -2 [-> -inf]
+fixbr 0.00000 -> 0 [-> nearest even]
+fixbr 0.00000 -> 0 [-> 0]
+fixbr 0.00000 -> 0 [-> +inf]
+fixbr 0.00000 -> 0 [-> -inf]
--- /dev/null
+prog: fixbr
+prereq: test -e fixbr && ../../../tests/s390x_features s390x-fpext