From ef5f5e1119145209894b43bc2fe16253aa9fbebe Mon Sep 17 00:00:00 2001 From: Florian Krohm Date: Wed, 12 Sep 2012 19:40:14 +0000 Subject: [PATCH] s390x: Testcases for floating point 32/64-bit. Related to VEX r2525. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12966 --- none/tests/s390x/Makefile.am | 2 +- none/tests/s390x/bfp-1.c | 93 ++++++++++++++++ none/tests/s390x/bfp-1.stderr.exp | 2 + none/tests/s390x/bfp-1.stdout.exp | 10 ++ none/tests/s390x/bfp-1.vgtest | 1 + none/tests/s390x/opcodes.h | 2 + none/tests/s390x/rounding-2.c | 41 +++++++ none/tests/s390x/rounding-2.stderr.exp | 2 + none/tests/s390x/rounding-2.stdout.exp | 9 ++ none/tests/s390x/rounding-2.vgtest | 1 + none/tests/s390x/rounding-3.c | 116 +++++++++++++++++++ none/tests/s390x/rounding-3.stderr.exp | 2 + none/tests/s390x/rounding-3.stdout.exp | 148 +++++++++++++++++++++++++ none/tests/s390x/rounding-3.vgtest | 1 + none/tests/s390x/rounding-4.c | 75 +++++++++++++ none/tests/s390x/rounding-4.stderr.exp | 2 + none/tests/s390x/rounding-4.stdout.exp | 19 ++++ none/tests/s390x/rounding-4.vgtest | 1 + none/tests/s390x/rounding-5.c | 93 ++++++++++++++++ none/tests/s390x/rounding-5.stderr.exp | 2 + none/tests/s390x/rounding-5.stdout.exp | 54 +++++++++ none/tests/s390x/rounding-5.vgtest | 1 + 22 files changed, 676 insertions(+), 1 deletion(-) create mode 100644 none/tests/s390x/bfp-1.c create mode 100644 none/tests/s390x/bfp-1.stderr.exp create mode 100644 none/tests/s390x/bfp-1.stdout.exp create mode 100644 none/tests/s390x/bfp-1.vgtest create mode 100644 none/tests/s390x/rounding-2.c create mode 100644 none/tests/s390x/rounding-2.stderr.exp create mode 100644 none/tests/s390x/rounding-2.stdout.exp create mode 100644 none/tests/s390x/rounding-2.vgtest create mode 100644 none/tests/s390x/rounding-3.c create mode 100644 none/tests/s390x/rounding-3.stderr.exp create mode 100644 none/tests/s390x/rounding-3.stdout.exp create mode 100644 none/tests/s390x/rounding-3.vgtest create mode 100644 none/tests/s390x/rounding-4.c create mode 100644 none/tests/s390x/rounding-4.stderr.exp create mode 100644 none/tests/s390x/rounding-4.stdout.exp create mode 100644 none/tests/s390x/rounding-4.vgtest create mode 100644 none/tests/s390x/rounding-5.c create mode 100644 none/tests/s390x/rounding-5.stderr.exp create mode 100644 none/tests/s390x/rounding-5.stdout.exp create mode 100644 none/tests/s390x/rounding-5.vgtest diff --git a/none/tests/s390x/Makefile.am b/none/tests/s390x/Makefile.am index da22c4b78..f03c58cf3 100644 --- a/none/tests/s390x/Makefile.am +++ b/none/tests/s390x/Makefile.am @@ -9,7 +9,7 @@ INSN_TESTS = clc clcle cvb cvd icm lpr tcxb lam_stam xc mvst add sub mul \ trto trot trtt tr tre cij cgij clij clgij crj cgrj clrj clgrj \ 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-1 rounding-2 rounding-3 rounding-4 rounding-5 bfp-1 check_PROGRAMS = $(INSN_TESTS) \ allexec \ diff --git a/none/tests/s390x/bfp-1.c b/none/tests/s390x/bfp-1.c new file mode 100644 index 000000000..2cf558e24 --- /dev/null +++ b/none/tests/s390x/bfp-1.c @@ -0,0 +1,93 @@ +#include + +/* Simple test to see that basic operators are mapped + correctly. Uses default rounding mode. */ + +volatile double d1, d2; +volatile float f1, f2; + +void fadd8(void) +{ + printf("%f + %f = %f\n", d1, d2, d1 + d2); +} + +void fsub8(void) +{ + printf("%f - %f = %f\n", d1, d2, d1 - d2); +} + +void fmul8(void) +{ + printf("%f * %f = %f\n", d1, d2, d1 * d2); +} + +void fdiv8(void) +{ + printf("%f / %f = %f\n", d1, d2, d1 / d2); +} + +void fadd4(void) +{ + register float r1 asm("f1") = f1; + register float r2 asm("f2") = f2; + + __asm__ volatile ("aebr %[r1],%[r2]\n\t" + : [r1] "+f"(r1) + : [r2] "f"(r2) : "cc"); + printf("%f + %f = %f\n", f1, f2, r1); +} + +void fsub4(void) +{ + register float r1 asm("f1") = f1; + register float r2 asm("f2") = f2; + + __asm__ volatile ("sebr %[r1],%[r2]\n\t" + : [r1] "+f"(r1) + : [r2] "f"(r2) : "cc"); + printf("%f - %f = %f\n", f1, f2, r1); +} + +void fmul4(void) +{ + register float r1 asm("f1") = f1; + register float r2 asm("f2") = f2; + + __asm__ volatile ("meebr %[r1],%[r2]\n\t" + : [r1] "+f"(r1) + : [r2] "f"(r2) : "cc"); + printf("%f * %f = %f\n", f1, f2, r1); +} + +void fdiv4(void) +{ + register float r1 asm("f1") = f1; + register float r2 asm("f2") = f2; + + __asm__ volatile ("debr %[r1],%[r2]\n\t" + : [r1] "+f"(r1) + : [r2] "f"(r2) : "cc"); + printf("%f / %f = %f\n", f1, f2, r1); +} + + +int main() +{ + printf("double arithmetic\n"); + d1 = 10.5; + d2 = 1.25; + fadd8(); + fsub8(); + fmul8(); + fdiv8(); + + printf("float arithmetic\n"); + f1 = 10.5f; + f2 = 1.25f; + fadd4(); + fsub4(); + fmul4(); + fdiv4(); + + return 0; +} diff --git a/none/tests/s390x/bfp-1.stderr.exp b/none/tests/s390x/bfp-1.stderr.exp new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/none/tests/s390x/bfp-1.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/bfp-1.stdout.exp b/none/tests/s390x/bfp-1.stdout.exp new file mode 100644 index 000000000..023c59864 --- /dev/null +++ b/none/tests/s390x/bfp-1.stdout.exp @@ -0,0 +1,10 @@ +double arithmetic +10.500000 + 1.250000 = 11.750000 +10.500000 - 1.250000 = 9.250000 +10.500000 * 1.250000 = 13.125000 +10.500000 / 1.250000 = 8.400000 +float arithmetic +10.500000 + 1.250000 = 11.750000 +10.500000 - 1.250000 = 9.250000 +10.500000 * 1.250000 = 13.125000 +10.500000 / 1.250000 = 8.400000 diff --git a/none/tests/s390x/bfp-1.vgtest b/none/tests/s390x/bfp-1.vgtest new file mode 100644 index 000000000..9d67c4abb --- /dev/null +++ b/none/tests/s390x/bfp-1.vgtest @@ -0,0 +1 @@ +prog: bfp-1 diff --git a/none/tests/s390x/opcodes.h b/none/tests/s390x/opcodes.h index 8dd6097d3..1d0daaf7a 100644 --- a/none/tests/s390x/opcodes.h +++ b/none/tests/s390x/opcodes.h @@ -52,6 +52,7 @@ ".long 0x" #i4 #m3 #u0 #op2 "\n\t" #define RRE_RR(op,u0,r1,r2) ".long 0x" #op #u0 #r1 #r2 "\n\t" #define RRE_RERE(op,r1,r2) ".long 0x" #op "00" #r1 #r2 "\n\t" +#define RRE_R0(op,r1) ".long 0x" #op "00" #r1 "0" "\n\t" #define SIL_RDU(op,b1,d1,i2) \ ".short 0x" #op "\n\t" \ ".long 0x" #b1 #d1 #i2 "\n\t" @@ -299,6 +300,7 @@ #define RNSBG(r1,r2,i3,i4,i5) RIE_RRUUU(ec,r1,r2,i3,i4,i5,54) #define ROSBG(r1,r2,i3,i4,i5) RIE_RRUUU(ec,r1,r2,i3,i4,i5,56) #define RXSBG(r1,r2,i3,i4,i5) RIE_RRUUU(ec,r1,r2,i3,i4,i5,57) +#define SFPC(r1) RRE_R0(b384,r1) #define SGRK(r3,r1,r2) RRF_R0RR2(b9e9,r3,0,r1,r2) #define SHHHR(r3,r1,r2) RRF_R0RR2(b9c9,r3,0,r1,r2) #define SHHLR(r3,r1,r2) RRF_R0RR2(b9d9,r3,0,r1,r2) diff --git a/none/tests/s390x/rounding-2.c b/none/tests/s390x/rounding-2.c new file mode 100644 index 000000000..ecc5a199e --- /dev/null +++ b/none/tests/s390x/rounding-2.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include "opcodes.h" + +/* Basic test that we can set the rounding mode in the FPC and + query it. Covers only generally available rounding modes. */ + +void +set_rounding_mode(unsigned mode) +{ + register unsigned r asm("1") = mode; + __asm__ volatile ( SFPC(1) : : "d"(r) ); +} + +unsigned +get_rounding_mode(void) +{ + unsigned fpc; + + __asm__ volatile ("stfpc %0\n\t" : "=m"(fpc)); + + return fpc & 0x7; +} + + +int main(void) +{ + int i; + const unsigned rmodes[] = { 0, 1, 2, 3 }; + + printf("initial rounding mode: %u\n", get_rounding_mode()); + + for (i = 0; i < sizeof rmodes / sizeof rmodes[0]; ++i) { + printf("setting rounding mode to %u\n", rmodes[i]); + set_rounding_mode(rmodes[i]); + printf("...checking: %u\n", get_rounding_mode()); + } + + return 0; +} diff --git a/none/tests/s390x/rounding-2.stderr.exp b/none/tests/s390x/rounding-2.stderr.exp new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/none/tests/s390x/rounding-2.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/rounding-2.stdout.exp b/none/tests/s390x/rounding-2.stdout.exp new file mode 100644 index 000000000..e0da36957 --- /dev/null +++ b/none/tests/s390x/rounding-2.stdout.exp @@ -0,0 +1,9 @@ +initial rounding mode: 0 +setting rounding mode to 0 +...checking: 0 +setting rounding mode to 1 +...checking: 1 +setting rounding mode to 2 +...checking: 2 +setting rounding mode to 3 +...checking: 3 diff --git a/none/tests/s390x/rounding-2.vgtest b/none/tests/s390x/rounding-2.vgtest new file mode 100644 index 000000000..c6e067d8b --- /dev/null +++ b/none/tests/s390x/rounding-2.vgtest @@ -0,0 +1 @@ +prog: rounding-2 diff --git a/none/tests/s390x/rounding-3.c b/none/tests/s390x/rounding-3.c new file mode 100644 index 000000000..4c12f9cd3 --- /dev/null +++ b/none/tests/s390x/rounding-3.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include "opcodes.h" + +/* Test "convert to fixed" with "per fpc" rounding. + Covers all generally available rounding modes. + + Note, that "convert to fixed" with rounding mode specified as + part of the insn is already tested in fpconv.c +*/ + +void +set_rounding_mode(unsigned mode) +{ + register unsigned r asm("1") = mode; + __asm__ volatile ( SFPC(1) : : "d"(r) ); +} + +unsigned +get_rounding_mode(void) +{ + unsigned fpc; + + __asm__ volatile ("stfpc %0\n\t" : "=m"(fpc)); + + return fpc & 0x7; +} + + +const char * +rtext(unsigned fpc_round) +{ + switch (fpc_round) { + case 0: return "[-> near]"; + case 1: return "[-> zero]"; + case 2: return "[-> +inf]"; + case 3: return "[-> -inf]"; + } + assert(0); +} + +#define convert_to_int(opcode,src_type,dst_type,dst_fmt,round,value) \ +do { \ + src_type src = value; \ + dst_type dst; \ + unsigned cc; \ + \ + __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \ + "ipm %[cc]\n\t" \ + "srl %[cc],28\n\t" \ + : [dst] "=d"(dst), [cc] "=d"(cc) \ + : [src] "f"(src) \ + : "cc"); \ + \ + printf("%s %f\t-> %"dst_fmt"\tcc = %u\n", \ + opcode, src, dst, cc); \ +} while (0) + + +#define cfebr(value) \ + convert_to_int("cfebr",float,int32_t,PRId32,0,value) +#define cfdbr(value) \ + convert_to_int("cfdbr",double,int32_t,PRId32,0,value) +#define cgebr(value) \ + convert_to_int("cgebr",float,int64_t,PRId64,0,value) +#define cgdbr(value) \ + convert_to_int("cgdbr",double,int64_t,PRId64,0,value) + +int main(void) +{ + int i, j; + static const unsigned rmodes[] = { 0, 1, 2, 3 }; + static const float fval[] = { + 1.4f, 1.5f, 2.5f, 1.6f, -1.4f, -1.5f, -2.5f, -1.6f, 0.0f, + }; + static const double dval[] = { + 1.4, 1.5, 2.5, 1.6, -1.4, -1.5, -2.5, -1.6, 0.0, + }; + + + for (i = 0; i < sizeof rmodes / sizeof rmodes[0]; ++i) { + printf("setting rounding mode to %s\n", rtext(rmodes[i])); + set_rounding_mode(rmodes[i]); + assert(get_rounding_mode() == rmodes[i]); + + /* f32 -> i32 */ + for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { + cfebr(fval[j]); + assert(get_rounding_mode() == rmodes[i]); + } + + /* f32 -> i64 */ + for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { + cgebr(fval[j]); + assert(get_rounding_mode() == rmodes[i]); + } + + /* f64 -> i32 */ + for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { + cfdbr(dval[j]); + assert(get_rounding_mode() == rmodes[i]); + } + + /* f64 -> i64 */ + for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { + cgdbr(dval[j]); + assert(get_rounding_mode() == rmodes[i]); + } + + } + + return 0; +} diff --git a/none/tests/s390x/rounding-3.stderr.exp b/none/tests/s390x/rounding-3.stderr.exp new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/none/tests/s390x/rounding-3.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/rounding-3.stdout.exp b/none/tests/s390x/rounding-3.stdout.exp new file mode 100644 index 000000000..5b08525c0 --- /dev/null +++ b/none/tests/s390x/rounding-3.stdout.exp @@ -0,0 +1,148 @@ +setting rounding mode to [-> near] +cfebr 1.400000 -> 1 cc = 2 +cfebr 1.500000 -> 2 cc = 2 +cfebr 2.500000 -> 2 cc = 2 +cfebr 1.600000 -> 2 cc = 2 +cfebr -1.400000 -> -1 cc = 1 +cfebr -1.500000 -> -2 cc = 1 +cfebr -2.500000 -> -2 cc = 1 +cfebr -1.600000 -> -2 cc = 1 +cfebr 0.000000 -> 0 cc = 0 +cgebr 1.400000 -> 1 cc = 2 +cgebr 1.500000 -> 2 cc = 2 +cgebr 2.500000 -> 2 cc = 2 +cgebr 1.600000 -> 2 cc = 2 +cgebr -1.400000 -> -1 cc = 1 +cgebr -1.500000 -> -2 cc = 1 +cgebr -2.500000 -> -2 cc = 1 +cgebr -1.600000 -> -2 cc = 1 +cgebr 0.000000 -> 0 cc = 0 +cfdbr 1.400000 -> 1 cc = 2 +cfdbr 1.500000 -> 2 cc = 2 +cfdbr 2.500000 -> 2 cc = 2 +cfdbr 1.600000 -> 2 cc = 2 +cfdbr -1.400000 -> -1 cc = 1 +cfdbr -1.500000 -> -2 cc = 1 +cfdbr -2.500000 -> -2 cc = 1 +cfdbr -1.600000 -> -2 cc = 1 +cfdbr 0.000000 -> 0 cc = 0 +cgdbr 1.400000 -> 1 cc = 2 +cgdbr 1.500000 -> 2 cc = 2 +cgdbr 2.500000 -> 2 cc = 2 +cgdbr 1.600000 -> 2 cc = 2 +cgdbr -1.400000 -> -1 cc = 1 +cgdbr -1.500000 -> -2 cc = 1 +cgdbr -2.500000 -> -2 cc = 1 +cgdbr -1.600000 -> -2 cc = 1 +cgdbr 0.000000 -> 0 cc = 0 +setting rounding mode to [-> zero] +cfebr 1.400000 -> 1 cc = 2 +cfebr 1.500000 -> 1 cc = 2 +cfebr 2.500000 -> 2 cc = 2 +cfebr 1.600000 -> 1 cc = 2 +cfebr -1.400000 -> -1 cc = 1 +cfebr -1.500000 -> -1 cc = 1 +cfebr -2.500000 -> -2 cc = 1 +cfebr -1.600000 -> -1 cc = 1 +cfebr 0.000000 -> 0 cc = 0 +cgebr 1.400000 -> 1 cc = 2 +cgebr 1.500000 -> 1 cc = 2 +cgebr 2.500000 -> 2 cc = 2 +cgebr 1.600000 -> 1 cc = 2 +cgebr -1.400000 -> -1 cc = 1 +cgebr -1.500000 -> -1 cc = 1 +cgebr -2.500000 -> -2 cc = 1 +cgebr -1.600000 -> -1 cc = 1 +cgebr 0.000000 -> 0 cc = 0 +cfdbr 1.400000 -> 1 cc = 2 +cfdbr 1.500000 -> 1 cc = 2 +cfdbr 2.500000 -> 2 cc = 2 +cfdbr 1.600000 -> 1 cc = 2 +cfdbr -1.400000 -> -1 cc = 1 +cfdbr -1.500000 -> -1 cc = 1 +cfdbr -2.500000 -> -2 cc = 1 +cfdbr -1.600000 -> -1 cc = 1 +cfdbr 0.000000 -> 0 cc = 0 +cgdbr 1.400000 -> 1 cc = 2 +cgdbr 1.500000 -> 1 cc = 2 +cgdbr 2.500000 -> 2 cc = 2 +cgdbr 1.600000 -> 1 cc = 2 +cgdbr -1.400000 -> -1 cc = 1 +cgdbr -1.500000 -> -1 cc = 1 +cgdbr -2.500000 -> -2 cc = 1 +cgdbr -1.600000 -> -1 cc = 1 +cgdbr 0.000000 -> 0 cc = 0 +setting rounding mode to [-> +inf] +cfebr 1.400000 -> 2 cc = 2 +cfebr 1.500000 -> 2 cc = 2 +cfebr 2.500000 -> 3 cc = 2 +cfebr 1.600000 -> 2 cc = 2 +cfebr -1.400000 -> -1 cc = 1 +cfebr -1.500000 -> -1 cc = 1 +cfebr -2.500000 -> -2 cc = 1 +cfebr -1.600000 -> -1 cc = 1 +cfebr 0.000000 -> 0 cc = 0 +cgebr 1.400000 -> 2 cc = 2 +cgebr 1.500000 -> 2 cc = 2 +cgebr 2.500000 -> 3 cc = 2 +cgebr 1.600000 -> 2 cc = 2 +cgebr -1.400000 -> -1 cc = 1 +cgebr -1.500000 -> -1 cc = 1 +cgebr -2.500000 -> -2 cc = 1 +cgebr -1.600000 -> -1 cc = 1 +cgebr 0.000000 -> 0 cc = 0 +cfdbr 1.400000 -> 2 cc = 2 +cfdbr 1.500000 -> 2 cc = 2 +cfdbr 2.500000 -> 3 cc = 2 +cfdbr 1.600000 -> 2 cc = 2 +cfdbr -1.400000 -> -1 cc = 1 +cfdbr -1.500000 -> -1 cc = 1 +cfdbr -2.500000 -> -2 cc = 1 +cfdbr -1.600000 -> -1 cc = 1 +cfdbr 0.000000 -> 0 cc = 0 +cgdbr 1.400000 -> 2 cc = 2 +cgdbr 1.500000 -> 2 cc = 2 +cgdbr 2.500000 -> 3 cc = 2 +cgdbr 1.600000 -> 2 cc = 2 +cgdbr -1.400000 -> -1 cc = 1 +cgdbr -1.500000 -> -1 cc = 1 +cgdbr -2.500000 -> -2 cc = 1 +cgdbr -1.600000 -> -1 cc = 1 +cgdbr 0.000000 -> 0 cc = 0 +setting rounding mode to [-> -inf] +cfebr 1.400000 -> 1 cc = 2 +cfebr 1.500000 -> 1 cc = 2 +cfebr 2.500000 -> 2 cc = 2 +cfebr 1.600000 -> 1 cc = 2 +cfebr -1.400000 -> -2 cc = 1 +cfebr -1.500000 -> -2 cc = 1 +cfebr -2.500000 -> -3 cc = 1 +cfebr -1.600000 -> -2 cc = 1 +cfebr 0.000000 -> 0 cc = 0 +cgebr 1.400000 -> 1 cc = 2 +cgebr 1.500000 -> 1 cc = 2 +cgebr 2.500000 -> 2 cc = 2 +cgebr 1.600000 -> 1 cc = 2 +cgebr -1.400000 -> -2 cc = 1 +cgebr -1.500000 -> -2 cc = 1 +cgebr -2.500000 -> -3 cc = 1 +cgebr -1.600000 -> -2 cc = 1 +cgebr 0.000000 -> 0 cc = 0 +cfdbr 1.400000 -> 1 cc = 2 +cfdbr 1.500000 -> 1 cc = 2 +cfdbr 2.500000 -> 2 cc = 2 +cfdbr 1.600000 -> 1 cc = 2 +cfdbr -1.400000 -> -2 cc = 1 +cfdbr -1.500000 -> -2 cc = 1 +cfdbr -2.500000 -> -3 cc = 1 +cfdbr -1.600000 -> -2 cc = 1 +cfdbr 0.000000 -> 0 cc = 0 +cgdbr 1.400000 -> 1 cc = 2 +cgdbr 1.500000 -> 1 cc = 2 +cgdbr 2.500000 -> 2 cc = 2 +cgdbr 1.600000 -> 1 cc = 2 +cgdbr -1.400000 -> -2 cc = 1 +cgdbr -1.500000 -> -2 cc = 1 +cgdbr -2.500000 -> -3 cc = 1 +cgdbr -1.600000 -> -2 cc = 1 +cgdbr 0.000000 -> 0 cc = 0 diff --git a/none/tests/s390x/rounding-3.vgtest b/none/tests/s390x/rounding-3.vgtest new file mode 100644 index 000000000..816871054 --- /dev/null +++ b/none/tests/s390x/rounding-3.vgtest @@ -0,0 +1 @@ +prog: rounding-3 diff --git a/none/tests/s390x/rounding-4.c b/none/tests/s390x/rounding-4.c new file mode 100644 index 000000000..e0a3cb39a --- /dev/null +++ b/none/tests/s390x/rounding-4.c @@ -0,0 +1,75 @@ +#include +#include +#include "opcodes.h" + +/* Test "load rounded" with universally available rounding modes. + Rounding mode is provided via FPC. + Also test "load lengthened" (which is independent of rounding modes). */ + +volatile double d; +volatile float f; + +const char * +rtext(unsigned fpc_round) +{ + switch (fpc_round) { + case 0: return "[-> near]"; + case 1: return "[-> zero]"; + case 2: return "[-> +inf]"; + case 3: return "[-> -inf]"; + } + assert(0); +} + +void +set_rounding_mode(unsigned mode) +{ + printf("setting FPC rounding mode to %s\n", rtext(mode)); + register unsigned r asm("1") = mode; + __asm__ volatile ( SFPC(1) : : "d"(r) ); +} + + +void +load_rounded(void) +{ + f = d; + printf("load rounded d = %22.20g f = %22.20g\n", d, f); +} + +void +load_lengthened(void) +{ + d = f; + printf("load lengthened d = %22.20g f = %22.20g\n", d, f); +} + +/* Tests for load rounded and load lengthened */ +int main() +{ + d = 12345678.98765432E21; + set_rounding_mode(0); + load_rounded(); + set_rounding_mode(1); + load_rounded(); + set_rounding_mode(2); + load_rounded(); + set_rounding_mode(3); + load_rounded(); + printf("\n"); + + d = -12345678.98765432E21; + set_rounding_mode(0); + load_rounded(); + set_rounding_mode(1); + load_rounded(); + set_rounding_mode(2); + load_rounded(); + set_rounding_mode(3); + load_rounded(); + printf("\n"); + + load_lengthened(); + + return 0; +} diff --git a/none/tests/s390x/rounding-4.stderr.exp b/none/tests/s390x/rounding-4.stderr.exp new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/none/tests/s390x/rounding-4.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/rounding-4.stdout.exp b/none/tests/s390x/rounding-4.stdout.exp new file mode 100644 index 000000000..a1e5d6e6e --- /dev/null +++ b/none/tests/s390x/rounding-4.stdout.exp @@ -0,0 +1,19 @@ +setting FPC rounding mode to [-> near] +load rounded d = 1.2345678987654319598e+28 f = 1.234567915439125133e+28 +setting FPC rounding mode to [-> zero] +load rounded d = 1.2345678987654319598e+28 f = 1.2345677973799630613e+28 +setting FPC rounding mode to [-> +inf] +load rounded d = 1.2345678987654319598e+28 f = 1.234567915439125133e+28 +setting FPC rounding mode to [-> -inf] +load rounded d = 1.2345678987654319598e+28 f = 1.2345677973799630613e+28 + +setting FPC rounding mode to [-> near] +load rounded d = -1.2345678987654319598e+28 f = -1.234567915439125133e+28 +setting FPC rounding mode to [-> zero] +load rounded d = -1.2345678987654319598e+28 f = -1.2345677973799630613e+28 +setting FPC rounding mode to [-> +inf] +load rounded d = -1.2345678987654319598e+28 f = -1.2345677973799630613e+28 +setting FPC rounding mode to [-> -inf] +load rounded d = -1.2345678987654319598e+28 f = -1.234567915439125133e+28 + +load lengthened d = -1.234567915439125133e+28 f = -1.234567915439125133e+28 diff --git a/none/tests/s390x/rounding-4.vgtest b/none/tests/s390x/rounding-4.vgtest new file mode 100644 index 000000000..e264b57a7 --- /dev/null +++ b/none/tests/s390x/rounding-4.vgtest @@ -0,0 +1 @@ +prog: rounding-4 diff --git a/none/tests/s390x/rounding-5.c b/none/tests/s390x/rounding-5.c new file mode 100644 index 000000000..e1eab408e --- /dev/null +++ b/none/tests/s390x/rounding-5.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include "opcodes.h" + +/* Test "convert from fixed" with universally available rounding modes. + Rounding mode is provided via FPC. */ + +volatile int32_t i32; +volatile int64_t i64; + +const char * +rtext(unsigned fpc_round) +{ + switch (fpc_round) { + case 0: return "[-> near]"; + case 1: return "[-> zero]"; + case 2: return "[-> +inf]"; + case 3: return "[-> -inf]"; + } + assert(0); +} + +void +set_rounding_mode(unsigned mode) +{ + printf("setting FPC rounding mode to %s\n", rtext(mode)); + register unsigned r asm("1") = mode; + __asm__ volatile ( SFPC(1) : : "d"(r) ); +} + +void cefbr(unsigned mode) +{ + set_rounding_mode(mode); + + float out; + + __asm__ volatile("cefbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i32)); + printf("cefbr: %"PRId32" -> %f\n", i32, out); +} + +void cegbr(unsigned mode) +{ + set_rounding_mode(mode); + + float out; + + __asm__ volatile("cegbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i64)); + printf("cegbr: %"PRId64" -> %f\n", i64, out); +} + +void cdgbr(unsigned mode) +{ + set_rounding_mode(mode); + + double out; + + __asm__ volatile("cdgbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i64)); + printf("cegbr: %"PRId64" -> %f\n", i64, out); +} + + +int main() +{ + int mode; + + /* i32 -> f32 */ + i32 = INT32_MAX; + for (mode = 0; mode <= 3; ++mode) cefbr(mode); + printf("\n"); + i32 = INT32_MIN; + for (mode = 0; mode <= 3; ++mode) cefbr(mode); + printf("\n"); + + /* i64 -> f32 */ + i64 = INT64_MAX; + for (mode = 0; mode <= 3; ++mode) cegbr(mode); + printf("\n"); + i64 = INT64_MIN; + for (mode = 0; mode <= 3; ++mode) cegbr(mode); + printf("\n"); + + /* i64 -> f64 */ + i64 = INT64_MAX; + for (mode = 0; mode <= 3; ++mode) cdgbr(mode); + printf("\n"); + i64 = INT64_MIN; + for (mode = 0; mode <= 3; ++mode) cdgbr(mode); + printf("\n"); + + return 0; +} diff --git a/none/tests/s390x/rounding-5.stderr.exp b/none/tests/s390x/rounding-5.stderr.exp new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/none/tests/s390x/rounding-5.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/rounding-5.stdout.exp b/none/tests/s390x/rounding-5.stdout.exp new file mode 100644 index 000000000..80e55f67d --- /dev/null +++ b/none/tests/s390x/rounding-5.stdout.exp @@ -0,0 +1,54 @@ +setting FPC rounding mode to [-> near] +cefbr: 2147483647 -> 2147483648.000000 +setting FPC rounding mode to [-> zero] +cefbr: 2147483647 -> 2147483520.000000 +setting FPC rounding mode to [-> +inf] +cefbr: 2147483647 -> 2147483648.000000 +setting FPC rounding mode to [-> -inf] +cefbr: 2147483647 -> 2147483520.000000 + +setting FPC rounding mode to [-> near] +cefbr: -2147483648 -> -2147483648.000000 +setting FPC rounding mode to [-> zero] +cefbr: -2147483648 -> -2147483648.000000 +setting FPC rounding mode to [-> +inf] +cefbr: -2147483648 -> -2147483648.000000 +setting FPC rounding mode to [-> -inf] +cefbr: -2147483648 -> -2147483648.000000 + +setting FPC rounding mode to [-> near] +cegbr: 9223372036854775807 -> 9223372036854775808.000000 +setting FPC rounding mode to [-> zero] +cegbr: 9223372036854775807 -> 9223371487098961920.000000 +setting FPC rounding mode to [-> +inf] +cegbr: 9223372036854775807 -> 9223372036854775808.000000 +setting FPC rounding mode to [-> -inf] +cegbr: 9223372036854775807 -> 9223371487098961920.000000 + +setting FPC rounding mode to [-> near] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> zero] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> +inf] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> -inf] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 + +setting FPC rounding mode to [-> near] +cegbr: 9223372036854775807 -> 9223372036854775808.000000 +setting FPC rounding mode to [-> zero] +cegbr: 9223372036854775807 -> 9223372036854774784.000000 +setting FPC rounding mode to [-> +inf] +cegbr: 9223372036854775807 -> 9223372036854775808.000000 +setting FPC rounding mode to [-> -inf] +cegbr: 9223372036854775807 -> 9223372036854774784.000000 + +setting FPC rounding mode to [-> near] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> zero] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> +inf] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 +setting FPC rounding mode to [-> -inf] +cegbr: -9223372036854775808 -> -9223372036854775808.000000 + diff --git a/none/tests/s390x/rounding-5.vgtest b/none/tests/s390x/rounding-5.vgtest new file mode 100644 index 000000000..51f302173 --- /dev/null +++ b/none/tests/s390x/rounding-5.vgtest @@ -0,0 +1 @@ +prog: rounding-5