s390: Add testcases for srnm and srnmb. Update opcode status list.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12997 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/docs/internals/s390-opcodes.csv b/docs/internals/s390-opcodes.csv
index 6b5528c..2f88c86 100644
--- a/docs/internals/s390-opcodes.csv
+++ b/docs/internals/s390-opcodes.csv
@@ -959,4 +959,4 @@
 mxtra,"multiply extended dfp with rounding mode","not implemented","new to z196"
 sdtra,"subtract long dfp with rounding mode","not implemented","new to z196"
 sxtra,"subtract extended dfp with rounding mode","not implemented","new to z196"
-srnmb,"set 3 bit bfp rounding mode","not implemented",
+srnmb,"set 3 bit bfp rounding mode",implemented,
diff --git a/none/tests/s390x/Makefile.am b/none/tests/s390x/Makefile.am
index 3ffc730..a8d736a 100644
--- a/none/tests/s390x/Makefile.am
+++ b/none/tests/s390x/Makefile.am
@@ -10,7 +10,7 @@
              cs csg cds cdsg cu21 cu21_1 cu24 cu24_1 cu42 cu12 cu12_1 \
              ex_sig ex_clone cu14 cu14_1 cu41 fpconv ecag fpext fpext_warn \
              rounding-1 rounding-2 rounding-3 rounding-4 rounding-5 bfp-1 \
-             bfp-2 bfp-3 bfp-4
+             bfp-2 bfp-3 bfp-4 srnm srnmb
 
 check_PROGRAMS = $(INSN_TESTS) \
 		 allexec \
diff --git a/none/tests/s390x/opcodes.h b/none/tests/s390x/opcodes.h
index 1d0daaf..b3aa7d6 100644
--- a/none/tests/s390x/opcodes.h
+++ b/none/tests/s390x/opcodes.h
@@ -98,6 +98,7 @@
             ".short 0x" #op1 #r1 #r2 "\n\t"  \
             ".long  0x" #i3 #i4 #i5 #op2 "\n\t"
 #define RRF_M0RERE(op,m3,r1,r2)  ".long 0x" #op #m3 "0" #r1 #r2 "\n\t"
+#define S_RD(op,b2,d2) ".long 0x" #op #b2 #d2 "\n\t"
 
 #define AFI(r1,i2)                      RIL_RI(c2,r1,9,i2)
 #define AGFI(r1,i2)                     RIL_RI(c2,r1,8,i2)
@@ -318,6 +319,7 @@
 #define SRAK(r1,r3,b2,dl2,dh2)          RSY_RRRD(eb,r1,r3,b2,dl2,dh2,dc)
 #define SRK(r3,r1,r2)                   RRF_R0RR2(b9f9,r3,0,r1,r2)
 #define SRLK(r1,r3,b2,dl2,dh2)          RSY_RRRD(eb,r1,r3,b2,dl2,dh2,de)
+#define SRNMB(b2,d2)                    S_RD(b2b8,b2,d2)
 #define STAMY(r1,r3,b2,dl2,dh2)         RSY_AARD(eb,r1,r3,b2,dl2,dh2,9b)
 #define STCH(r1,x2,b2,dl2,dh2)          RXY_RRRD(e3,r1,x2,b2,dl2,dh2,c3)
 #define STCMY(r1,r3,b2,dl2,dh2)         RSY_RURD(eb,r1,r3,b2,dl2,dh2,2d)
