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 * 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 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 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 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 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 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