blob: ae0aa1b999f71119319ebe0951e8c0d796afa18a [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
cborntrab9e129b2015-07-09 19:21:42 +000047#define round_to_int(opcode,type,round,value) \
48do { \
49 type src = value; \
50 type dst; \
51 \
52 __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \
53 : [dst] "=f"(dst) \
54 : [src] "f"(src) \
55 : ); \
56 \
57 printf("%s %.5f\t-> %g %s\n", \
58 opcode, src, dst, rtext(round)); \
59} while (0)
60
floriane7b55be2012-10-27 14:25:28 +000061
62#define cfebr(value, round) \
63 convert_to_int("cfebr",float,int32_t,PRId32,round,value)
64#define cfdbr(value, round) \
65 convert_to_int("cfdbr",double,int32_t,PRId32,round,value)
66#define cgebr(value, round) \
67 convert_to_int("cgebr",float,int64_t,PRId64,round,value)
68#define cgdbr(value, round) \
69 convert_to_int("cgdbr",double,int64_t,PRId64,round,value)
70
cborntrab9e129b2015-07-09 19:21:42 +000071#define fiebr(value, round) \
72 round_to_int("fiebr",float,round,value)
73#define fidbr(value, round) \
74 round_to_int("fidbr",double,round,value)
75
floriane7b55be2012-10-27 14:25:28 +000076void
77set_rounding_mode(unsigned mode)
78{
79 register unsigned r asm("1") = mode;
80 __asm__ volatile ( SFPC(1) : : "d"(r) );
81}
82
83
84int main(void)
85{
86 int j;
87 static const float fval[] = {
floriand34ec242014-08-14 17:32:26 +000088 1.25f, 1.5f, 2.5f, 1.75f, -1.25f, -1.5f, -2.5f, -1.75f, 0.0f,
floriane7b55be2012-10-27 14:25:28 +000089 };
90 static const double dval[] = {
floriand34ec242014-08-14 17:32:26 +000091 1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0,
floriane7b55be2012-10-27 14:25:28 +000092 };
93
94 /* Note when testing M3_NEAR need to set the FPC rounding mode
95 to something else. FPC rounding mode is NEAR by default.
96 Setting the FPC rounding mode to != NEAR is the only way to make
97 sure the M3 field is not ignored. */
98
99 /* f32 -> i32 */
100 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
101 set_rounding_mode(FPC_BFP_ROUND_ZERO);
102 cfebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN);
103 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
104 cfebr(fval[j], M3_BFP_ROUND_ZERO);
105 cfebr(fval[j], M3_BFP_ROUND_POSINF);
106 cfebr(fval[j], M3_BFP_ROUND_NEGINF);
107 }
108
109 /* f32 -> i64 */
110 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
111 set_rounding_mode(FPC_BFP_ROUND_ZERO);
112 cgebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN);
113 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
114 cgebr(fval[j], M3_BFP_ROUND_ZERO);
115 cgebr(fval[j], M3_BFP_ROUND_POSINF);
116 cgebr(fval[j], M3_BFP_ROUND_NEGINF);
117 }
118
119 /* f64 -> i32 */
120 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
121 set_rounding_mode(FPC_BFP_ROUND_ZERO);
122 cfdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
123 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
124 cfdbr(dval[j], M3_BFP_ROUND_ZERO);
125 cfdbr(dval[j], M3_BFP_ROUND_POSINF);
126 cfdbr(dval[j], M3_BFP_ROUND_NEGINF);
127 }
128
129 /* f64 -> i64 */
130 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
131 set_rounding_mode(FPC_BFP_ROUND_ZERO);
132 cgdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
133 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
134 cgdbr(dval[j], M3_BFP_ROUND_ZERO);
135 cgdbr(dval[j], M3_BFP_ROUND_POSINF);
136 cgdbr(dval[j], M3_BFP_ROUND_NEGINF);
137 }
138
cborntrab9e129b2015-07-09 19:21:42 +0000139 /* f32 -> f32, round to int */
140 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
141 set_rounding_mode(FPC_BFP_ROUND_ZERO);
142 fiebr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
143 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
144 fiebr(dval[j], M3_BFP_ROUND_ZERO);
145 fiebr(dval[j], M3_BFP_ROUND_POSINF);
146 fiebr(dval[j], M3_BFP_ROUND_NEGINF);
147 }
148
149 /* f64 -> f64, round to int */
150 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
151 set_rounding_mode(FPC_BFP_ROUND_ZERO);
152 fidbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN);
153 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN);
154 fidbr(dval[j], M3_BFP_ROUND_ZERO);
155 fidbr(dval[j], M3_BFP_ROUND_POSINF);
156 fidbr(dval[j], M3_BFP_ROUND_NEGINF);
157 }
158
floriane7b55be2012-10-27 14:25:28 +0000159 return 0;
160}