| #define ASSERT(EXPRESSION) \ |
| do { \ |
| if (!(EXPRESSION)) { \ |
| fprintf (stderr, "%s:%d: assertion failed - %s\n", \ |
| __FILE__, __LINE__, #EXPRESSION); \ |
| abort (); \ |
| } \ |
| } while (0) |
| |
| #define SIM_BITS_INLINE (INCLUDE_MODULE | INCLUDED_BY_MODULE) |
| |
| #include "milieu.h" |
| #include "softfloat.h" |
| #include "systfloat.h" |
| #include "systmodes.h" |
| |
| /* #define SIM_FPU_INLINE (INCLUDE_MODULE | INCLUDED_BY_MODULE) */ |
| |
| |
| #include "sim-bits.h" |
| #include "sim-fpu.h" |
| #include "sim-fpu.c" |
| |
| |
| |
| static int flags; |
| |
| int8_t |
| syst_float_flags_clear () |
| { |
| int old_flags = 0; |
| int i = 1; |
| while (flags >= i) |
| { |
| switch ((sim_fpu_status) (flags & i)) |
| { |
| case sim_fpu_status_denorm: |
| break; |
| case sim_fpu_status_invalid_snan: |
| case sim_fpu_status_invalid_qnan: |
| case sim_fpu_status_invalid_isi: |
| case sim_fpu_status_invalid_idi: |
| case sim_fpu_status_invalid_zdz: |
| case sim_fpu_status_invalid_imz: |
| case sim_fpu_status_invalid_cvi: |
| case sim_fpu_status_invalid_cmp: |
| case sim_fpu_status_invalid_sqrt: |
| old_flags |= float_flag_invalid; /* v */ |
| break; |
| case sim_fpu_status_inexact: |
| old_flags |= float_flag_inexact; /* x */ |
| break; |
| case sim_fpu_status_overflow: |
| old_flags |= float_flag_overflow; /* o */ |
| break; |
| case sim_fpu_status_underflow: |
| old_flags |= float_flag_underflow; /* u */ |
| break; |
| case sim_fpu_status_invalid_div0: |
| old_flags |= float_flag_divbyzero; /* z */ |
| break; |
| case sim_fpu_status_rounded: |
| break; |
| } |
| i <<= 1; |
| } |
| flags = 0; |
| return old_flags; |
| } |
| |
| |
| sim_fpu_round rounding_mode; |
| |
| void |
| syst_float_set_rounding_mode(int8_t mode) |
| { |
| switch (mode) |
| { |
| case float_round_nearest_even: |
| rounding_mode = sim_fpu_round_near; |
| break; |
| case float_round_down: |
| rounding_mode = sim_fpu_round_down; |
| break; |
| case float_round_up: |
| rounding_mode = sim_fpu_round_up; |
| break; |
| case float_round_to_zero: |
| rounding_mode = sim_fpu_round_zero; |
| break; |
| } |
| } |
| |
| |
| float32 |
| syst_int32_to_float32(int32_t a) |
| { |
| float32 z; |
| sim_fpu s; |
| flags |= sim_fpu_i32to (&s, a, rounding_mode); |
| flags |= sim_fpu_round_32 (&s, rounding_mode, 0); |
| sim_fpu_to32 (&z, &s); |
| return z; |
| } |
| |
| float64 |
| syst_int32_to_float64( int32_t a ) |
| { |
| float64 z; |
| sim_fpu s; |
| flags |= sim_fpu_i32to (&s, a, rounding_mode); |
| sim_fpu_to64 (&z, &s); |
| return z; |
| } |
| |
| int32_t |
| syst_float32_to_int32_round_to_zero( float32 a ) |
| { |
| int32_t z; |
| sim_fpu s; |
| sim_fpu_32to (&s, a); |
| flags |= sim_fpu_to32i (&z, &s, sim_fpu_round_zero); |
| return z; |
| } |
| |
| float64 |
| syst_float32_to_float64 (float32 a) |
| { |
| float64 z; |
| sim_fpu s; |
| sim_fpu_32to (&s, a); |
| flags |= sim_fpu_round_64 (&s, rounding_mode, 0); |
| sim_fpu_to64 (&z, &s); |
| return z; |
| } |
| |
| float32 syst_float32_add( float32 a, float32 b ) |
| { |
| float32 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| #if 0 |
| fprintf (stdout, "\n "); |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n+ "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n= "); |
| #endif |
| flags |= sim_fpu_add (&ans, &A, &B); |
| flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to32 (&z, &ans); |
| return z; |
| } |
| |
| float32 syst_float32_sub( float32 a, float32 b ) |
| { |
| float32 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " + "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_sub (&ans, &A, &B); |
| flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to32 (&z, &ans); |
| return z; |
| } |
| |
| float32 syst_float32_mul( float32 a, float32 b ) |
| { |
| float32 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " + "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_mul (&ans, &A, &B); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to32 (&z, &ans); |
| return z; |
| } |
| |
| float32 syst_float32_div( float32 a, float32 b ) |
| { |
| float32 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= sim_fpu_div (&ans, &A, &B); |
| flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); |
| sim_fpu_to32 (&z, &ans); |
| return z; |
| } |
| |
| float32 syst_float32_sqrt( float32 a ) |
| { |
| float32 z; |
| sim_fpu A; |
| sim_fpu ans; |
| sim_fpu_32to (&A, a); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " sqrt> "); |
| #endif |
| flags |= sim_fpu_sqrt (&ans, &A); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_32 (&ans, rounding_mode, 0); |
| #if 0 |
| fprintf (stdout, " (%x)\n", flags); |
| #endif |
| sim_fpu_to32 (&z, &ans); |
| return z; |
| } |
| |
| flag syst_float32_eq( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= (sim_fpu_eq (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |
| flag syst_float32_eq_signaling( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= sim_fpu_eq (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float32_le( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= sim_fpu_le (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float32_le_quiet( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= (sim_fpu_le (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |
| flag syst_float32_lt( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= sim_fpu_lt (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float32_lt_quiet( float32 a, float32 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_32to (&A, a); |
| sim_fpu_32to (&B, b); |
| flags |= (sim_fpu_lt (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |
| int32_t syst_float64_to_int32_round_to_zero( float64 a ) |
| { |
| int32_t z; |
| sim_fpu s; |
| sim_fpu_64to (&s, a); |
| flags |= sim_fpu_to32i (&z, &s, sim_fpu_round_zero); |
| return z; |
| } |
| |
| float32 syst_float64_to_float32( float64 a ) |
| { |
| float32 z; |
| sim_fpu s; |
| sim_fpu_64to (&s, a); |
| #if 0 |
| sim_fpu_print_fpu (&s, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " -> "); |
| #endif |
| flags |= sim_fpu_round_32 (&s, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_fpu (&s, (sim_fpu_print_func*) fprintf, stdout); |
| sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); |
| printf ("\n"); |
| #endif |
| sim_fpu_to32 (&z, &s); |
| return z; |
| } |
| |
| float64 syst_float64_add( float64 a, float64 b ) |
| { |
| float64 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " + "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_add (&ans, &A, &B); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); |
| #if 0 |
| fprintf (stdout, " (%x)\n", flags); |
| #endif |
| sim_fpu_to64 (&z, &ans); |
| return z; |
| } |
| |
| float64 syst_float64_sub( float64 a, float64 b ) |
| { |
| float64 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " + "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_sub (&ans, &A, &B); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); |
| #if 0 |
| fprintf (stdout, " (%x)\n", flags); |
| #endif |
| sim_fpu_to64 (&z, &ans); |
| return z; |
| } |
| |
| float64 syst_float64_mul( float64 a, float64 b ) |
| { |
| float64 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " * "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_mul (&ans, &A, &B); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to64 (&z, &ans); |
| return z; |
| } |
| |
| float64 syst_float64_div( float64 a, float64 b ) |
| { |
| float64 z; |
| sim_fpu A; |
| sim_fpu B; |
| sim_fpu ans; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " + "); |
| sim_fpu_print_fpu (&B, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, " = "); |
| #endif |
| flags |= sim_fpu_div (&ans, &A, &B); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to64 (&z, &ans); |
| return z; |
| } |
| |
| float64 syst_float64_sqrt( float64 a ) |
| { |
| float64 z; |
| sim_fpu A; |
| sim_fpu ans; |
| sim_fpu_64to (&A, a); |
| #if 0 |
| sim_fpu_print_fpu (&A, (sim_fpu_print_func*) fprintf, stdout); |
| printf (" sqrt> "); |
| printf ("\n"); |
| #endif |
| flags |= sim_fpu_sqrt (&ans, &A); |
| #if 0 |
| sim_fpu_print_fpu (&ans, (sim_fpu_print_func*) fprintf, stdout); |
| #endif |
| flags |= sim_fpu_round_64 (&ans, rounding_mode, 0); |
| #if 0 |
| sim_fpu_print_status (flags, (sim_fpu_print_func*) fprintf, stdout); |
| fprintf (stdout, "\n"); |
| #endif |
| sim_fpu_to64 (&z, &ans); |
| return z; |
| } |
| |
| flag syst_float64_eq( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= (sim_fpu_eq (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |
| flag syst_float64_eq_signaling( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= sim_fpu_eq (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float64_le( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= sim_fpu_le (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float64_le_quiet( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= (sim_fpu_le (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |
| flag syst_float64_lt( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= sim_fpu_lt (&is, &A, &B); |
| return is; |
| } |
| |
| flag syst_float64_lt_quiet( float64 a, float64 b ) |
| { |
| sim_fpu A; |
| sim_fpu B; |
| int is; |
| sim_fpu_64to (&A, a); |
| sim_fpu_64to (&B, b); |
| flags |= (sim_fpu_lt (&is, &A, &B) & ~sim_fpu_status_invalid_qnan); |
| return is; |
| } |
| |