diff --git a/none/tests/s390x/srnm.c b/none/tests/s390x/srnm.c
new file mode 100644
index 0000000..f383398
--- /dev/null
+++ b/none/tests/s390x/srnm.c
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "opcodes.h"
+
+#define srnm(b,d) \
+   ({ \
+      __asm__ volatile ( "lghi 8," #b "\n\t" \
+                         "srnm " #d "(8)\n\t" ::: "8"); \
+   })
+
+unsigned
+get_rounding_mode(void)
+{
+   unsigned fpc;
+
+   __asm__ volatile ("stfpc  %0\n\t" : "=m"(fpc));
+
+   return fpc & 0x7;
+}
+
+int main(void)
+{
+   printf("initial rounding mode = %u\n", get_rounding_mode());
+
+   /* Set basic rounding modes in various ways */
+   srnm(1,2);  // 1 + 2 = 3
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnm(2,0);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnm(0,1);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnm(0,0);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   /* Some rounding modes with bits to be ignored */
+   srnm(0xff,0);  // -> 3
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnm(0,0xfe);  // -> 2
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnm(0xf0,0x0f);  // -> 3
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   return 0;
+}
diff --git a/none/tests/s390x/srnm.stderr.exp b/none/tests/s390x/srnm.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/s390x/srnm.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/s390x/srnm.stdout.exp b/none/tests/s390x/srnm.stdout.exp
new file mode 100644
index 0000000..a5a0278
--- /dev/null
+++ b/none/tests/s390x/srnm.stdout.exp
@@ -0,0 +1,8 @@
+initial rounding mode = 0
+rounding mode = 3
+rounding mode = 2
+rounding mode = 1
+rounding mode = 0
+rounding mode = 3
+rounding mode = 2
+rounding mode = 3
diff --git a/none/tests/s390x/srnm.vgtest b/none/tests/s390x/srnm.vgtest
new file mode 100644
index 0000000..4144aeb
--- /dev/null
+++ b/none/tests/s390x/srnm.vgtest
@@ -0,0 +1 @@
+prog: srnm
diff --git a/none/tests/s390x/srnmb.c b/none/tests/s390x/srnmb.c
new file mode 100644
index 0000000..4ef9cbd
--- /dev/null
+++ b/none/tests/s390x/srnmb.c
@@ -0,0 +1,67 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "opcodes.h"
+
+#define srnmb(b,d) \
+   ({ \
+      __asm__ volatile ( "lghi 8," #b "\n\t" \
+                         SRNMB(8,d) \
+                         ::: "8"); \
+   })
+
+
+/* Like srnm above, except it uses r0 as a base register */
+#define srnmb0(d) \
+   ({ \
+      __asm__ volatile ( SRNMB(0,d) \
+                         ::: "0"); \
+   })
+
+unsigned
+get_rounding_mode(void)
+{
+   unsigned fpc;
+
+   __asm__ volatile ("stfpc  %0\n\t" : "=m"(fpc));
+
+   return fpc & 0x7;
+}
+
+int main(void)
+{
+   printf("initial rounding mode = %u\n", get_rounding_mode());
+
+   /* Set basic rounding modes in various ways */
+   srnmb(1,002);  // 1 + 2 = 3
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb(2,000);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb(0,001);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb(0,000);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+#if 0
+   // fpext
+   srnmb(7,000);  // -> 7
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb(0,000);  // -> 0
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb(0,007);  // -> 7
+   printf("rounding mode = %u\n", get_rounding_mode());
+#endif
+
+   srnmb(0,001);
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   srnmb0(004);    // -> emul warning invalid rounding mode
+   printf("rounding mode = %u\n", get_rounding_mode());
+
+   return 0;
+}
diff --git a/none/tests/s390x/srnmb.stderr.exp b/none/tests/s390x/srnmb.stderr.exp
new file mode 100644
index 0000000..12c94ab
--- /dev/null
+++ b/none/tests/s390x/srnmb.stderr.exp
@@ -0,0 +1,6 @@
+
+Emulation warning: unsupported action:
+  The specified rounding mode is invalid.
+  Continuing using 'round to nearest'. Results may differ!
+   at 0x........: main (srnmb.c:64)
+
diff --git a/none/tests/s390x/srnmb.stdout.exp b/none/tests/s390x/srnmb.stdout.exp
new file mode 100644
index 0000000..c2be0f7
--- /dev/null
+++ b/none/tests/s390x/srnmb.stdout.exp
@@ -0,0 +1,7 @@
+initial rounding mode = 0
+rounding mode = 3
+rounding mode = 2
+rounding mode = 1
+rounding mode = 0
+rounding mode = 1
+rounding mode = 0
diff --git a/none/tests/s390x/srnmb.vgtest b/none/tests/s390x/srnmb.vgtest
new file mode 100644
index 0000000..6eff81b
--- /dev/null
+++ b/none/tests/s390x/srnmb.vgtest
@@ -0,0 +1,2 @@
+prog: srnmb
+vgopts: --show-emwarns=yes