Home | History | Annotate | Download | only in s390x
      1 #include <float.h>
      2 #include <stdio.h>
      3 #include <stdint.h>
      4 #include <inttypes.h>
      5 #include <limits.h>
      6 
      7 /* The following opcodes are tested:
      8 
      9    Convert to fixed:    cfebr, cgebr, cfdbr, cgdbr
     10    Convert from fixed:  cefbr, cdfbr, cegbr, cdgbr
     11 
     12    We do not test rounding here. Just making sure the insn selector
     13    picks the correct insn.
     14 */
     15 
     16 #define I2F(insn, initial, target_type)                         \
     17 do {                                                            \
     18    int64_t source = initial;                                    \
     19    target_type target;                                          \
     20    asm volatile(insn " %0,%1\n\t" :"=f" (target) :"d"(source)); \
     21    printf(insn " %"PRId64" -> %f\n", source, target);           \
     22 } while (0)
     23 
     24 #define DO_INSN_I32_TO_F(insn, target_type)        \
     25 do {                                               \
     26    printf("\n----- int32_t -> " #target_type "\n");\
     27    I2F(insn,   0, target_type);                    \
     28    I2F(insn,   1, target_type);                    \
     29    I2F(insn,  -1, target_type);                    \
     30    I2F(insn,  42, target_type);                    \
     31    I2F(insn, SHRT_MAX, target_type);               \
     32    I2F(insn, SHRT_MIN, target_type);               \
     33    I2F(insn, INT_MAX, target_type);                \
     34    I2F(insn, INT_MIN, target_type);                \
     35 } while (0)
     36 
     37 #define DO_INSN_I64_TO_F(insn, target_type)        \
     38 do {                                               \
     39    printf("\n----- int64_t -> " #target_type "\n");\
     40    I2F(insn,   0, target_type);                    \
     41    I2F(insn,   1, target_type);                    \
     42    I2F(insn,  -1, target_type);                    \
     43    I2F(insn,  42, target_type);                    \
     44    I2F(insn, SHRT_MAX, target_type);               \
     45    I2F(insn, SHRT_MIN, target_type);               \
     46    I2F(insn, INT_MAX, target_type);                \
     47    I2F(insn, INT_MIN, target_type);                \
     48    I2F(insn, LONG_MAX, target_type);               \
     49    I2F(insn, LONG_MIN, target_type);               \
     50 } while (0)
     51 
     52 #define DO_I2F()                        \
     53 do {                                    \
     54    DO_INSN_I32_TO_F("cefbr", float);    \
     55    DO_INSN_I32_TO_F("cdfbr", double);   \
     56    DO_INSN_I64_TO_F("cegbr", float);    \
     57    DO_INSN_I64_TO_F("cdgbr", double);   \
     58 } while (0)
     59 
     60 
     61 #define F2I(insn, initial, source_type, target_type)               \
     62 do {                                                               \
     63    int cc;                                                         \
     64    source_type source = initial;                                   \
     65    target_type target = 0;                                         \
     66    asm volatile(insn " %0,0,%2\n\t"                                \
     67                 "ipm %1\n\t"                                       \
     68                 "srl %1,28\n\t"                                    \
     69  		: "=d" (target), "=d" (cc) : "f"(source) : "cc");  \
     70    printf(insn " %f -> %ld   cc = %d\n", source, (long)target, cc); \
     71 } while (0)
     72 
     73 #define DO_INSN_F32_TO_I(insn, type)          \
     74 do {                                          \
     75    printf("\n----- float -> " #type "\n");    \
     76    F2I(insn, -1.0f, float, type);             \
     77    F2I(insn,  0.0f, float, type);             \
     78    F2I(insn,  1.0f, float, type);             \
     79    F2I(insn, 1.4f, float, type);              \
     80    F2I(insn, 1.5f, float, type);              \
     81    F2I(insn, 1.6f, float, type);              \
     82    F2I(insn, 1.6E+4f, float, type);           \
     83    F2I(insn, 1.6E+8f, float, type);           \
     84    F2I(insn, 1.6E-4f, float, type);           \
     85    F2I(insn, FLT_MAX, float, type);           \
     86 } while (0)
     87 
     88 #define DO_INSN_F64_TO_I(insn, type)          \
     89 do {                                          \
     90    printf("\n----- double -> " #type "\n");   \
     91    F2I(insn, -1.0, double, type);             \
     92    F2I(insn,  0.0, double, type);             \
     93    F2I(insn,  1.0, double, type);             \
     94    F2I(insn, 1.4, double, type);              \
     95    F2I(insn, 1.5, double, type);              \
     96    F2I(insn, 1.6, double, type);              \
     97    F2I(insn, 1.6E+4, double, type);           \
     98    F2I(insn, 1.6E+8, double, type);           \
     99    F2I(insn, 1.6E-4, double, type);           \
    100    F2I(insn, FLT_MAX, double, type);          \
    101    F2I(insn, DBL_MAX, double, type);          \
    102 } while (0)
    103 
    104 #define DO_F2I()                        \
    105 do {                                    \
    106    DO_INSN_F32_TO_I("cfebr", int32_t);  \
    107    DO_INSN_F32_TO_I("cgebr", int64_t);  \
    108    DO_INSN_F64_TO_I("cfdbr", int32_t);  \
    109    DO_INSN_F64_TO_I("cgdbr", int64_t);  \
    110 } while (0)
    111 
    112 
    113 int main()
    114 {
    115    DO_I2F();
    116    DO_F2I();
    117 
    118    return 0;
    119 }
    120