Added RV32D extension
This commit is contained in:
		| @@ -41,6 +41,8 @@ extern "C" { | ||||
| #include "specialize.h" | ||||
| } | ||||
|  | ||||
| #include <limits> | ||||
|  | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl { | ||||
| @@ -68,18 +70,34 @@ using namespace std; | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| void add_fp_functions_2_module(Module *mod) { | ||||
|     FDECL(fget_flags, INT_TYPE(32)); | ||||
|     FDECL(fadd_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsub_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fmul_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fdiv_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsqrt_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fcmp_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|     FDECL(fcvt_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fmadd_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsel_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|     FDECL(fclass_s,   INT_TYPE(32), INT_TYPE(32)); | ||||
| void add_fp_functions_2_module(Module *mod, uint32_t flen) { | ||||
|     if(flen){ | ||||
|         FDECL(fget_flags, INT_TYPE(32)); | ||||
|         FDECL(fadd_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsub_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fmul_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fdiv_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsqrt_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fcmp_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|         FDECL(fcvt_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fmadd_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsel_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|         FDECL(fclass_s,   INT_TYPE(32), INT_TYPE(32)); | ||||
|         if(flen>32){ | ||||
|             FDECL(fconv_d2f,  INT_TYPE(32), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fconv_f2d,  INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fadd_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fsub_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fmul_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fdiv_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fsqrt_d,    INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fcmp_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); | ||||
|             FDECL(fcvt_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fmadd_d,    INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fsel_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); | ||||
|             FDECL(fclass_d,   INT_TYPE(64), INT_TYPE(64)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| } | ||||
| @@ -202,14 +220,14 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1); | ||||
|     if(op>1) res.v ^= 0x80000000UL; | ||||
|     if(op>1) res.v ^= 1ULL<<31; | ||||
|     return res.v; | ||||
| } | ||||
|  | ||||
| uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { | ||||
|     softfloat_exceptionFlags = 0; | ||||
|     bool v1_nan = (v1 & defaultNaNF32UI) == quiet_nan32; | ||||
|     bool v2_nan = (v2 & defaultNaNF32UI) == quiet_nan32; | ||||
|     bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI; | ||||
|     bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI; | ||||
|     bool v1_snan = softfloat_isSigNaNF32UI(v1); | ||||
|     bool v2_snan = softfloat_isSigNaNF32UI(v2); | ||||
|     if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
| @@ -257,6 +275,156 @@ uint32_t fclass_s( uint32_t v1 ){ | ||||
|         ( isNaN && !isSNaN )                       << 9; | ||||
| } | ||||
|  | ||||
| uint32_t fconv_d2f(uint64_t v1, uint8_t mode){ | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     bool nan = (v1 & defaultNaNF64UI)==defaultNaNF64UI; | ||||
|     if(nan){ | ||||
|         return defaultNaNF32UI; | ||||
|     } else { | ||||
|         float32_t res = f64_to_f32(float64_t{v1}); | ||||
|         return res.v; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint64_t fconv_f2d(uint32_t v1, uint8_t mode){ | ||||
|     bool nan = (v1 & defaultNaNF32UI)==defaultNaNF32UI; | ||||
|     if(nan){ | ||||
|         return defaultNaNF64UI; | ||||
|     } else { | ||||
|         softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|         float64_t res = f32_to_f64(float32_t{v1}); | ||||
|         return res.v; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     bool nan = (v1&defaultNaNF32UI)==quiet_nan32; | ||||
|     bool snan = softfloat_isSigNaNF32UI(v1); | ||||
|    float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r =f64_add(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_sub(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_mul(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_div(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { | ||||
|     float64_t v1f{v1}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_sqrt(v1f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     bool nan = (v1&defaultNaNF64UI)==quiet_nan32 || (v2&defaultNaNF64UI)==quiet_nan32; | ||||
|     bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2); | ||||
|     switch(op){ | ||||
|     case 0: | ||||
|         if(nan | snan){ | ||||
|             if(snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_eq(v1f,v2f )?1:0; | ||||
|     case 1: | ||||
|         if(nan | snan){ | ||||
|             softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_le(v1f,v2f )?1:0; | ||||
|     case 2: | ||||
|         if(nan | snan){ | ||||
|             softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_lt(v1f,v2f )?1:0; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) { | ||||
|     float64_t v1f{v1}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r; | ||||
|     int32_t res; | ||||
|     switch(op){ | ||||
|     case 0: //w->s, fp to int32 | ||||
|         res = f64_to_i64(v1f,rmm_map[mode&0x7],true); | ||||
|         return (uint64_t)res; | ||||
|     case 1: //wu->s | ||||
|         return f64_to_ui64(v1f,rmm_map[mode&0x7],true); | ||||
|     case 2: //s->w | ||||
|         r=i64_to_f64(v1); | ||||
|         return r.v; | ||||
|     case 3: //s->wu | ||||
|         r=ui64_to_f64(v1); | ||||
|         return r.v; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { | ||||
|     // op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)} | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t res = softfloat_mulAddF64(v1, v2, v3, op&0x1); | ||||
|     if(op>1) res.v ^= 1ULL<<63; | ||||
|     return res.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) { | ||||
|     softfloat_exceptionFlags = 0; | ||||
|     bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI; | ||||
|     bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI; | ||||
|     bool v1_snan = softfloat_isSigNaNF64UI(v1); | ||||
|     bool v2_snan = softfloat_isSigNaNF64UI(v2); | ||||
|     if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|     if (v1_nan || v1_snan) | ||||
|         return (v2_nan || v2_snan) ? defaultNaNF64UI : v2; | ||||
|     else | ||||
|         if (v2_nan || v2_snan) | ||||
|             return v1; | ||||
|         else { | ||||
|             if ((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) { | ||||
|                 return op == 0 ? | ||||
|                         ((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) : | ||||
|                         ((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1); | ||||
|             } else { | ||||
|                 float64_t v1f{ v1 }, v2f{ v2 }; | ||||
|                 return op == 0 ? | ||||
|                         (f64_lt(v1f, v2f) ? v1 : v2) : | ||||
|                         (f64_lt(v1f, v2f) ? v2 : v1); | ||||
|             } | ||||
|         } | ||||
| } | ||||
|  | ||||
| uint64_t fclass_d(uint64_t v1  ){ | ||||
|  | ||||
|     float64_t a{v1}; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -50,7 +50,7 @@ | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *mod); | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -89,7 +89,7 @@ protected: | ||||
|  | ||||
|     void setup_module(llvm::Module* m) override { | ||||
|         super::setup_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); | ||||
|     } | ||||
|  | ||||
|     inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, | ||||
|   | ||||
| @@ -50,7 +50,7 @@ | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *mod); | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -89,7 +89,7 @@ protected: | ||||
|  | ||||
|     void setup_module(llvm::Module* m) override { | ||||
|         super::setup_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); | ||||
|     } | ||||
|  | ||||
|     inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user