blob: 999aacdbe2c355e01fcc451c17028dbd824b486f [file] [log] [blame]
floriane7b55be2012-10-27 14:25:28 +00001#include <assert.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <stdint.h>
5#include <inttypes.h>
6#include "opcodes.h"
7#include "rounding.h"
8
9/* Test "convert to fixed" with rounding mode given in insn (m3 field)
10 Covers all generally available rounding modes that can be mapped to
11 IRRoundingMode. As a consequence m3=1 which is "round to nearest with
12 ties away from 0" is not tested here.
13*/
14
15const char *
16rtext(unsigned m3_round)
17{
18 switch (m3_round) {
19 case 0: return "[-> per fpc]";
20 case 1: return "[-> nearest away]";
21 case 3: return "[-> prepare short]"; // floating point extension fac needed
22 case 4: return "[-> nearest even]";
23 case 5: return "[-> 0]";
24 case 6: return "[-> +inf]";
25 case 7: return "[-> -inf]";
26 }
27 assert(0);
28}
29
30#define convert_to_int(opcode,src_type,dst_type,dst_fmt,round,value) \
31do { \
32 src_type src = value; \
33 dst_type dst; \
34 unsigned cc; \
35 \
36 __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \
37 "ipm %[cc]\n\t" \
38 "srl %[cc],28\n\t" \
39 : [dst] "=d"(dst), [cc] "=d"(cc) \
40 : [src] "f"(src) \
41 : "cc"); \
42 \
43 printf("%s %f\t-> %"dst_fmt"\tcc = %u %s\n", \
44 opcode, src, dst, cc, rtext(round)); \
45} while (0)
46
47
48#define cfebr(value, round) \
49 convert_to_int("cfebr",float,int32_t,PRId32,round,value)
50#define cfdbr(value, round) \
51 convert_to_int("cfdbr",double,int32_t,PRId32,round,value)
52#define cgebr(value, round) \
53 convert_to_int("cgebr",float,int64_t,PRId64,round,value)
54#define cgdbr(value, round) \
55 convert_to_int("cgdbr",double,int64_t,PRId64,round,value)
56
57void
58set_rounding_mode(unsigned mode)
59{
60 register unsigned r asm("1") = mode;
61 __asm__ volatile ( SFPC(1) : : "d"(r) );
62}
63
64
65int main(void)
66{
67 int j;
68 static const float fval[] = {
floriand34ec242014-08-14 17:32:26 +000069 1.25f, 1.5f, 2.5f, 1.75f, -1.25f, -1.5f, -2.5f, -1.75f, 0.0f,
floriane7b55be2012-10-27 14:25:28 +000070 };
71 static const double dval[] = {
floriand34ec242014-08-14 17:32:26 +000072 1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0,
floriane7b55be2012-10-27 14:25:28 +000073 };
74
75 /* Note when testing M3_NEAR need to set the FPC rounding mode
76 to something else. FPC rounding mode is NEAR by default.
77 Setting the FPC rounding mode to != NEAR is the only way to make
78 sure the M3 field is not ignored. */
79
80 /* f32 -> i32 */
81 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
82 set_rounding_mode(FPC_BFP_ROUND_ZERO);
83 cfebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN);
84 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
85 cfebr(fval[j], M3_BFP_ROUND_ZERO);
86 cfebr(fval[j], M3_BFP_ROUND_POSINF);
87 cfebr(fval[j], M3_BFP_ROUND_NEGINF);
88 }
89
90 /* f32 -> i64 */
91 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
92 set_rounding_mode(FPC_BFP_ROUND_ZERO);
93 cgebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN);
94 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
95 cgebr(fval[j], M3_BFP_ROUND_ZERO);
96 cgebr(fval[j], M3_BFP_ROUND_POSINF);
97 cgebr(fval[j], M3_BFP_ROUND_NEGINF);
98 }
99
100 /* f64 -> i32 */
101 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
102 set_rounding_mode(FPC_BFP_ROUND_ZERO);
103 cfdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
104 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
105 cfdbr(dval[j], M3_BFP_ROUND_ZERO);
106 cfdbr(dval[j], M3_BFP_ROUND_POSINF);
107 cfdbr(dval[j], M3_BFP_ROUND_NEGINF);
108 }
109
110 /* f64 -> i64 */
111 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
112 set_rounding_mode(FPC_BFP_ROUND_ZERO);
113 cgdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
114 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
115 cgdbr(dval[j], M3_BFP_ROUND_ZERO);
116 cgdbr(dval[j], M3_BFP_ROUND_POSINF);
117 cgdbr(dval[j], M3_BFP_ROUND_NEGINF);
118 }
119
120 return 0;
121}