1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdint.h>
4 #include <inttypes.h>
5 #include "opcodes.h"
6
7 /* Test "convert from fixed" with universally available rounding modes.
8 Rounding mode is provided via FPC. */
9
10 volatile int32_t i32;
11 volatile int64_t i64;
12
13 const char *
rtext(unsigned fpc_round)14 rtext(unsigned fpc_round)
15 {
16 switch (fpc_round) {
17 case 0: return "[-> near]";
18 case 1: return "[-> zero]";
19 case 2: return "[-> +inf]";
20 case 3: return "[-> -inf]";
21 }
22 assert(0);
23 }
24
25 void
set_rounding_mode(unsigned mode)26 set_rounding_mode(unsigned mode)
27 {
28 printf("setting FPC rounding mode to %s\n", rtext(mode));
29 register unsigned r asm("1") = mode;
30 __asm__ volatile ( SFPC(1) : : "d"(r) );
31 }
32
cefbr(unsigned mode)33 void cefbr(unsigned mode)
34 {
35 set_rounding_mode(mode);
36
37 float out;
38
39 __asm__ volatile("cefbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i32));
40 printf("cefbr: %"PRId32" -> %f\n", i32, out);
41 }
42
cegbr(unsigned mode)43 void cegbr(unsigned mode)
44 {
45 set_rounding_mode(mode);
46
47 float out;
48
49 __asm__ volatile("cegbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i64));
50 printf("cegbr: %"PRId64" -> %f\n", i64, out);
51 }
52
cdgbr(unsigned mode)53 void cdgbr(unsigned mode)
54 {
55 set_rounding_mode(mode);
56
57 double out;
58
59 __asm__ volatile("cdgbr %[r1],%[r2]" : [r1] "=f"(out) : [r2] "d"(i64));
60 printf("cegbr: %"PRId64" -> %f\n", i64, out);
61 }
62
63
main()64 int main()
65 {
66 int mode;
67
68 /* i32 -> f32 */
69 i32 = INT32_MAX;
70 for (mode = 0; mode <= 3; ++mode) cefbr(mode);
71 printf("\n");
72 i32 = INT32_MIN;
73 for (mode = 0; mode <= 3; ++mode) cefbr(mode);
74 printf("\n");
75
76 /* i64 -> f32 */
77 i64 = INT64_MAX;
78 for (mode = 0; mode <= 3; ++mode) cegbr(mode);
79 printf("\n");
80 i64 = INT64_MIN;
81 for (mode = 0; mode <= 3; ++mode) cegbr(mode);
82 printf("\n");
83
84 /* i64 -> f64 */
85 i64 = INT64_MAX;
86 for (mode = 0; mode <= 3; ++mode) cdgbr(mode);
87 printf("\n");
88 i64 = INT64_MIN;
89 for (mode = 0; mode <= 3; ++mode) cdgbr(mode);
90 printf("\n");
91
92 return 0;
93 }
94