| /* CGEN fpu support |
| Copyright (C) 1999 Cygnus Solutions. |
| Copyright (C) 2010 Doug Evans. */ |
| |
| #ifndef CGEN_FPU_H |
| #define CGEN_FPU_H |
| |
| /* Floating point support is a little more complicated. |
| We want to support using either host fp insns or an accurate fp library. |
| We also want to support easily added variants (e.g. modified ieee). |
| This is done by vectoring all calls through a table. */ |
| |
| typedef USI SF; |
| typedef UDI DF; |
| typedef struct { SI parts[3]; } XF; |
| typedef struct { SI parts[4]; } TF; |
| |
| #ifndef TARGET_EXT_FP_WORDS |
| #define TARGET_EXT_FP_WORDS 4 |
| #endif |
| |
| /* Supported floating point conversion kinds (rounding modes). |
| FIXME: The IEEE rounding modes need to be implemented. */ |
| |
| typedef enum { |
| FPCONV_DEFAULT = 0, |
| FPCONV_TIES_TO_EVEN = 1, |
| FPCONV_TIES_TO_AWAY = 2, |
| FPCONV_TOWARD_ZERO = 3, |
| FPCONV_TOWARD_POSITIVE = 4, |
| FPCONV_TOWARD_NEGATIVE = 5 |
| } CGEN_FPCONV_KIND; |
| |
| /* forward decl */ |
| typedef struct cgen_fp_ops CGEN_FP_OPS; |
| |
| /* Instance of an fpu. */ |
| |
| typedef struct { |
| /* Usually a pointer back to the SIM_CPU struct. */ |
| void* owner; |
| /* Pointer to ops struct, rather than copy of it, to avoid bloating |
| SIM_CPU struct. */ |
| CGEN_FP_OPS* ops; |
| } CGEN_FPU; |
| |
| /* result of cmp */ |
| |
| typedef enum { |
| /* ??? May wish to distinguish qnan/snan here. */ |
| FP_CMP_EQ, FP_CMP_LT, FP_CMP_GT, FP_CMP_NAN |
| } CGEN_FP_CMP; |
| |
| /* error handler */ |
| |
| typedef void (CGEN_FPU_ERROR_FN) (CGEN_FPU*, int); |
| |
| /* fpu operation table */ |
| |
| struct cgen_fp_ops { |
| |
| /* error (e.g. signalling nan) handler, supplied by owner */ |
| |
| CGEN_FPU_ERROR_FN *error; |
| |
| /* basic SF ops */ |
| |
| SF (*addsf) (CGEN_FPU*, SF, SF); |
| SF (*subsf) (CGEN_FPU*, SF, SF); |
| SF (*mulsf) (CGEN_FPU*, SF, SF); |
| SF (*divsf) (CGEN_FPU*, SF, SF); |
| SF (*remsf) (CGEN_FPU*, SF, SF); |
| SF (*negsf) (CGEN_FPU*, SF); |
| SF (*abssf) (CGEN_FPU*, SF); |
| SF (*sqrtsf) (CGEN_FPU*, SF); |
| SF (*invsf) (CGEN_FPU*, SF); |
| SF (*cossf) (CGEN_FPU*, SF); |
| SF (*sinsf) (CGEN_FPU*, SF); |
| SF (*minsf) (CGEN_FPU*, SF, SF); |
| SF (*maxsf) (CGEN_FPU*, SF, SF); |
| |
| /* ??? to be revisited */ |
| CGEN_FP_CMP (*cmpsf) (CGEN_FPU*, SF, SF); |
| int (*eqsf) (CGEN_FPU*, SF, SF); |
| int (*nesf) (CGEN_FPU*, SF, SF); |
| int (*ltsf) (CGEN_FPU*, SF, SF); |
| int (*lesf) (CGEN_FPU*, SF, SF); |
| int (*gtsf) (CGEN_FPU*, SF, SF); |
| int (*gesf) (CGEN_FPU*, SF, SF); |
| int (*unorderedsf) (CGEN_FPU*, SF, SF); |
| |
| /* basic DF ops */ |
| |
| DF (*adddf) (CGEN_FPU*, DF, DF); |
| DF (*subdf) (CGEN_FPU*, DF, DF); |
| DF (*muldf) (CGEN_FPU*, DF, DF); |
| DF (*divdf) (CGEN_FPU*, DF, DF); |
| DF (*remdf) (CGEN_FPU*, DF, DF); |
| DF (*negdf) (CGEN_FPU*, DF); |
| DF (*absdf) (CGEN_FPU*, DF); |
| DF (*sqrtdf) (CGEN_FPU*, DF); |
| DF (*invdf) (CGEN_FPU*, DF); |
| DF (*cosdf) (CGEN_FPU*, DF); |
| DF (*sindf) (CGEN_FPU*, DF); |
| DF (*mindf) (CGEN_FPU*, DF, DF); |
| DF (*maxdf) (CGEN_FPU*, DF, DF); |
| |
| /* ??? to be revisited */ |
| CGEN_FP_CMP (*cmpdf) (CGEN_FPU*, DF, DF); |
| int (*eqdf) (CGEN_FPU*, DF, DF); |
| int (*nedf) (CGEN_FPU*, DF, DF); |
| int (*ltdf) (CGEN_FPU*, DF, DF); |
| int (*ledf) (CGEN_FPU*, DF, DF); |
| int (*gtdf) (CGEN_FPU*, DF, DF); |
| int (*gedf) (CGEN_FPU*, DF, DF); |
| int (*unordereddf) (CGEN_FPU*, DF, DF); |
| |
| /* SF/DF conversion ops */ |
| |
| DF (*fextsfdf) (CGEN_FPU*, int, SF); |
| SF (*ftruncdfsf) (CGEN_FPU*, int, DF); |
| |
| SF (*floatsisf) (CGEN_FPU*, int, SI); |
| SF (*floatdisf) (CGEN_FPU*, int, DI); |
| SF (*ufloatsisf) (CGEN_FPU*, int, USI); |
| SF (*ufloatdisf) (CGEN_FPU*, int, UDI); |
| |
| SI (*fixsfsi) (CGEN_FPU*, int, SF); |
| DI (*fixsfdi) (CGEN_FPU*, int, SF); |
| USI (*ufixsfsi) (CGEN_FPU*, int, SF); |
| UDI (*ufixsfdi) (CGEN_FPU*, int, SF); |
| |
| DF (*floatsidf) (CGEN_FPU*, int, SI); |
| DF (*floatdidf) (CGEN_FPU*, int, DI); |
| DF (*ufloatsidf) (CGEN_FPU*, int, USI); |
| DF (*ufloatdidf) (CGEN_FPU*, int, UDI); |
| |
| SI (*fixdfsi) (CGEN_FPU*, int, DF); |
| DI (*fixdfdi) (CGEN_FPU*, int, DF); |
| USI (*ufixdfsi) (CGEN_FPU*, int, DF); |
| UDI (*ufixdfdi) (CGEN_FPU*, int, DF); |
| |
| /* XF mode support (kept separate 'cus not always present) */ |
| |
| XF (*addxf) (CGEN_FPU*, XF, XF); |
| XF (*subxf) (CGEN_FPU*, XF, XF); |
| XF (*mulxf) (CGEN_FPU*, XF, XF); |
| XF (*divxf) (CGEN_FPU*, XF, XF); |
| XF (*remxf) (CGEN_FPU*, XF, XF); |
| XF (*negxf) (CGEN_FPU*, XF); |
| XF (*absxf) (CGEN_FPU*, XF); |
| XF (*sqrtxf) (CGEN_FPU*, XF); |
| XF (*invxf) (CGEN_FPU*, XF); |
| XF (*cosxf) (CGEN_FPU*, XF); |
| XF (*sinxf) (CGEN_FPU*, XF); |
| XF (*minxf) (CGEN_FPU*, XF, XF); |
| XF (*maxxf) (CGEN_FPU*, XF, XF); |
| |
| CGEN_FP_CMP (*cmpxf) (CGEN_FPU*, XF, XF); |
| int (*eqxf) (CGEN_FPU*, XF, XF); |
| int (*nexf) (CGEN_FPU*, XF, XF); |
| int (*ltxf) (CGEN_FPU*, XF, XF); |
| int (*lexf) (CGEN_FPU*, XF, XF); |
| int (*gtxf) (CGEN_FPU*, XF, XF); |
| int (*gexf) (CGEN_FPU*, XF, XF); |
| |
| XF (*extsfxf) (CGEN_FPU*, int, SF); |
| XF (*extdfxf) (CGEN_FPU*, int, DF); |
| SF (*truncxfsf) (CGEN_FPU*, int, XF); |
| DF (*truncxfdf) (CGEN_FPU*, int, XF); |
| |
| XF (*floatsixf) (CGEN_FPU*, int, SI); |
| XF (*floatdixf) (CGEN_FPU*, int, DI); |
| XF (*ufloatsixf) (CGEN_FPU*, int, USI); |
| XF (*ufloatdixf) (CGEN_FPU*, int, UDI); |
| |
| SI (*fixxfsi) (CGEN_FPU*, int, XF); |
| DI (*fixxfdi) (CGEN_FPU*, int, XF); |
| USI (*ufixxfsi) (CGEN_FPU*, int, XF); |
| UDI (*ufixxfdi) (CGEN_FPU*, int, XF); |
| |
| /* TF mode support (kept separate 'cus not always present) */ |
| |
| TF (*addtf) (CGEN_FPU*, TF, TF); |
| TF (*subtf) (CGEN_FPU*, TF, TF); |
| TF (*multf) (CGEN_FPU*, TF, TF); |
| TF (*divtf) (CGEN_FPU*, TF, TF); |
| TF (*remtf) (CGEN_FPU*, TF, TF); |
| TF (*negtf) (CGEN_FPU*, TF); |
| TF (*abstf) (CGEN_FPU*, TF); |
| TF (*sqrttf) (CGEN_FPU*, TF); |
| TF (*invtf) (CGEN_FPU*, TF); |
| TF (*costf) (CGEN_FPU*, TF); |
| TF (*sintf) (CGEN_FPU*, TF); |
| TF (*mintf) (CGEN_FPU*, TF, TF); |
| TF (*maxtf) (CGEN_FPU*, TF, TF); |
| |
| CGEN_FP_CMP (*cmptf) (CGEN_FPU*, TF, TF); |
| int (*eqtf) (CGEN_FPU*, TF, TF); |
| int (*netf) (CGEN_FPU*, TF, TF); |
| int (*lttf) (CGEN_FPU*, TF, TF); |
| int (*letf) (CGEN_FPU*, TF, TF); |
| int (*gttf) (CGEN_FPU*, TF, TF); |
| int (*getf) (CGEN_FPU*, TF, TF); |
| |
| TF (*extsftf) (CGEN_FPU*, int, SF); |
| TF (*extdftf) (CGEN_FPU*, int, DF); |
| SF (*trunctfsf) (CGEN_FPU*, int, TF); |
| DF (*trunctfdf) (CGEN_FPU*, int, TF); |
| |
| TF (*floatsitf) (CGEN_FPU*, int, SI); |
| TF (*floatditf) (CGEN_FPU*, int, DI); |
| TF (*ufloatsitf) (CGEN_FPU*, int, USI); |
| TF (*ufloatditf) (CGEN_FPU*, int, UDI); |
| |
| SI (*fixtfsi) (CGEN_FPU*, int, TF); |
| DI (*fixtfdi) (CGEN_FPU*, int, TF); |
| USI (*ufixtfsi) (CGEN_FPU*, int, TF); |
| UDI (*ufixtfdi) (CGEN_FPU*, int, TF); |
| |
| }; |
| |
| extern void cgen_init_accurate_fpu (SIM_CPU*, CGEN_FPU*, CGEN_FPU_ERROR_FN*); |
| |
| BI cgen_sf_snan_p (CGEN_FPU*, SF); |
| BI cgen_df_snan_p (CGEN_FPU*, DF); |
| |
| /* no-op fp error handler */ |
| extern CGEN_FPU_ERROR_FN cgen_fpu_ignore_errors; |
| |
| #endif /* CGEN_FPU_H */ |