From: Andrew Waterman Date: Tue, 10 Aug 2010 03:51:44 +0000 (-0700) Subject: [xcc,sim] implement FP using softfloat X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2d75bf71bb3990f5a718ddca3c99f9139c03c10b;p=riscv-isa-sim.git [xcc,sim] implement FP using softfloat The intersection of the Hauser FP and MIPS FP is implemented. --- diff --git a/configure b/configure index d6adcf2..5e9e2a3 100755 --- a/configure +++ b/configure @@ -4124,6 +4124,51 @@ fi + # Determine if this is a required or an optional subproject + + + + # Determine if there is a group with the same name + + + + # Create variations of the subproject name suitable for use as a CPP + # enabled define, a shell enabled variable, and a shell function + + + + + + + + + + + + # Add subproject to our running list + + subprojects="$subprojects softfloat" + + # Process the subproject appropriately. If enabled add it to the + # $enabled_subprojects running shell variable, set a + # SUBPROJECT_ENABLED C define, and include the appropriate + # 'subproject.ac'. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : softfloat" >&5 +$as_echo "$as_me: configuring default subproject : softfloat" >&6;} + ac_config_files="$ac_config_files softfloat.mk:softfloat/softfloat.mk.in" + + enable_softfloat_sproj="yes" + subprojects_enabled="$subprojects_enabled softfloat" + +$as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h + + + + + + # Output make variables @@ -4830,6 +4875,7 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "riscv.mk") CONFIG_FILES="$CONFIG_FILES riscv.mk:riscv/riscv.mk.in" ;; + "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; diff --git a/configure.ac b/configure.ac index c7c3a16..967e7c4 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ AC_SUBST([CXXFLAGS],["-Wall -O2"]) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ riscv ]) +MCPPBS_SUBPROJECTS([ riscv, softfloat ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/riscv/decode.h b/riscv/decode.h index 7bdfb18..424ad7f 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -9,13 +9,7 @@ typedef unsigned int uint128_t __attribute__((mode(TI))); #define support_64bit 1 typedef int64_t sreg_t; typedef uint64_t reg_t; - -union freg_t -{ - float sp; - double dp; - uint64_t bits; -}; +typedef uint64_t freg_t; const int OPCODE_BITS = 7; const int JTYPE_OPCODE_BITS = 5; @@ -42,7 +36,38 @@ const int BIGIMM_BITS = 20; #define SR_UX 0x0000000000000020ULL #define SR_KX 0x0000000000000040ULL #define SR_IM 0x000000000000FF00ULL -#define SR_ZERO 0xFFFFFFFFFFFF0082ULL +#define SR_ZERO ~(SR_ET | SR_PS | SR_S | SR_EF | SR_UX | SR_KX | SR_IM) + +#define FP_RD_NE 0 +#define FP_RD_0 1 +#define FP_RD_UP 2 +#define FP_RD_DN 3 +#define FSR_RD_SHIFT 10 +#define FSR_RD (0x3 << FSR_RD_SHIFT) + +#define FPEXC_NV 0x10 +#define FPEXC_OF 0x08 +#define FPEXC_UF 0x04 +#define FPEXC_DZ 0x02 +#define FPEXC_NX 0x01 + +#define FSR_AEXC_SHIFT 5 +#define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT) +#define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT) +#define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT) +#define FSR_DZA (FPEXC_DZ << FSR_AEXC_SHIFT) +#define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT) +#define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) + +#define FSR_CEXC_SHIFT 0 +#define FSR_NVC (FPEXC_NV << FSR_AEXC_SHIFT) +#define FSR_OFC (FPEXC_OF << FSR_AEXC_SHIFT) +#define FSR_UFC (FPEXC_UF << FSR_AEXC_SHIFT) +#define FSR_DZC (FPEXC_DZ << FSR_AEXC_SHIFT) +#define FSR_NXC (FPEXC_NX << FSR_AEXC_SHIFT) +#define FSR_CEXC (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC) + +#define FSR_ZERO ~(FSR_RD | FSR_AEXC | FSR_CEXC) // note: bit fields are in little-endian order struct itype_t @@ -118,6 +143,10 @@ union insn_t #define require64 if(gprlen != 64) throw trap_illegal_instruction #define require_fp if(!(sr & SR_EF)) throw trap_fp_disabled #define cmp_trunc(reg) (reg_t(reg) << (64-gprlen)) +#define set_fp_exceptions ({ set_fsr((fsr & ~FSR_CEXC) | \ + (float_exception_flags << FSR_AEXC_SHIFT) | \ + (float_exception_flags << FSR_CEXC_SHIFT)); \ + float_exception_flags = 0; }) static inline sreg_t sext32(int32_t arg) { diff --git a/riscv/execute.h b/riscv/execute.h index ad655ac..f5b83af 100644 --- a/riscv/execute.h +++ b/riscv/execute.h @@ -149,262 +149,130 @@ switch((insn.bits >> 0x19) & 0x7f) } #include "insns/unimp.h" } - default: - { - #include "insns/unimp.h" - } - } - break; - } - case 0x69: - { - switch((insn.bits >> 0xc) & 0x7) - { - case 0x0: + case 0x1: { - if((insn.bits & 0xfe0ffc00) == 0xd2000000) + if((insn.bits & 0xfe0fffe0) == 0xd00010c0) { - #include "insns/round_l_fmt.h" + #include "insns/cvt_s_w.h" break; } - #include "insns/unimp.h" - } - case 0x1: - { - if((insn.bits & 0xfe0ffc00) == 0xd2001000) + if((insn.bits & 0xfe0fffe0) == 0xd0001ca0) { - #include "insns/trunc_l_fmt.h" + #include "insns/cvtu_d_l.h" break; } - #include "insns/unimp.h" - } - case 0x2: - { - if((insn.bits & 0xfe0ffc00) == 0xd2002000) + if((insn.bits & 0xfe0fffe0) == 0xd0001c40) { - #include "insns/ceil_l_fmt.h" + #include "insns/trunc_w_d.h" break; } - #include "insns/unimp.h" - } - case 0x3: - { - if((insn.bits & 0xfe0ffc00) == 0xd2003000) + if((insn.bits & 0xfe0fffe0) == 0xd0001040) { - #include "insns/floor_l_fmt.h" + #include "insns/trunc_w_s.h" break; } - #include "insns/unimp.h" - } - case 0x4: - { - if((insn.bits & 0xfe0ffc00) == 0xd2004000) + if((insn.bits & 0xfe0fffe0) == 0xd0001ce0) { - #include "insns/round_w_fmt.h" + #include "insns/cvtu_d_w.h" break; } - #include "insns/unimp.h" - } - case 0x5: - { - if((insn.bits & 0xfe0ffc00) == 0xd2005000) + if((insn.bits & 0xfe0fffe0) == 0xd0001e00) { - #include "insns/trunc_w_fmt.h" + #include "insns/cvt_d_s.h" break; } - #include "insns/unimp.h" - } - case 0x6: - { - if((insn.bits & 0xfe0ffc00) == 0xd2006000) + if((insn.bits & 0xfe0fffe0) == 0xd0001000) { - #include "insns/ceil_w_fmt.h" + #include "insns/trunc_l_s.h" break; } - #include "insns/unimp.h" - } - case 0x7: - { - if((insn.bits & 0xfe0ffc00) == 0xd2007000) + if((insn.bits & 0xfe0fffe0) == 0xd0001c00) { - #include "insns/floor_w_fmt.h" + #include "insns/trunc_l_d.h" break; } - #include "insns/unimp.h" - } - default: - { - #include "insns/unimp.h" - } - } - break; - } - case 0x6a: - { - switch((insn.bits >> 0xc) & 0x7) - { - case 0x0: - { - if((insn.bits & 0xfe007fff) == 0xd4000000) + if((insn.bits & 0xfe0fffe0) == 0xd00010e0) { - #include "insns/mff_s.h" + #include "insns/cvtu_s_w.h" break; } - #include "insns/unimp.h" - } - case 0x1: - { - if((insn.bits & 0xfe007fff) == 0xd4001000) + if((insn.bits & 0xfe0fffe0) == 0xd0001020) { - #include "insns/mff_d.h" + #include "insns/truncu_l_s.h" break; } - #include "insns/unimp.h" - } - case 0x4: - { - if((insn.bits & 0xfe007fff) == 0xd4004000) + if((insn.bits & 0xfe0fffe0) == 0xd0001c20) { - #include "insns/mtf_s.h" + #include "insns/truncu_l_d.h" break; } - #include "insns/unimp.h" - } - case 0x5: - { - if((insn.bits & 0xfe007fff) == 0xd4005000) + if((insn.bits & 0xfe0fffe0) == 0xd00010a0) { - #include "insns/mtf_d.h" + #include "insns/cvtu_s_l.h" break; } - #include "insns/unimp.h" - } - default: - { - #include "insns/unimp.h" - } - } - break; - } - case 0x6b: - { - switch((insn.bits >> 0xc) & 0x7) - { - case 0x0: - { - if((insn.bits & 0xfe0ffc00) == 0xd6000000) + if((insn.bits & 0xfe0fffe0) == 0xd0001080) { - #include "insns/cvt_s_fmt.h" + #include "insns/cvt_s_l.h" break; } - #include "insns/unimp.h" - } - case 0x1: - { - if((insn.bits & 0xfe0ffc00) == 0xd6001000) + if((insn.bits & 0xfe0fffe0) == 0xd0001260) { - #include "insns/cvt_d_fmt.h" + #include "insns/cvt_s_d.h" break; } - #include "insns/unimp.h" - } - case 0x4: - { - if((insn.bits & 0xfe0ffc00) == 0xd6004000) + if((insn.bits & 0xfe0fffe0) == 0xd0001060) { - #include "insns/cvt_w_fmt.h" + #include "insns/truncu_w_s.h" break; } - #include "insns/unimp.h" - } - case 0x5: - { - if((insn.bits & 0xfe0ffc00) == 0xd6005000) + if((insn.bits & 0xfe0fffe0) == 0xd0001cc0) { - #include "insns/cvt_l_fmt.h" + #include "insns/cvt_d_w.h" break; } - #include "insns/unimp.h" - } - default: - { - #include "insns/unimp.h" - } - } - break; - } - case 0x6c: - { - switch((insn.bits >> 0xc) & 0x7) - { - case 0x0: - { - if((insn.bits & 0xfe007c00) == 0xd8000000) + if((insn.bits & 0xfe0fffe0) == 0xd0001c80) { - #include "insns/c_f_fmt.h" + #include "insns/cvt_d_l.h" break; } - #include "insns/unimp.h" - } - case 0x1: - { - if((insn.bits & 0xfe007c00) == 0xd8001000) + if((insn.bits & 0xfe0fffe0) == 0xd0001c60) { - #include "insns/c_un_fmt.h" + #include "insns/truncu_w_d.h" break; } #include "insns/unimp.h" } case 0x2: { - if((insn.bits & 0xfe007c00) == 0xd8002000) + if((insn.bits & 0xfe007fe0) == 0xd0002c20) { - #include "insns/c_eq_fmt.h" + #include "insns/c_eq_d.h" break; } - #include "insns/unimp.h" - } - case 0x3: - { - if((insn.bits & 0xfe007c00) == 0xd8003000) + if((insn.bits & 0xfe007fe0) == 0xd0002020) { - #include "insns/c_ueq_fmt.h" + #include "insns/c_eq_s.h" break; } - #include "insns/unimp.h" - } - case 0x4: - { - if((insn.bits & 0xfe007c00) == 0xd8004000) + if((insn.bits & 0xfe007fe0) == 0xd0002c60) { - #include "insns/c_olt_fmt.h" + #include "insns/c_le_d.h" break; } - #include "insns/unimp.h" - } - case 0x5: - { - if((insn.bits & 0xfe007c00) == 0xd8005000) + if((insn.bits & 0xfe007fe0) == 0xd0002040) { - #include "insns/c_ult_fmt.h" + #include "insns/c_lt_s.h" break; } - #include "insns/unimp.h" - } - case 0x6: - { - if((insn.bits & 0xfe007c00) == 0xd8006000) + if((insn.bits & 0xfe007fe0) == 0xd0002060) { - #include "insns/c_ole_fmt.h" + #include "insns/c_le_s.h" break; } - #include "insns/unimp.h" - } - case 0x7: - { - if((insn.bits & 0xfe007c00) == 0xd8007000) + if((insn.bits & 0xfe007fe0) == 0xd0002c40) { - #include "insns/c_ule_fmt.h" + #include "insns/c_lt_d.h" break; } #include "insns/unimp.h" @@ -416,78 +284,42 @@ switch((insn.bits >> 0x19) & 0x7f) } break; } - case 0x6d: + case 0x6a: { switch((insn.bits >> 0xc) & 0x7) { case 0x0: { - if((insn.bits & 0xfe007c00) == 0xda000000) + if((insn.bits & 0xfe007fff) == 0xd4000000) { - #include "insns/c_sf_fmt.h" + #include "insns/mff_s.h" break; } #include "insns/unimp.h" } case 0x1: { - if((insn.bits & 0xfe007c00) == 0xda001000) - { - #include "insns/c_ngle_fmt.h" - break; - } - #include "insns/unimp.h" - } - case 0x2: - { - if((insn.bits & 0xfe007c00) == 0xda002000) - { - #include "insns/c_seq_fmt.h" - break; - } - #include "insns/unimp.h" - } - case 0x3: - { - if((insn.bits & 0xfe007c00) == 0xda003000) + if((insn.bits & 0xfe007fff) == 0xd4001000) { - #include "insns/c_ngl_fmt.h" + #include "insns/mff_d.h" break; } #include "insns/unimp.h" } case 0x4: { - if((insn.bits & 0xfe007c00) == 0xda004000) + if((insn.bits & 0xfe007fff) == 0xd4004000) { - #include "insns/c_lt_fmt.h" + #include "insns/mtf_s.h" break; } #include "insns/unimp.h" } case 0x5: { - if((insn.bits & 0xfe007c00) == 0xda005000) - { - #include "insns/c_nge_fmt.h" - break; - } - #include "insns/unimp.h" - } - case 0x6: - { - if((insn.bits & 0xfe007c00) == 0xda006000) - { - #include "insns/c_le_fmt.h" - break; - } - #include "insns/unimp.h" - } - case 0x7: - { - if((insn.bits & 0xfe007c00) == 0xda007000) + if((insn.bits & 0xfe007fff) == 0xd4005000) { - #include "insns/c_ngt_fmt.h" + #include "insns/mtf_d.h" break; } #include "insns/unimp.h" diff --git a/riscv/insns/add_d.h b/riscv/insns/add_d.h index e69de29..bd0f55a 100644 --- a/riscv/insns/add_d.h +++ b/riscv/insns/add_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_add(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/add_s.h b/riscv/insns/add_s.h index e69de29..b4f98f6 100644 --- a/riscv/insns/add_s.h +++ b/riscv/insns/add_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_add(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_eq_d.h b/riscv/insns/c_eq_d.h new file mode 100644 index 0000000..4387ea3 --- /dev/null +++ b/riscv/insns/c_eq_d.h @@ -0,0 +1,3 @@ +require_fp; +RC = float64_eq(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_eq_fmt.h b/riscv/insns/c_eq_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_eq_s.h b/riscv/insns/c_eq_s.h new file mode 100644 index 0000000..062fb74 --- /dev/null +++ b/riscv/insns/c_eq_s.h @@ -0,0 +1,3 @@ +require_fp; +RC = float32_eq(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_f_fmt.h b/riscv/insns/c_f_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_le_d.h b/riscv/insns/c_le_d.h new file mode 100644 index 0000000..24ea657 --- /dev/null +++ b/riscv/insns/c_le_d.h @@ -0,0 +1,3 @@ +require_fp; +RC = float64_le(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_le_fmt.h b/riscv/insns/c_le_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_le_s.h b/riscv/insns/c_le_s.h new file mode 100644 index 0000000..107622f --- /dev/null +++ b/riscv/insns/c_le_s.h @@ -0,0 +1,3 @@ +require_fp; +RC = float32_le(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_lt_d.h b/riscv/insns/c_lt_d.h new file mode 100644 index 0000000..3d42500 --- /dev/null +++ b/riscv/insns/c_lt_d.h @@ -0,0 +1,3 @@ +require_fp; +RC = float64_lt(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_lt_fmt.h b/riscv/insns/c_lt_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_lt_s.h b/riscv/insns/c_lt_s.h new file mode 100644 index 0000000..1f7a0e1 --- /dev/null +++ b/riscv/insns/c_lt_s.h @@ -0,0 +1,3 @@ +require_fp; +RC = float32_lt(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/c_nge_fmt.h b/riscv/insns/c_nge_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ngl_fmt.h b/riscv/insns/c_ngl_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ngle_fmt.h b/riscv/insns/c_ngle_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ngt_fmt.h b/riscv/insns/c_ngt_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ole_fmt.h b/riscv/insns/c_ole_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_olt_fmt.h b/riscv/insns/c_olt_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_seq_fmt.h b/riscv/insns/c_seq_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_sf_fmt.h b/riscv/insns/c_sf_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ueq_fmt.h b/riscv/insns/c_ueq_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ule_fmt.h b/riscv/insns/c_ule_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_ult_fmt.h b/riscv/insns/c_ult_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/c_un_fmt.h b/riscv/insns/c_un_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/ceil_l_fmt.h b/riscv/insns/ceil_l_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/ceil_w_fmt.h b/riscv/insns/ceil_w_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/cvt_d_fmt.h b/riscv/insns/cvt_d_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/cvt_d_l.h b/riscv/insns/cvt_d_l.h new file mode 100644 index 0000000..5246f6f --- /dev/null +++ b/riscv/insns/cvt_d_l.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int64_to_float64(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_d_s.h b/riscv/insns/cvt_d_s.h new file mode 100644 index 0000000..481a4d1 --- /dev/null +++ b/riscv/insns/cvt_d_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_to_float64(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_d_w.h b/riscv/insns/cvt_d_w.h new file mode 100644 index 0000000..67702a2 --- /dev/null +++ b/riscv/insns/cvt_d_w.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int32_to_float64(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_l_fmt.h b/riscv/insns/cvt_l_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/cvt_s_d.h b/riscv/insns/cvt_s_d.h new file mode 100644 index 0000000..528f11c --- /dev/null +++ b/riscv/insns/cvt_s_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_to_float32(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_s_fmt.h b/riscv/insns/cvt_s_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/cvt_s_l.h b/riscv/insns/cvt_s_l.h new file mode 100644 index 0000000..2d1f93a --- /dev/null +++ b/riscv/insns/cvt_s_l.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int64_to_float32(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_s_w.h b/riscv/insns/cvt_s_w.h new file mode 100644 index 0000000..c2d583f --- /dev/null +++ b/riscv/insns/cvt_s_w.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int32_to_float32(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvt_w_fmt.h b/riscv/insns/cvt_w_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/cvtu_d_l.h b/riscv/insns/cvtu_d_l.h new file mode 100644 index 0000000..5246f6f --- /dev/null +++ b/riscv/insns/cvtu_d_l.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int64_to_float64(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvtu_d_w.h b/riscv/insns/cvtu_d_w.h new file mode 100644 index 0000000..67702a2 --- /dev/null +++ b/riscv/insns/cvtu_d_w.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int32_to_float64(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvtu_s_l.h b/riscv/insns/cvtu_s_l.h new file mode 100644 index 0000000..2d1f93a --- /dev/null +++ b/riscv/insns/cvtu_s_l.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int64_to_float32(FRA); +set_fp_exceptions; diff --git a/riscv/insns/cvtu_s_w.h b/riscv/insns/cvtu_s_w.h new file mode 100644 index 0000000..c2d583f --- /dev/null +++ b/riscv/insns/cvtu_s_w.h @@ -0,0 +1,3 @@ +require_fp; +FRC = int32_to_float32(FRA); +set_fp_exceptions; diff --git a/riscv/insns/div_d.h b/riscv/insns/div_d.h index e69de29..3b47563 100644 --- a/riscv/insns/div_d.h +++ b/riscv/insns/div_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_div(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/div_s.h b/riscv/insns/div_s.h index e69de29..cb5c9bd 100644 --- a/riscv/insns/div_s.h +++ b/riscv/insns/div_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_div(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/floor_l_fmt.h b/riscv/insns/floor_l_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/floor_w_fmt.h b/riscv/insns/floor_w_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/l_d.h b/riscv/insns/l_d.h index 279fff2..760cf98 100644 --- a/riscv/insns/l_d.h +++ b/riscv/insns/l_d.h @@ -1,2 +1,2 @@ require_fp; -FRA.bits = mmu.load_int64(RB+SIMM); +FRA = mmu.load_int64(RB+SIMM); diff --git a/riscv/insns/l_s.h b/riscv/insns/l_s.h index 11cdf18..1637fed 100644 --- a/riscv/insns/l_s.h +++ b/riscv/insns/l_s.h @@ -1,2 +1,2 @@ require_fp; -FRA.bits = mmu.load_int32(RB+SIMM); +FRA = mmu.load_int32(RB+SIMM); diff --git a/riscv/insns/mff_d.h b/riscv/insns/mff_d.h index f1bb205..eaece44 100644 --- a/riscv/insns/mff_d.h +++ b/riscv/insns/mff_d.h @@ -1,3 +1,3 @@ require64; require_fp; -RA = FRB.bits; +RA = FRB; diff --git a/riscv/insns/mff_s.h b/riscv/insns/mff_s.h index 9e3b9c4..6233a3f 100644 --- a/riscv/insns/mff_s.h +++ b/riscv/insns/mff_s.h @@ -1,2 +1,2 @@ require_fp; -RA = sext32(FRB.bits); +RA = sext32(FRB); diff --git a/riscv/insns/mtf_d.h b/riscv/insns/mtf_d.h index b0eeca9..fcee6a1 100644 --- a/riscv/insns/mtf_d.h +++ b/riscv/insns/mtf_d.h @@ -1,3 +1,3 @@ require64; require_fp; -FRA.bits = RB; +FRA = RB; diff --git a/riscv/insns/mtf_s.h b/riscv/insns/mtf_s.h index 04f33fe..a3b7737 100644 --- a/riscv/insns/mtf_s.h +++ b/riscv/insns/mtf_s.h @@ -1,2 +1,2 @@ require_fp; -FRA.bits = RB; +FRA = sext32(RB); diff --git a/riscv/insns/mul_d.h b/riscv/insns/mul_d.h index e69de29..b2a0dbf 100644 --- a/riscv/insns/mul_d.h +++ b/riscv/insns/mul_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_mul(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/mul_s.h b/riscv/insns/mul_s.h index e69de29..e7d4f3f 100644 --- a/riscv/insns/mul_s.h +++ b/riscv/insns/mul_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_mul(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/round_l_fmt.h b/riscv/insns/round_l_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/round_w_fmt.h b/riscv/insns/round_w_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/s_d.h b/riscv/insns/s_d.h index 2d2f9c3..d1c8037 100644 --- a/riscv/insns/s_d.h +++ b/riscv/insns/s_d.h @@ -1,2 +1,2 @@ require_fp; -mmu.store_uint64(RB+SIMM, FRA.bits); +mmu.store_uint64(RB+SIMM, FRA); diff --git a/riscv/insns/s_s.h b/riscv/insns/s_s.h index 6c3006e..837c258 100644 --- a/riscv/insns/s_s.h +++ b/riscv/insns/s_s.h @@ -1,2 +1,2 @@ require_fp; -mmu.store_uint32(RB+SIMM, FRA.bits); +mmu.store_uint32(RB+SIMM, FRA); diff --git a/riscv/insns/sgninj_d.h b/riscv/insns/sgninj_d.h index a87ca63..8bca56a 100644 --- a/riscv/insns/sgninj_d.h +++ b/riscv/insns/sgninj_d.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = (FRA.bits &~ INT64_MIN) | (FRB.bits & INT64_MIN); +FRC = (FRA &~ INT64_MIN) | (FRB & INT64_MIN); diff --git a/riscv/insns/sgninj_s.h b/riscv/insns/sgninj_s.h index db56f49..b688177 100644 --- a/riscv/insns/sgninj_s.h +++ b/riscv/insns/sgninj_s.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = (FRA.bits &~ (uint32_t)INT32_MIN) | (FRB.bits & (uint32_t)INT32_MIN); +FRC = (FRA &~ (uint32_t)INT32_MIN) | (FRB & (uint32_t)INT32_MIN); diff --git a/riscv/insns/sgninjn_d.h b/riscv/insns/sgninjn_d.h index 5fad072..c526735 100644 --- a/riscv/insns/sgninjn_d.h +++ b/riscv/insns/sgninjn_d.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = (FRA.bits &~ INT64_MIN) | ((~FRB.bits) & INT64_MIN); +FRC = (FRA &~ INT64_MIN) | ((~FRB) & INT64_MIN); diff --git a/riscv/insns/sgninjn_s.h b/riscv/insns/sgninjn_s.h index c50967b..80dd7e8 100644 --- a/riscv/insns/sgninjn_s.h +++ b/riscv/insns/sgninjn_s.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = (FRA.bits &~ (uint32_t)INT32_MIN) | ((~FRB.bits) & (uint32_t)INT32_MIN); +FRC = (FRA &~ (uint32_t)INT32_MIN) | ((~FRB) & (uint32_t)INT32_MIN); diff --git a/riscv/insns/sgnmul_d.h b/riscv/insns/sgnmul_d.h index 47d950f..c30dcea 100644 --- a/riscv/insns/sgnmul_d.h +++ b/riscv/insns/sgnmul_d.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = FRA.bits ^ (FRB.bits & INT64_MIN); +FRC = FRA ^ (FRB & INT64_MIN); diff --git a/riscv/insns/sgnmul_s.h b/riscv/insns/sgnmul_s.h index 2a9ae11..6640b31 100644 --- a/riscv/insns/sgnmul_s.h +++ b/riscv/insns/sgnmul_s.h @@ -1,2 +1,2 @@ require_fp; -FRC.bits = FRA.bits ^ (FRB.bits & (uint32_t)INT32_MIN); +FRC = FRA ^ (FRB & (uint32_t)INT32_MIN); diff --git a/riscv/insns/sqrt_d.h b/riscv/insns/sqrt_d.h index e69de29..3f831f5 100644 --- a/riscv/insns/sqrt_d.h +++ b/riscv/insns/sqrt_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_sqrt(FRA); +set_fp_exceptions; diff --git a/riscv/insns/sqrt_s.h b/riscv/insns/sqrt_s.h index e69de29..51b5892 100644 --- a/riscv/insns/sqrt_s.h +++ b/riscv/insns/sqrt_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_sqrt(FRA); +set_fp_exceptions; diff --git a/riscv/insns/sub_d.h b/riscv/insns/sub_d.h index e69de29..55d0e86 100644 --- a/riscv/insns/sub_d.h +++ b/riscv/insns/sub_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_sub(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/sub_s.h b/riscv/insns/sub_s.h index e69de29..4a359bf 100644 --- a/riscv/insns/sub_s.h +++ b/riscv/insns/sub_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_sub(FRA, FRB); +set_fp_exceptions; diff --git a/riscv/insns/trunc_l_d.h b/riscv/insns/trunc_l_d.h new file mode 100644 index 0000000..ecca8cd --- /dev/null +++ b/riscv/insns/trunc_l_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_to_int64_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/trunc_l_fmt.h b/riscv/insns/trunc_l_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/trunc_l_s.h b/riscv/insns/trunc_l_s.h new file mode 100644 index 0000000..9dd0e51 --- /dev/null +++ b/riscv/insns/trunc_l_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_to_int64_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/trunc_w_d.h b/riscv/insns/trunc_w_d.h new file mode 100644 index 0000000..9b7cdb0 --- /dev/null +++ b/riscv/insns/trunc_w_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_to_int32_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/trunc_w_fmt.h b/riscv/insns/trunc_w_fmt.h deleted file mode 100644 index e69de29..0000000 diff --git a/riscv/insns/trunc_w_s.h b/riscv/insns/trunc_w_s.h new file mode 100644 index 0000000..147ec8b --- /dev/null +++ b/riscv/insns/trunc_w_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_to_int32_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/truncu_l_d.h b/riscv/insns/truncu_l_d.h new file mode 100644 index 0000000..ecca8cd --- /dev/null +++ b/riscv/insns/truncu_l_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_to_int64_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/truncu_l_s.h b/riscv/insns/truncu_l_s.h new file mode 100644 index 0000000..9dd0e51 --- /dev/null +++ b/riscv/insns/truncu_l_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_to_int64_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/truncu_w_d.h b/riscv/insns/truncu_w_d.h new file mode 100644 index 0000000..9b7cdb0 --- /dev/null +++ b/riscv/insns/truncu_w_d.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float64_to_int32_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/insns/truncu_w_s.h b/riscv/insns/truncu_w_s.h new file mode 100644 index 0000000..147ec8b --- /dev/null +++ b/riscv/insns/truncu_w_s.h @@ -0,0 +1,3 @@ +require_fp; +FRC = float32_to_int32_round_to_zero(FRA); +set_fp_exceptions; diff --git a/riscv/processor.cc b/riscv/processor.cc index 5751c70..7ca015d 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -1,11 +1,13 @@ #include #include +#include #include #include #include "processor.h" #include "common.h" #include "config.h" #include "sim.h" +#include "softfloat.h" processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz) : sim(_sim), mmu(_mem,_memsz) @@ -17,6 +19,7 @@ processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz) epc = 0; badvaddr = 0; set_sr(SR_S); + set_fsr(0); memset(counters,0,sizeof(counters)); @@ -45,6 +48,11 @@ void processor_t::set_sr(uint32_t val) gprlen = ((sr & SR_S) ? (sr & SR_KX) : (sr & SR_UX)) ? 64 : 32; } +void processor_t::set_fsr(uint32_t val) +{ + fsr = val & ~FSR_ZERO; +} + void processor_t::step(size_t n, bool noisy) { size_t i = 0; diff --git a/riscv/processor.h b/riscv/processor.h index 652fa07..8c64d6d 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -27,6 +27,7 @@ private: reg_t ebase; uint32_t id; uint32_t sr; + uint32_t fsr; int gprlen; // shared memory @@ -37,6 +38,7 @@ private: // functions void set_sr(uint32_t val); + void set_fsr(uint32_t val); void take_trap(trap_t t); void disasm(insn_t insn, reg_t pc); diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index bd806cc..3f6427d 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1,4 +1,4 @@ -riscv_subproject_deps = +riscv_subproject_deps = softfloat \ riscv_hdrs = \ applink.h \ diff --git a/softfloat/softfloat-header b/softfloat/softfloat-header new file mode 100644 index 0000000..eb5303a --- /dev/null +++ b/softfloat/softfloat-header @@ -0,0 +1,259 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| The macro `FLOATX80' must be defined to enable the extended double-precision +| floating-point format `floatx80'. If this macro is not defined, the +| `floatx80' type will not be defined, and none of the functions that either +| input or output the `floatx80' type will be defined. The same applies to +| the `FLOAT128' macro and the quadruple-precision format `float128'. +*----------------------------------------------------------------------------*/ +#define FLOATX80 +#define FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef unsigned int float32; +typedef unsigned long long float64; +#ifdef FLOATX80 +typedef struct { + unsigned short high; + unsigned long long low; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + unsigned long long high, low; +} float128; +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern int float_detect_tininess; +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern int float_rounding_mode; +enum { + float_round_nearest_even = 0, + float_round_to_zero = 1, + float_round_up = 2, + float_round_down = 3 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern int float_exception_flags; +enum { + float_flag_inexact = 1, + float_flag_divbyzero = 2, + float_flag_underflow = 4, + float_flag_overflow = 8, + float_flag_invalid = 16 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software IEC/IEEE floating-point +| exception flags. +*----------------------------------------------------------------------------*/ +void float_raise( int ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +float32 int64_to_float32( long long ); +float64 int64_to_float64( long long ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( long long ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( long long ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +long long float32_to_int64( float32 ); +long long float32_to_int64_round_to_zero( float32 ); +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision operations. +*----------------------------------------------------------------------------*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +int float32_eq( float32, float32 ); +int float32_le( float32, float32 ); +int float32_lt( float32, float32 ); +int float32_eq_signaling( float32, float32 ); +int float32_le_quiet( float32, float32 ); +int float32_lt_quiet( float32, float32 ); +int float32_is_signaling_nan( float32 ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +long long float64_to_int64( float64 ); +long long float64_to_int64_round_to_zero( float64 ); +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision operations. +*----------------------------------------------------------------------------*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +int float64_eq( float64, float64 ); +int float64_le( float64, float64 ); +int float64_lt( float64, float64 ); +int float64_eq_signaling( float64, float64 ); +int float64_le_quiet( float64, float64 ); +int float64_lt_quiet( float64, float64 ); +int float64_is_signaling_nan( float64 ); + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +long long floatx80_to_int64( floatx80 ); +long long floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision rounding precision. Valid +| values are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern int floatx80_rounding_precision; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +int floatx80_eq( floatx80, floatx80 ); +int floatx80_le( floatx80, floatx80 ); +int floatx80_lt( floatx80, floatx80 ); +int floatx80_eq_signaling( floatx80, floatx80 ); +int floatx80_le_quiet( floatx80, floatx80 ); +int floatx80_lt_quiet( floatx80, floatx80 ); +int floatx80_is_signaling_nan( floatx80 ); + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +long long float128_to_int64( float128 ); +long long float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision operations. +*----------------------------------------------------------------------------*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +int float128_eq( float128, float128 ); +int float128_le( float128, float128 ); +int float128_lt( float128, float128 ); +int float128_eq_signaling( float128, float128 ); +int float128_le_quiet( float128, float128 ); +int float128_lt_quiet( float128, float128 ); +int float128_is_signaling_nan( float128 ); + +#endif + diff --git a/softfloat/softfloat.ac b/softfloat/softfloat.ac new file mode 100644 index 0000000..e69de29 diff --git a/softfloat/softfloat.c b/softfloat/softfloat.c index 3c31f0e..0d09b40 100644 --- a/softfloat/softfloat.c +++ b/softfloat/softfloat.c @@ -4909,7 +4909,7 @@ float128 float128_rem( float128 a, float128 b ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); } while ( 0 <= (sbits64) aSig0 ); add128( - aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); + aSig0, aSig1, alternateASig0, alternateASig1, (bits64*)&sigMean0, &sigMean1 ); if ( ( sigMean0 < 0 ) || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { aSig0 = alternateASig0; diff --git a/softfloat/softfloat.cc b/softfloat/softfloat.cc new file mode 100644 index 0000000..c44e828 --- /dev/null +++ b/softfloat/softfloat.cc @@ -0,0 +1 @@ +#include "softfloat.c" diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index eb5303a..fc3f9dc 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -1,259 +1,14 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef unsigned int float32; -typedef unsigned long long float64; -#ifdef FLOATX80 -typedef struct { - unsigned short high; - unsigned long long low; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - unsigned long long high, low; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_up = 2, - float_round_down = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int float_exception_flags; -enum { - float_flag_inexact = 1, - float_flag_divbyzero = 2, - float_flag_underflow = 4, - float_flag_overflow = 8, - float_flag_invalid = 16 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int ); -float64 int32_to_float64( int ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int ); -#endif -float32 int64_to_float32( long long ); -float64 int64_to_float64( long long ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( long long ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( long long ); +#ifdef __cplusplus +extern "C" { #endif -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float32_to_int32( float32 ); -int float32_to_int32_round_to_zero( float32 ); -long long float32_to_int64( float32 ); -long long float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif +#ifndef _SOFTFLOAT_H +#define _SOFTFLOAT_H -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -int float32_eq( float32, float32 ); -int float32_le( float32, float32 ); -int float32_lt( float32, float32 ); -int float32_eq_signaling( float32, float32 ); -int float32_le_quiet( float32, float32 ); -int float32_lt_quiet( float32, float32 ); -int float32_is_signaling_nan( float32 ); +#include "softfloat-header" -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float64_to_int32( float64 ); -int float64_to_int32_round_to_zero( float64 ); -long long float64_to_int64( float64 ); -long long float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); #endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -int float64_eq( float64, float64 ); -int float64_le( float64, float64 ); -int float64_lt( float64, float64 ); -int float64_eq_signaling( float64, float64 ); -int float64_le_quiet( float64, float64 ); -int float64_lt_quiet( float64, float64 ); -int float64_is_signaling_nan( float64 ); -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int floatx80_to_int32( floatx80 ); -int floatx80_to_int32_round_to_zero( floatx80 ); -long long floatx80_to_int64( floatx80 ); -long long floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); +#ifdef __cplusplus +} #endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern int floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -int floatx80_eq( floatx80, floatx80 ); -int floatx80_le( floatx80, floatx80 ); -int floatx80_lt( floatx80, floatx80 ); -int floatx80_eq_signaling( floatx80, floatx80 ); -int floatx80_le_quiet( floatx80, floatx80 ); -int floatx80_lt_quiet( floatx80, floatx80 ); -int floatx80_is_signaling_nan( floatx80 ); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float128_to_int32( float128 ); -int float128_to_int32_round_to_zero( float128 ); -long long float128_to_int64( float128 ); -long long float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -int float128_eq( float128, float128 ); -int float128_le( float128, float128 ); -int float128_lt( float128, float128 ); -int float128_eq_signaling( float128, float128 ); -int float128_le_quiet( float128, float128 ); -int float128_lt_quiet( float128, float128 ); -int float128_is_signaling_nan( float128 ); - -#endif -