Rewrite simulator floating point module. Do not rely on host FP
implementation. Add preliminary support for different IEEE-754 rounding modes. Implement SQRT in software. Update TiC80 simulator. Add sim-fpu -> TestFloat interface for testing.
This commit is contained in:
parent
22b23d7deb
commit
b3c77578dc
|
@ -0,0 +1,538 @@
|
||||||
|
#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
|
||||||
|
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 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 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 a )
|
||||||
|
{
|
||||||
|
float64 z;
|
||||||
|
sim_fpu s;
|
||||||
|
flags |= sim_fpu_i32to (&s, a, rounding_mode);
|
||||||
|
sim_fpu_to64 (&z, &s);
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
syst_float32_to_int32_round_to_zero( float32 a )
|
||||||
|
{
|
||||||
|
int32 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 syst_float64_to_int32_round_to_zero( float64 a )
|
||||||
|
{
|
||||||
|
int32 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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
Mon Sep 29 12:49:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* insns (get_fp_reg, set_fp_reg): Update to use changed sim_fpu
|
||||||
|
interface.
|
||||||
|
(do_fadd, do_fcmp, do_fdiv, do_fmpy, do_frnd, do_fsub): Ditto.
|
||||||
|
|
||||||
|
* misc.c (tic80_trace_fpu3, tic80_trace_fpu2, tic80_trace_fpu1,
|
||||||
|
tic80_trace_fpu2i) Update to use changed sim_fpu interface.
|
||||||
|
|
||||||
Fri Oct 3 09:28:00 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Fri Oct 3 09:28:00 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* configure.in (SIM_AC_OPTIONS_BITSIZE): Define.
|
* configure.in (SIM_AC_OPTIONS_BITSIZE): Define.
|
||||||
|
|
|
@ -434,10 +434,12 @@ void::function::do_dst:int Source, unsigned32 base, unsigned32 *rBase, int m , i
|
||||||
|
|
||||||
|
|
||||||
sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
|
sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
|
||||||
|
sim_fpu ans;
|
||||||
switch (precision)
|
switch (precision)
|
||||||
{
|
{
|
||||||
case 0: /* single */
|
case 0: /* single */
|
||||||
return sim_fpu_32to (val);
|
sim_fpu_32to (&ans, val);
|
||||||
|
break;
|
||||||
case 1: /* double */
|
case 1: /* double */
|
||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
sim_engine_abort (SD, CPU, cia, "DP immediate invalid");
|
sim_engine_abort (SD, CPU, cia, "DP immediate invalid");
|
||||||
|
@ -445,43 +447,43 @@ sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
|
||||||
sim_engine_abort (SD, CPU, cia, "DP FP register must be even");
|
sim_engine_abort (SD, CPU, cia, "DP FP register must be even");
|
||||||
if (reg <= 1)
|
if (reg <= 1)
|
||||||
sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2");
|
sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2");
|
||||||
return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32)
|
sim_fpu_232to (&ans, GPR (reg), GPR (reg + 1));
|
||||||
| INSERTED64 (GPR (reg), 31, 0));
|
break;
|
||||||
case 2: /* 32 bit signed integer */
|
case 2: /* 32 bit signed integer */
|
||||||
return sim_fpu_i32to (val);
|
sim_fpu_i32to (&ans, val, 0);
|
||||||
|
break;
|
||||||
case 3: /* 32 bit unsigned integer */
|
case 3: /* 32 bit unsigned integer */
|
||||||
return sim_fpu_u32to (val);
|
sim_fpu_u32to (&ans, val, 0);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
|
sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
|
||||||
}
|
}
|
||||||
return sim_fpu_i32to (0);
|
return ans;
|
||||||
void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
||||||
switch (PD)
|
switch (PD)
|
||||||
{
|
{
|
||||||
case 0: /* single */
|
case 0: /* single */
|
||||||
{
|
{
|
||||||
GPR (Dest) = sim_fpu_to32 (val);
|
sim_fpu_to32 (&GPR (Dest), &val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: /* double */
|
case 1: /* double */
|
||||||
{
|
{
|
||||||
unsigned64 v = sim_fpu_to64 (val);
|
|
||||||
if (Dest & 1)
|
if (Dest & 1)
|
||||||
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even");
|
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even");
|
||||||
if (Dest <= 1)
|
if (Dest <= 1)
|
||||||
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2");
|
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2");
|
||||||
GPR (Dest + 0) = VL4_8 (v);
|
sim_fpu_to232 (&GPR (Dest + 0), &GPR (Dest + 1), &val);
|
||||||
GPR (Dest + 1) = VH4_8 (v);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: /* signed */
|
case 2: /* signed */
|
||||||
{
|
{
|
||||||
GPR (Dest) = sim_fpu_to32i (val);
|
sim_fpu_to32i (&GPR (Dest), &val, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: /* unsigned */
|
case 3: /* unsigned */
|
||||||
{
|
{
|
||||||
GPR (Dest) = sim_fpu_to32u (val);
|
sim_fpu_to32u (&GPR (Dest), &val, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -490,7 +492,8 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
||||||
|
|
||||||
// fadd.{s|d}{s|d}{s|d}
|
// fadd.{s|d}{s|d}{s|d}
|
||||||
void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
||||||
sim_fpu ans = sim_fpu_add (s1, s2);
|
sim_fpu ans;
|
||||||
|
sim_fpu_add (&ans, &s1, &s2);
|
||||||
TRACE_FPU3 (ans, s1, s2);
|
TRACE_FPU3 (ans, s1, s2);
|
||||||
set_fp_reg (_SD, Dest, ans, PD);
|
set_fp_reg (_SD, Dest, ans, PD);
|
||||||
const char *::function::str_PX:int PX
|
const char *::function::str_PX:int PX
|
||||||
|
@ -517,25 +520,25 @@ const char *::function::str_PX:int PX
|
||||||
// fcmp.{s|d}{s|d}{s|d}
|
// fcmp.{s|d}{s|d}{s|d}
|
||||||
void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2
|
void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2
|
||||||
unsigned32 result = 0;
|
unsigned32 result = 0;
|
||||||
if (sim_fpu_is_nan (s1) || sim_fpu_is_nan (s2))
|
if (sim_fpu_is_nan (&s1) || sim_fpu_is_nan (&s2))
|
||||||
result |= BIT32 (30);
|
result |= BIT32 (30);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result |= BIT32 (31);
|
result |= BIT32 (31);
|
||||||
if (sim_fpu_is_eq (s1, s2)) result |= BIT32(20);
|
if (sim_fpu_is_eq (&s1, &s2)) result |= BIT32(20);
|
||||||
if (sim_fpu_is_ne (s1, s2)) result |= BIT32(21);
|
if (sim_fpu_is_ne (&s1, &s2)) result |= BIT32(21);
|
||||||
if (sim_fpu_is_gt (s1, s2)) result |= BIT32(22);
|
if (sim_fpu_is_gt (&s1, &s2)) result |= BIT32(22);
|
||||||
if (sim_fpu_is_le (s1, s2)) result |= BIT32(23);
|
if (sim_fpu_is_le (&s1, &s2)) result |= BIT32(23);
|
||||||
if (sim_fpu_is_lt (s1, s2)) result |= BIT32(24);
|
if (sim_fpu_is_lt (&s1, &s2)) result |= BIT32(24);
|
||||||
if (sim_fpu_is_ge (s1, s2)) result |= BIT32(25);
|
if (sim_fpu_is_ge (&s1, &s2)) result |= BIT32(25);
|
||||||
if (sim_fpu_is_lt (s1, sim_fpu_i32to (0))
|
if (sim_fpu_is_lt (&s1, &sim_fpu_zero)
|
||||||
|| sim_fpu_is_gt (s1, s2)) result |= BIT32(26);
|
|| sim_fpu_is_gt (&s1, &s2)) result |= BIT32(26);
|
||||||
if (sim_fpu_is_lt (sim_fpu_i32to (0), s1)
|
if (sim_fpu_is_lt (&sim_fpu_zero, &s1)
|
||||||
&& sim_fpu_is_lt (s1, s2)) result |= BIT32(27);
|
&& sim_fpu_is_lt (&s1, &s2)) result |= BIT32(27);
|
||||||
if (sim_fpu_is_le (sim_fpu_i32to (0), s1)
|
if (sim_fpu_is_le (&sim_fpu_zero, &s1)
|
||||||
&& sim_fpu_is_le (s1, s2)) result |= BIT32(28);
|
&& sim_fpu_is_le (&s1, &s2)) result |= BIT32(28);
|
||||||
if (sim_fpu_is_le (s1, sim_fpu_i32to (0))
|
if (sim_fpu_is_le (&s1, &sim_fpu_zero)
|
||||||
|| sim_fpu_is_ge (s1, s2)) result |= BIT32(29);
|
|| sim_fpu_is_ge (&s1, &s2)) result |= BIT32(29);
|
||||||
}
|
}
|
||||||
*rDest = result;
|
*rDest = result;
|
||||||
TRACE_FPU2I (result, s1, s2);
|
TRACE_FPU2I (result, s1, s2);
|
||||||
|
@ -554,7 +557,8 @@ void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2
|
||||||
|
|
||||||
// fdiv.{s|d}{s|d}{s|d}
|
// fdiv.{s|d}{s|d}{s|d}
|
||||||
void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
||||||
sim_fpu ans = sim_fpu_div (s1, s2);
|
sim_fpu ans;
|
||||||
|
sim_fpu_div (&ans, &s1, &s2);
|
||||||
TRACE_FPU3 (ans, s1, s2);
|
TRACE_FPU3 (ans, s1, s2);
|
||||||
set_fp_reg (_SD, Dest, ans, PD);
|
set_fp_reg (_SD, Dest, ans, PD);
|
||||||
31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fdiv r
|
31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fdiv r
|
||||||
|
@ -575,19 +579,28 @@ void::function::do_fmpy:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
||||||
{
|
{
|
||||||
case 2: /* signed */
|
case 2: /* signed */
|
||||||
{
|
{
|
||||||
GPR (Dest) = sim_fpu_to64i (s1) * sim_fpu_to64i (s2);
|
signed64 i1;
|
||||||
|
signed64 i2;
|
||||||
|
sim_fpu_to64i (&i1, &s1, 0);
|
||||||
|
sim_fpu_to64i (&i2, &s2, 0);
|
||||||
|
GPR (Dest) = i1 * i2;
|
||||||
TRACE_FPU2I (GPR (Dest), s1, s2);
|
TRACE_FPU2I (GPR (Dest), s1, s2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: /* unsigned */
|
case 3: /* unsigned */
|
||||||
{
|
{
|
||||||
GPR (Dest) = sim_fpu_to64u (s1) * sim_fpu_to64u (s2);
|
unsigned64 u1;
|
||||||
|
unsigned64 u2;
|
||||||
|
sim_fpu_to64u (&u1, &s1, 0);
|
||||||
|
sim_fpu_to64u (&u2, &s2, 0);
|
||||||
|
GPR (Dest) = u1 * u2;
|
||||||
TRACE_FPU2I (GPR (Dest), s1, s2);
|
TRACE_FPU2I (GPR (Dest), s1, s2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sim_fpu ans = sim_fpu_mul (s1, s2);
|
sim_fpu ans;
|
||||||
|
sim_fpu_mul (&ans, &s1, &s2);
|
||||||
set_fp_reg (_SD, Dest, ans, PD);
|
set_fp_reg (_SD, Dest, ans, PD);
|
||||||
TRACE_FPU3 (ans, s1, s2);
|
TRACE_FPU3 (ans, s1, s2);
|
||||||
}
|
}
|
||||||
|
@ -664,7 +677,8 @@ void::function::do_frnd:int Dest, int PD, sim_fpu s1
|
||||||
|
|
||||||
// fsub.{s|d}{s|d}{s|d}
|
// fsub.{s|d}{s|d}{s|d}
|
||||||
void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2
|
||||||
sim_fpu ans = sim_fpu_sub (s1, s2);
|
sim_fpu ans;
|
||||||
|
sim_fpu_sub (&ans, &s1, &s2);
|
||||||
TRACE_FPU3 (ans, s1, s2);
|
TRACE_FPU3 (ans, s1, s2);
|
||||||
set_fp_reg (_SD, Dest, ans, PD);
|
set_fp_reg (_SD, Dest, ans, PD);
|
||||||
31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fsub r
|
31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fsub r
|
||||||
|
|
|
@ -241,9 +241,9 @@ tic80_trace_fpu3 (SIM_DESC sd,
|
||||||
itable[indx].file, itable[indx].line_nr, "fpu",
|
itable[indx].file, itable[indx].line_nr, "fpu",
|
||||||
"%-*s %*g %*g => %*g",
|
"%-*s %*g %*g => %*g",
|
||||||
tic80_size_name, itable[indx].name,
|
tic80_size_name, itable[indx].name,
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1),
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input1),
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2),
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input2),
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (result));
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
|
/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
|
||||||
|
@ -262,9 +262,9 @@ tic80_trace_fpu2 (SIM_DESC sd,
|
||||||
itable[indx].file, itable[indx].line_nr, "fpu",
|
itable[indx].file, itable[indx].line_nr, "fpu",
|
||||||
"%-*s %*g %-*s => %*g",
|
"%-*s %*g %-*s => %*g",
|
||||||
tic80_size_name, itable[indx].name,
|
tic80_size_name, itable[indx].name,
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input),
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input),
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
||||||
SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result));
|
SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (&result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
|
/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
|
||||||
|
@ -284,7 +284,7 @@ tic80_trace_fpu1 (SIM_DESC sd,
|
||||||
tic80_size_name, itable[indx].name,
|
tic80_size_name, itable[indx].name,
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
SIZE_HEX + SIZE_DECIMAL + 3, "",
|
||||||
SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result));
|
SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (&result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trace the result of an FPU operation with 1 integer input and an integer output */
|
/* Trace the result of an FPU operation with 1 integer input and an integer output */
|
||||||
|
@ -304,8 +304,8 @@ tic80_trace_fpu2i (SIM_DESC sd,
|
||||||
itable[indx].file, itable[indx].line_nr, "fpu",
|
itable[indx].file, itable[indx].line_nr, "fpu",
|
||||||
"%-*s %*f %*f => 0x%.*lx %-*ld",
|
"%-*s %*f %*f => 0x%.*lx %-*ld",
|
||||||
tic80_size_name, itable[indx].name,
|
tic80_size_name, itable[indx].name,
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1),
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input1),
|
||||||
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2),
|
SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input2),
|
||||||
SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
|
SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue