diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index bc6293c0b..08b9ee5f2 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4434,7 +4434,7 @@ FP_COMPARE_REG(int dst, int src) addbyte((uint8_t) cpu_state_offset(npxs) + 1); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); if (src) { addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ @@ -4467,7 +4467,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0x9f); /*LAHF*/ addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ @@ -4493,7 +4493,7 @@ FP_COMPARE_MEM(void) addbyte((uint8_t) cpu_state_offset(ST)); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0x66); /*COMISD XMM0, XMM1*/ addbyte(0x0f); addbyte(0x2f); @@ -4501,7 +4501,7 @@ FP_COMPARE_MEM(void) addbyte(0x9f); /*LAHF*/ addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 410ce8e17..c48324c2a 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -2911,7 +2911,7 @@ FP_COMPARE_S(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xd8); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2919,7 +2919,7 @@ FP_COMPARE_S(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -2943,7 +2943,7 @@ FP_COMPARE_S(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xd8); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2951,7 +2951,7 @@ FP_COMPARE_S(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -2980,7 +2980,7 @@ FP_COMPARE_D(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2988,7 +2988,7 @@ FP_COMPARE_D(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3016,7 +3016,7 @@ FP_COMPARE_D(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3024,7 +3024,7 @@ FP_COMPARE_D(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3050,7 +3050,7 @@ FP_COMPARE_IW(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xde); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3058,7 +3058,7 @@ FP_COMPARE_IW(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3082,7 +3082,7 @@ FP_COMPARE_IW(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xde); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3090,7 +3090,7 @@ FP_COMPARE_IW(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3115,7 +3115,7 @@ FP_COMPARE_IL(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xda); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3123,7 +3123,7 @@ FP_COMPARE_IL(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3147,7 +3147,7 @@ FP_COMPARE_IL(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xda); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3155,7 +3155,7 @@ FP_COMPARE_IL(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3250,7 +3250,7 @@ FP_COMPARE_REG(int dst, int src) addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP ST[src][EBP]*/ addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); @@ -3258,7 +3258,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ @@ -3286,7 +3286,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe2); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); if (src) { addbyte(0xdd); /*FLD ST[EBX*8]*/ @@ -3312,7 +3312,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 7514e1f0c..421292c7e 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -648,10 +648,10 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); host_arm64_MOVZ_IMM(block, dest_reg, 0); host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0); host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); } else @@ -690,10 +690,10 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { host_arm64_MOVZ_IMM(block, dest_reg, 0); host_arm64_FCMP_D(block, src_reg_a, src_reg_b); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0); host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); } else diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index 338d3dd54..04b61255b 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -718,9 +718,9 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); host_arm_MOV_IMM(block, dest_reg, 0); host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -758,9 +758,9 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_arm_VCMP_D(block, src_reg_a, src_reg_b); host_arm_MOV_IMM(block, dest_reg, 0); host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index fcab0f3ce..1b82f9fca 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -672,7 +672,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); @@ -720,7 +720,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index 5ef2d97b8..91f2c7ec3 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -677,7 +677,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); @@ -725,7 +725,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index 3ab7be8ac..15a6399e6 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -59,7 +59,7 @@ ropFCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; @@ -71,7 +71,7 @@ ropFCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP(block, ir); @@ -82,7 +82,7 @@ ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP2(block, ir); @@ -269,7 +269,7 @@ ropFUCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; @@ -281,7 +281,7 @@ ropFUCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP(block, ir); @@ -292,7 +292,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP2(block, ir); @@ -328,7 +328,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f codegen_check_seg_read(block, ir, target_seg); \ load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ @@ -344,7 +344,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f codegen_check_seg_read(block, ir, target_seg); \ load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ fpu_POP(block, ir); \ \ @@ -460,7 +460,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ @@ -477,7 +477,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ fpu_POP(block, ir); \ \ @@ -600,7 +600,7 @@ ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 { uop_FP_ENTER(ir); uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index bd03a5558..fc5ba975f 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -34,5 +34,5 @@ if(DYNAREC) codegen_timing_winchip.c codegen_timing_winchip2.c) endif() -add_subdirectory(softfloat) -target_link_libraries(86Box softfloat) +add_subdirectory(softfloat3e) +target_link_libraries(86Box softfloat3e) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 900d3d7e1..ae5b4692a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -21,7 +21,7 @@ #ifndef EMU_CPU_H #define EMU_CPU_H -#include "softfloat/softfloat.h" +#include "softfloat3e/softfloat.h" enum { FPU_NONE, @@ -592,8 +592,6 @@ extern uint32_t eip_msr; extern uint64_t amd_efer; extern uint64_t star; -#define FPU_CW_Reserved_Bits (0xe0c0) - #define cr0 cpu_state.CR0.l #define msw cpu_state.CR0.w extern uint32_t cr2; diff --git a/src/cpu/softfloat/CMakeLists.txt b/src/cpu/softfloat/CMakeLists.txt deleted file mode 100644 index 936157185..000000000 --- a/src/cpu/softfloat/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# -# 86Box A hypervisor and IBM PC system emulator that specializes in -# running old operating systems and software designed for IBM -# PC systems and compatibles from 1981 through fairly recent -# system designs based on the PCI bus. -# -# This file is part of the 86Box distribution. -# -# CMake build script. -# -# Authors: David Hrdlička, -# -# Copyright 2020-2021 David Hrdlička. -# - -add_library(softfloat OBJECT f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc softfloat_poly.cc softfloat.cc softfloat16.cc - softfloat-muladd.cc softfloat-round-pack.cc softfloat-specialize.cc softfloatx80.cc) diff --git a/src/cpu/softfloat/config.h b/src/cpu/softfloat/config.h deleted file mode 100644 index 9e39c2d29..000000000 --- a/src/cpu/softfloat/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef EMU_SF_CONFIG_H -#define EMU_SF_CONFIG_H - -#include - -typedef int8_t flag; -typedef uint8_t uint8; -typedef int8_t int8; -typedef uint16_t uint16; -typedef int16_t int16; -typedef uint32_t uint32; -typedef int32_t int32; -typedef uint64_t uint64; -typedef int64_t int64; - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef uint8_t bits8; -typedef int8_t sbits8; -typedef uint16_t bits16; -typedef int16_t sbits16; -typedef uint32_t bits32; -typedef int32_t sbits32; -typedef uint64_t bits64; -typedef int64_t sbits64; - -typedef uint8_t Bit8u; -typedef int8_t Bit8s; -typedef uint16_t Bit16u; -typedef int16_t Bit16s; -typedef uint32_t Bit32u; -typedef int32_t Bit32s; -typedef uint64_t Bit64u; -typedef int64_t Bit64s; - -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define BX_CONST64(a) a##LL -#define BX_CPP_INLINE static __inline - -#endif /*EMU_SF_CONFIG_H*/ diff --git a/src/cpu/softfloat/softfloat-compare.h b/src/cpu/softfloat/softfloat-compare.h deleted file mode 100644 index 8b9821460..000000000 --- a/src/cpu/softfloat/softfloat-compare.h +++ /dev/null @@ -1,496 +0,0 @@ -/*============================================================================ -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. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_COMPARE_H_ -#define _SOFTFLOAT_COMPARE_H_ - -#include "softfloat.h" - -// ======= float32 ======= // - -typedef int (*float32_compare_method)(float32, float32, struct float_status_t *status); - -// 0x00 -BX_CPP_INLINE int float32_eq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_equal); -} - -// 0x01 -BX_CPP_INLINE int float32_lt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less); -} - -// 0x02 -BX_CPP_INLINE int float32_le_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x03 -BX_CPP_INLINE int float32_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x04 -BX_CPP_INLINE int float32_neq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_equal); -} - -// 0x05 -BX_CPP_INLINE int float32_nlt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_less); -} - -// 0x06 -BX_CPP_INLINE int float32_nle_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x07 -BX_CPP_INLINE int float32_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x08 -BX_CPP_INLINE int float32_eq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x09 -BX_CPP_INLINE int float32_nge_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x0a -BX_CPP_INLINE int float32_ngt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_greater); -} - -// 0x0b -BX_CPP_INLINE int float32_false_quiet(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_quiet(a, b, status); - return 0; -} - -// 0x0c -BX_CPP_INLINE int float32_neq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x0d -BX_CPP_INLINE int float32_ge_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x0e -BX_CPP_INLINE int float32_gt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_greater); -} - -// 0x0f -BX_CPP_INLINE int float32_true_quiet(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_quiet(a, b, status); - return 1; -} - -// 0x10 -BX_CPP_INLINE int float32_eq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_equal); -} - -// 0x11 -BX_CPP_INLINE int float32_lt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less); -} - -// 0x12 -BX_CPP_INLINE int float32_le_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x13 -BX_CPP_INLINE int float32_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x14 -BX_CPP_INLINE int float32_neq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_equal); -} - -// 0x15 -BX_CPP_INLINE int float32_nlt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_less); -} - -// 0x16 -BX_CPP_INLINE int float32_nle_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x17 -BX_CPP_INLINE int float32_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x18 -BX_CPP_INLINE int float32_eq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x19 -BX_CPP_INLINE int float32_nge_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x1a -BX_CPP_INLINE int float32_ngt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_greater); -} - -// 0x1b -BX_CPP_INLINE int float32_false_signalling(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_two(a, b, status); - return 0; -} - -// 0x1c -BX_CPP_INLINE int float32_neq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x1d -BX_CPP_INLINE int float32_ge_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x1e -BX_CPP_INLINE int float32_gt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_greater); -} - -// 0x1f -BX_CPP_INLINE int float32_true_signalling(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_two(a, b, status); - return 1; -} - -// ======= float64 ======= // - -typedef int (*float64_compare_method)(float64, float64, struct float_status_t *status); - -// 0x00 -BX_CPP_INLINE int float64_eq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_equal); -} - -// 0x01 -BX_CPP_INLINE int float64_lt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less); -} - -// 0x02 -BX_CPP_INLINE int float64_le_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x03 -BX_CPP_INLINE int float64_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x04 -BX_CPP_INLINE int float64_neq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_equal); -} - -// 0x05 -BX_CPP_INLINE int float64_nlt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_less); -} - -// 0x06 -BX_CPP_INLINE int float64_nle_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x07 -BX_CPP_INLINE int float64_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x08 -BX_CPP_INLINE int float64_eq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x09 -BX_CPP_INLINE int float64_nge_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x0a -BX_CPP_INLINE int float64_ngt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_greater); -} - -// 0x0b -BX_CPP_INLINE int float64_false_quiet(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_quiet(a, b, status); - return 0; -} - -// 0x0c -BX_CPP_INLINE int float64_neq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x0d -BX_CPP_INLINE int float64_ge_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x0e -BX_CPP_INLINE int float64_gt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_greater); -} - -// 0x0f -BX_CPP_INLINE int float64_true_quiet(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_quiet(a, b, status); - return 1; -} - -// 0x10 -BX_CPP_INLINE int float64_eq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_equal); -} - -// 0x11 -BX_CPP_INLINE int float64_lt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less); -} - -// 0x12 -BX_CPP_INLINE int float64_le_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x13 -BX_CPP_INLINE int float64_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x14 -BX_CPP_INLINE int float64_neq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_equal); -} - -// 0x15 -BX_CPP_INLINE int float64_nlt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_less); -} - -// 0x16 -BX_CPP_INLINE int float64_nle_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x17 -BX_CPP_INLINE int float64_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x18 -BX_CPP_INLINE int float64_eq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x19 -BX_CPP_INLINE int float64_nge_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x1a -BX_CPP_INLINE int float64_ngt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_greater); -} - -// 0x1b -BX_CPP_INLINE int float64_false_signalling(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_two(a, b, status); - return 0; -} - -// 0x1c -BX_CPP_INLINE int float64_neq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x1d -BX_CPP_INLINE int float64_ge_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x1e -BX_CPP_INLINE int float64_gt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_greater); -} - -// 0x1f -BX_CPP_INLINE int float64_true_signalling(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_two(a, b, status); - return 1; -} - -#endif diff --git a/src/cpu/softfloat/softfloat-macros.h b/src/cpu/softfloat/softfloat-macros.h deleted file mode 100644 index cb867bf5d..000000000 --- a/src/cpu/softfloat/softfloat-macros.h +++ /dev/null @@ -1,686 +0,0 @@ -/*============================================================================ -This C source fragment 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 notice) 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. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_MACROS_H_ -#define _SOFTFLOAT_MACROS_H_ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 16, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count) -{ - Bit16u z; - - if (count == 0) { - z = a; - } - else if (count < 16) { - z = (a>>count) | ((a<<((-count) & 15)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count) -{ - Bit32u z; - - if (count == 0) { - z = a; - } - else if (count < 32) { - z = (a>>count) | ((a<<((-count) & 31)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count) -{ - Bit64u z; - - if (count == 0) { - z = a; - } - else if (count < 64) { - z = (a>>count) | ((a << ((-count) & 63)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else { - z1 = ((a0 | a1) != 0); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + (z1 < a1); -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void - sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - (a1 < b1); -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit32u aHigh, aLow, bHigh, bLow; - Bit64u z0, zMiddleA, zMiddleB, z1; - - aLow = (Bit32u) a; - aHigh = (Bit32u)(a>>32); - bLow = (Bit32u) b; - bHigh = (Bit32u)(b>>32); - z1 = ((Bit64u) aLow) * bLow; - zMiddleA = ((Bit64u) aLow) * bHigh; - zMiddleB = ((Bit64u) aHigh) * bLow; - z0 = ((Bit64u) aHigh) * bHigh; - zMiddleA += zMiddleB; - z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += (z1 < zMiddleA); - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateDiv128To64 -static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b) -{ - Bit64u b0, b1; - Bit64u rem0, rem1, term0, term1; - Bit64u z; - - if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); - b0 = b>>32; - z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; - mul64To128(b, z, &term0, &term1); - sub128(a0, a1, term0, term1, &rem0, &rem1); - while (((Bit64s) rem0) < 0) { - z -= BX_CONST64(0x100000000); - b1 = b<<32; - add128(rem0, rem1, b0, b1, &rem0, &rem1); - } - rem0 = (rem0<<32) | (rem1>>32); - z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; - return z; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateSqrt32 -static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a) -{ - static const Bit16u sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const Bit16u sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - Bit32u z; - - int index = (a>>27) & 15; - if (aExp & 1) { - z = 0x4000 + (a>>17) - sqrtOddAdjustments[index]; - z = ((a / z)<<14) + (z<<15); - a >>= 1; - } - else { - z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index]; - z = a / z + z; - z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15); - if (z <= a) return (Bit32u) (((Bit32s) a)>>1); - } - return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1); -} -#endif - -static const int countLeadingZeros8[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 16 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros16(Bit16u a) -{ - int shiftCount = 0; - if (a < 0x100) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>8]; - return shiftCount; -} - -#endif - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros32(Bit32u a) -{ - int shiftCount = 0; - if (a < 0x10000) { - shiftCount += 16; - a <<= 16; - } - if (a < 0x1000000) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>24]; - return shiftCount; -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros64(Bit64u a) -{ - int shiftCount = 0; - if (a < BX_CONST64(0x100000000)) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32((Bit32u)(a)); - return shiftCount; -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count); - z0 = a0>>count; - } - else { - z1 = (count < 128) ? (a0>>(count & 63)) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count) | ((a1<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else if (count < 128) { - z1 = (a0>>(count & 63)) | (((a0<>((-count) & 63)); -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned carry0, carry1; - - z2 = a2 + b2; - carry1 = (z2 < a2); - z1 = a1 + b1; - carry0 = (z1 < a1); - z0 = a0 + b0; - z1 += carry1; - z0 += (z1 < carry1); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void sub192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = (a2 < b2); - z1 = a1 - b1; - borrow0 = (a1 < b1); - z0 = a0 - b0; - z0 -= (z1 < borrow1); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 == b0) && (a1 == b1); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 <= b1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 < b1)); -} - -#endif /* FLOATX80 */ - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128By64To192( - Bit64u a0, - Bit64u a1, - Bit64u b, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2, more1; - - mul64To128(a1, b, &z1, &z2); - mul64To128(a0, b, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128To256( - Bit64u a0, - Bit64u a1, - Bit64u b0, - Bit64u b1, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr, - Bit64u *z3Ptr -) -{ - Bit64u z0, z1, z2, z3; - Bit64u more1, more2; - - mul64To128(a1, b1, &z2, &z3); - mul64To128(a1, b0, &z1, &more2); - add128(z1, more2, 0, z2, &z1, &z2); - mul64To128(a0, b0, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - mul64To128(a0, b1, &more1, &more2); - add128(more1, more2, 0, z2, &more1, &z2); - add128(z0, z1, 0, more1, &z0, &z1); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right -| by 64 _plus_ the number of bits given in `count'. The shifted result is -| at most 128 nonzero bits; these are broken into two 64-bit pieces which are -| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted -| off form a third 64-bit result as follows: The _last_ bit shifted off is -| the most-significant bit of the extra result, and the other 63 bits of the -| extra result are all zero if and only if _all_but_the_last_ bits shifted off -| were all zero. This extra result is stored in the location pointed to by -| `z2Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0', `a1', and `a2' are considered -| to form a fixed-point value with binary point between `a1' and `a2'. This -| fixed-point value is shifted right by the number of bits given in `count', -| and the integer part of the result is returned at the locations pointed to -| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly -| corrupted as described above, and is returned at the location pointed to by -| `z2Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128ExtraRightJamming( - Bit64u a0, - Bit64u a1, - Bit64u a2, - int count, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - int negCount = (-count) & 63; - - if (count == 0) { - z2 = a2; - z1 = a1; - z0 = a0; - } - else { - if (count < 64) { - z2 = a1<>count); - z0 = a0>>count; - } - else { - if (count == 64) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if (count < 128) { - z2 = a0<>(count & 63); - } - else { - z2 = (count == 128) ? a0 : (a0 != 0); - z1 = 0; - } - } - z0 = 0; - } - z2 |= (a2 != 0); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat-muladd.cc b/src/cpu/softfloat/softfloat-muladd.cc deleted file mode 100644 index 7c9fec70e..000000000 --- a/src/cpu/softfloat/softfloat-muladd.cc +++ /dev/null @@ -1,558 +0,0 @@ -/*============================================================================ -This C source 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. -=============================================================================*/ - -/*============================================================================ - * This code is based on QEMU patch by Peter Maydell - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes three single-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - int aIsNaN = float32_is_nan(a); - int bIsNaN = float32_is_nan(b); - - int aIsSignalingNaN = float32_is_signaling_nan(a); - int bIsSignalingNaN = float32_is_signaling_nan(b); - int cIsSignalingNaN = float32_is_signaling_nan(c); - - a |= 0x00400000; - b |= 0x00400000; - c |= 0x00400000; - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) - float_raise(status, float_flag_invalid); - - // operate according to float_first_operand_nan mode - if (aIsSignalingNaN | aIsNaN) { - return a; - } - else { - return (bIsSignalingNaN | bIsNaN) ? b : c; - } -} - -/*---------------------------------------------------------------------------- -| Takes three double-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - int aIsNaN = float64_is_nan(a); - int bIsNaN = float64_is_nan(b); - - int aIsSignalingNaN = float64_is_signaling_nan(a); - int bIsSignalingNaN = float64_is_signaling_nan(b); - int cIsSignalingNaN = float64_is_signaling_nan(c); - - a |= BX_CONST64(0x0008000000000000); - b |= BX_CONST64(0x0008000000000000); - c |= BX_CONST64(0x0008000000000000); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) - float_raise(status, float_flag_invalid); - - // operate according to float_first_operand_nan mode - if (aIsSignalingNaN | aIsNaN) { - return a; - } - else { - return (bIsSignalingNaN | bIsNaN) ? b : c; - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float32 float32_muladd(float32 a, float32 b, float32 c, int flags, struct float_status_t *status) -{ - int aSign, bSign, cSign, zSign; - Bit16s aExp, bExp, cExp, pExp, zExp; - Bit32u aSig, bSig, cSig; - int pInf, pZero, pSign; - Bit64u pSig64, cSig64, zSig64; - Bit32u pSig; - int shiftcount; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - cSig = extractFloat32Frac(c); - cExp = extractFloat32Exp(c); - cSign = extractFloat32Sign(c); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0xff) && aSig) || - ((bExp == 0xff) && bSig) || - ((cExp == 0xff) && cSig)) { - return propagateFloat32MulAddNaN(a, b, c, status); - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - if (cExp == 0) cSig = 0; - } - - int infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) || - (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0)); - - if (infzero) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0xff) || (bExp == 0xff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0xff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - if ((aSig && aExp == 0) || (bSig && bExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat32(cSign, 0xff, 0); - } - - if (pInf) { - if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat32(pSign, 0xff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (get_float_rounding_mode(status) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat32(zSign, 0, 0); - } - /* Exact zero plus a denormal */ - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(cSign, 0, 0); - } - } - /* Zero plus something non-zero */ - return packFloat32(cSign, cExp, cSig); - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat32() takes. - */ - pExp = aExp + bExp - 0x7e; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - pSig64 = (Bit64u)aSig * bSig; - if ((Bit64s)(pSig64 << 1) >= 0) { - pSig64 <<= 1; - pExp--; - } - - zSign = pSign; - - /* Now pSig64 is the significand of the multiply, with the explicit bit in - * position 62. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - pSig = (Bit32u) shift64RightJamming(pSig64, 32); - return roundAndPackFloat32(zSign, pExp - 1, pSig, status); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(cSig, &cExp, &cSig); - } - - cSig64 = (Bit64u)cSig << 39; - cSig64 |= BX_CONST64(0x4000000000000000); - int expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - cSig64 = shift64RightJamming(cSig64, expDiff); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - pSig64 = shift64RightJamming(pSig64, -expDiff); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 62 */ - zSig64 = pSig64 + cSig64; - if ((Bit64s)zSig64 < 0) { - zSig64 = shift64RightJamming(zSig64, 1); - } else { - zExp--; - } - zSig64 = shift64RightJamming(zSig64, 32); - return roundAndPackFloat32(zSign, zExp, zSig64, status); - } else { - /* Subtraction */ - if (expDiff > 0) { - cSig64 = shift64RightJamming(cSig64, expDiff); - zSig64 = pSig64 - cSig64; - zExp = pExp; - } else if (expDiff < 0) { - pSig64 = shift64RightJamming(pSig64, -expDiff); - zSig64 = cSig64 - pSig64; - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (cSig64 < pSig64) { - zSig64 = pSig64 - cSig64; - } else if (pSig64 < cSig64) { - zSig64 = cSig64 - pSig64; - zSign ^= 1; - } else { - /* Exact zero */ - return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat32() but - * starting with the significand in a Bit64u. - */ - shiftcount = countLeadingZeros64(zSig64) - 1; - zSig64 <<= shiftcount; - zExp -= shiftcount; - zSig64 = shift64RightJamming(zSig64, 32); - return roundAndPackFloat32(zSign, zExp, zSig64, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float64 float64_muladd(float64 a, float64 b, float64 c, int flags, struct float_status_t *status) -{ - int aSign, bSign, cSign, zSign; - Bit16s aExp, bExp, cExp, pExp, zExp; - Bit64u aSig, bSig, cSig; - int pInf, pZero, pSign; - Bit64u pSig0, pSig1, cSig0, cSig1, zSig0, zSig1; - int shiftcount; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - cSig = extractFloat64Frac(c); - cExp = extractFloat64Exp(c); - cSign = extractFloat64Sign(c); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0x7ff) && aSig) || - ((bExp == 0x7ff) && bSig) || - ((cExp == 0x7ff) && cSig)) { - return propagateFloat64MulAddNaN(a, b, c, status); - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - if (cExp == 0) cSig = 0; - } - - int infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) || - (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0)); - - if (infzero) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0x7ff) || (bExp == 0x7ff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0x7ff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - if ((aSig && aExp == 0) || (bSig && bExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat64(cSign, 0x7ff, 0); - } - - if (pInf) { - if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat64(pSign, 0x7ff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (get_float_rounding_mode(status) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat64(zSign, 0, 0); - } - /* Exact zero plus a denormal */ - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(cSign, 0, 0); - } - } - /* Zero plus something non-zero */ - return packFloat64(cSign, cExp, cSig); - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat64() takes. - */ - pExp = aExp + bExp - 0x3fe; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - mul64To128(aSig, bSig, &pSig0, &pSig1); - if ((Bit64s)(pSig0 << 1) >= 0) { - shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1); - pExp--; - } - - zSign = pSign; - - /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit - * bit in position 126. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); - return roundAndPackFloat64(zSign, pExp - 1, pSig1, status); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(cSig, &cExp, &cSig); - } - - cSig0 = cSig << 10; - cSig1 = 0; - cSig0 |= BX_CONST64(0x4000000000000000); - int expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 126 */ - add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - if ((Bit64s)zSig0 < 0) { - shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - } else { - zExp--; - } - shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); - return roundAndPackFloat64(zSign, zExp, zSig1, status); - } else { - /* Subtraction */ - if (expDiff > 0) { - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - zExp = pExp; - } else if (expDiff < 0) { - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (lt128(cSig0, cSig1, pSig0, pSig1)) { - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - } else if (lt128(pSig0, pSig1, cSig0, cSig1)) { - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zSign ^= 1; - } else { - /* Exact zero */ - return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat64() but - * starting with the significand in a pair of Bit64u. - */ - if (zSig0) { - shiftcount = countLeadingZeros64(zSig0) - 1; - shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1); - if (zSig1) { - zSig0 |= 1; - } - zExp -= shiftcount; - } else { - shiftcount = countLeadingZeros64(zSig1) - 1; - zSig0 = zSig1 << shiftcount; - zExp -= (shiftcount + 64); - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); - } -} diff --git a/src/cpu/softfloat/softfloat-round-pack.cc b/src/cpu/softfloat/softfloat-round-pack.cc deleted file mode 100644 index 2b3965840..000000000 --- a/src/cpu/softfloat/softfloat-round-pack.cc +++ /dev/null @@ -1,896 +0,0 @@ -/*============================================================================ -This C source 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. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s roundAndPackInt32(int zSign, Bit64u exactAbsZ, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int roundIncrement = 0x40; - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) roundIncrement = 0; - else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) roundIncrement = 0; - } - else { - if (roundingMode == float_round_down) roundIncrement = 0; - } - } - } - int roundBits = (int)(exactAbsZ & 0x7F); - Bit64u absZ = (exactAbsZ + roundIncrement)>>7; - absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - Bit32s z = (Bit32s) absZ; - if (zSign) z = -z; - if ((absZ>>32) || (z && ((z < 0) ^ zSign))) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((absZ << 7) > exactAbsZ) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) -{ - Bit64s z; - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int increment = ((Bit64s) absZ1 < 0); - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) increment = 0; - else { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } - else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - Bit64u exactAbsZ0 = absZ0; - if (increment) { - ++absZ0; - if (absZ0 == 0) goto overflow; - absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); - } - z = absZ0; - if (zSign) z = -z; - if (z && ((z < 0) ^ zSign)) { - overflow: - float_raise(status, float_flag_invalid); - return (Bit64s)(int64_indefinite); - } - if (absZ1) { - float_raise(status, float_flag_inexact); - if (absZ0 > exactAbsZ0) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit unsigned integer corresponding to the -| input. Ordinarily, the fixed-point input is simply rounded to an integer, -| with the inexact exception raised if the input cannot be represented exactly -| as an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int increment = ((Bit64s) absZ1 < 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - increment = 0; - } else if (absZ1) { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - if (increment) { - ++absZ0; - if (absZ0 == 0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); - } - - if (zSign && absZ0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (absZ1) { - float_raise(status, float_flag_inexact); - } - return absZ0; -} - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal half-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr) -{ - int shiftCount = countLeadingZeros16(aSig) - 5; - *zSigPtr = aSig<> 4; - zSigRound &= ~(((roundBits ^ 0x10) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - return packFloat16(zSign, zExp, zSigRound); -} - -#endif - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr) -{ - int shiftCount = countLeadingZeros32(aSig) - 8; - *zSigPtr = aSig<> 7; - zSigRound &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((zSigRound << 7) > zSig) set_float_rounding_up(status); - } - return packFloat32(zSign, zExp, zSigRound); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status) -{ - int shiftCount = countLeadingZeros32(zSig) - 1; - return roundAndPackFloat32(zSign, zExp - shiftCount, zSig<>10; - zSigRound &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((zSigRound << 10) > zSig) set_float_rounding_up(status); - } - return packFloat64(zSign, zExp, zSigRound); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status) -{ - int shiftCount = countLeadingZeros64(zSig) - 1; - return roundAndPackFloat64(zSign, zExp - shiftCount, zSig< zSigExact) set_float_rounding_up(status); - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (roundBits) float_raise(status, float_flag_inexact); - zSigExact = zSig0; - zSig0 += roundIncrement; - if (zSig0 < roundIncrement) { - // Basically scale by shifting right and keep overflow - ++zExp; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - roundIncrement = roundMask + 1; - if (roundNearestEven && (roundBits<<1 == roundIncrement)) - roundMask |= roundIncrement; - zSig0 &= ~roundMask; - if (zSig0 > zSigExact) set_float_rounding_up(status); - if (zSig0 == 0) zExp = 0; - return packFloatx80(zSign, zExp, zSig0); - precision80: - increment = ((Bit64s) zSig1 < 0); - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) increment = 0; - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } - else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - } - if (0x7FFD <= (Bit32u) (zExp - 1)) { - if ((0x7FFE < zExp) - || ((zExp == 0x7FFE) - && (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF)) - && increment)) - { - roundMask = 0; - overflow: - float_raise(status, float_flag_overflow | float_flag_inexact); - if ((roundingMode == float_round_to_zero) - || (zSign && (roundingMode == float_round_up)) - || (! zSign && (roundingMode == float_round_down))) - { - return packFloatx80(zSign, 0x7FFE, ~roundMask); - } - set_float_rounding_up(status); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (zExp <= 0) { - int isTiny = (zExp < 0) || (! increment) - || (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1); - zExp = 0; - if (isTiny) { - if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow))) - float_raise(status, float_flag_underflow); - } - if (zSig1) float_raise(status, float_flag_inexact); - if (roundNearestEven) increment = ((Bit64s) zSig1 < 0); - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - if (increment) { - zSigExact = zSig0++; - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - if (zSig0 > zSigExact) set_float_rounding_up(status); - if ((Bit64s) zSig0 < 0) zExp = 1; - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (zSig1) float_raise(status, float_flag_inexact); - if (increment) { - zSigExact = zSig0++; - if (zSig0 == 0) { - zExp++; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - else { - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - } - if (zSig0 > zSigExact) set_float_rounding_up(status); - } - else { - if (zSig0 == 0) zExp = 0; - } - return packFloatx80(zSign, zExp, zSig0); -} - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - struct float_status_t *round_status = status; - floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); - - // bias unmasked undeflow - if (status->float_exception_flags & ~status->float_exception_masks & float_flag_underflow) { - float_raise(round_status, float_flag_underflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status); - } - - // bias unmasked overflow - if (status->float_exception_flags & ~status->float_exception_masks & float_flag_overflow) { - float_raise(round_status, float_flag_overflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status); - } - - return result; -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0); - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - zExp -= shiftCount; - return - roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr) -{ - int shiftCount; - - if (aSig0 == 0) { - shiftCount = countLeadingZeros64(aSig1) - 15; - if (shiftCount < 0) { - *zSig0Ptr = aSig1 >>(-shiftCount); - *zSig1Ptr = aSig1 << (shiftCount & 63); - } - else { - *zSig0Ptr = aSig1 << shiftCount; - *zSig1Ptr = 0; - } - *zExpPtr = - shiftCount - 63; - } - else { - shiftCount = countLeadingZeros64(aSig0) - 15; - shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr); - *zExpPtr = 1 - shiftCount; - } -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status) -{ - int increment = ((Bit64s) zSig2 < 0); - if (0x7FFD <= (Bit32u) zExp) { - if ((0x7FFD < zExp) - || ((zExp == 0x7FFD) - && eq128(BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1) - && increment)) - { - float_raise(status, float_flag_overflow | float_flag_inexact); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (zExp < 0) { - int isTiny = (zExp < -1) - || ! increment - || lt128(zSig0, zSig1, - BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2); - zExp = 0; - if (isTiny && zSig2) float_raise(status, float_flag_underflow); - increment = ((Bit64s) zSig2 < 0); - } - } - if (zSig2) float_raise(status, float_flag_inexact); - if (increment) { - add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1); - zSig1 &= ~((zSig2 + zSig2 == 0) & 1); - } - else { - if ((zSig0 | zSig1) == 0) zExp = 0; - } - return packFloat128Four(zSign, zExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - Bit64u zSig2; - - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0) - 15; - if (0 <= shiftCount) { - zSig2 = 0; - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2); - } - zExp -= shiftCount; - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -#endif diff --git a/src/cpu/softfloat/softfloat-round-pack.h b/src/cpu/softfloat/softfloat-round-pack.h deleted file mode 100644 index 1422aaea6..000000000 --- a/src/cpu/softfloat/softfloat-round-pack.h +++ /dev/null @@ -1,309 +0,0 @@ -/*============================================================================ -This C source 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. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_ROUND_PACK_H_ -#define _SOFTFLOAT_ROUND_PACK_H_ - -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s roundAndPackInt32(int zSign, Bit64u absZ, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit unsigned integer corresponding to the -| input. Ordinarily, the fixed-point input is simply rounded to an integer, -| with the inexact exception raised if the input cannot be represented exactly -| as an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal half-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper half-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the half-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 14 -| and 13, which is 4 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status); - -#endif - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the single-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 30 -| and 29, which is 7 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the double-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded -| to a subnormal number, and the underflow and inexact exceptions are raised -| if the abstract input cannot be represented exactly as a subnormal double- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 62 -| and 61, which is 10 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| rounded and packed into the extended double-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal extended -| double-precision floating-point number. -| If `roundingPrecision' is 32 or 64, the result is rounded to the same -| number of bits as single or double precision, respectively. Otherwise, the -| result is rounded to the full precision of the extended double-precision -| format. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. The -| handling of underflow and overflow follows the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -#endif // FLOATX80 - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -#endif // FLOAT128 - -#endif diff --git a/src/cpu/softfloat/softfloat-specialize.cc b/src/cpu/softfloat/softfloat-specialize.cc deleted file mode 100644 index bf0d11144..000000000 --- a/src/cpu/softfloat/softfloat-specialize.cc +++ /dev/null @@ -1,187 +0,0 @@ -/*============================================================================ -This C source fragment 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. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status) -{ - int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan(a); - aIsSignalingNaN = float32_is_signaling_nan(a); - bIsNaN = float32_is_nan(b); - bIsSignalingNaN = float32_is_signaling_nan(b); - a |= 0x00400000; - b |= 0x00400000; - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b; - if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a; - return (a < b) ? a : b; - } - else { - return b; - } - } else { - return (aIsSignalingNaN | aIsNaN) ? a : b; - } -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status) -{ - int aIsNaN = float64_is_nan(a); - int aIsSignalingNaN = float64_is_signaling_nan(a); - int bIsNaN = float64_is_nan(b); - int bIsSignalingNaN = float64_is_signaling_nan(b); - a |= BX_CONST64(0x0008000000000000); - b |= BX_CONST64(0x0008000000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b; - if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a; - return (a < b) ? a : b; - } - else { - return b; - } - } else { - return (aIsSignalingNaN | aIsNaN) ? a : b; - } -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aIsNaN = floatx80_is_nan(a); - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsNaN = floatx80_is_nan(b); - int bIsSignalingNaN = floatx80_is_signaling_nan(b); - a.fraction |= BX_CONST64(0xC000000000000000); - b.fraction |= BX_CONST64(0xC000000000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if (a.fraction < b.fraction) return b; - if (b.fraction < a.fraction) return a; - return (a.exp < b.exp) ? a : b; - } - else { - return b; - } -} - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status) -{ - int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - aIsNaN = float128_is_nan(a); - aIsSignalingNaN = float128_is_signaling_nan(a); - bIsNaN = float128_is_nan(b); - bIsSignalingNaN = float128_is_signaling_nan(b); - a.hi |= BX_CONST64(0x0000800000000000); - b.hi |= BX_CONST64(0x0000800000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | !bIsNaN) return a; - returnLargerSignificand: - if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b; - if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a; - return (a.hi < b.hi) ? a : b; - } - else { - return b; - } -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -const float128 float128_default_nan = - packFloat128(float128_default_nan_hi, float128_default_nan_lo); - -#endif /* FLOAT128 */ diff --git a/src/cpu/softfloat/softfloat-specialize.h b/src/cpu/softfloat/softfloat-specialize.h deleted file mode 100644 index 302ce53e4..000000000 --- a/src/cpu/softfloat/softfloat-specialize.h +++ /dev/null @@ -1,789 +0,0 @@ -/*============================================================================ -This C source fragment 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. -=============================================================================*/ - -#ifndef _SOFTFLOAT_SPECIALIZE_H_ -#define _SOFTFLOAT_SPECIALIZE_H_ - -#include "softfloat.h" - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#define int16_indefinite ((Bit16s)0x8000) -#define int32_indefinite ((Bit32s)0x80000000) -#define int64_indefinite BX_CONST64(0x8000000000000000) - -#define uint16_indefinite (0xffff) -#define uint32_indefinite (0xffffffff) -#define uint64_indefinite BX_CONST64(0xffffffffffffffff) - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ - -typedef struct { - int sign; - Bit64u hi, lo; -} commonNaNT; - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated half-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float16 float16_default_nan; - -#define float16_fraction extractFloat16Frac -#define float16_exp extractFloat16Exp -#define float16_sign extractFloat16Sign - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a) -{ - return a & 0x3FF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a) -{ - return (a>>10) & 0x1F; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat16Sign(float16 a) -{ - return a>>15; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig) -{ - return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_nan(float16 a) -{ - return (0xF800 < (Bit16u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_signaling_nan(float16 a) -{ - return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_denormal(float16 a) -{ - return (extractFloat16Exp(a) == 0) && (extractFloat16Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float16 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 float16_denormal_to_zero(float16 a) -{ - if (float16_is_denormal(a)) a &= 0x8000; - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, struct float_status_t *status) -{ - commonNaNT z; - if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>15; - z.lo = 0; - z.hi = ((Bit64u) a)<<54; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the half- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a) -{ - return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54); -} - -#endif - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -extern const float32 float32_negative_inf; -extern const float32 float32_positive_inf; -extern const float32 float32_negative_zero; -extern const float32 float32_positive_zero; -extern const float32 float32_negative_one; -extern const float32 float32_positive_one; -extern const float32 float32_max_float; -extern const float32 float32_min_float; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float32 float32_default_nan; - -#define float32_fraction extractFloat32Frac -#define float32_exp extractFloat32Exp -#define float32_sign extractFloat32Sign - -#define FLOAT32_EXP_BIAS 0x7F - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a) -{ - return a & 0x007FFFFF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a) -{ - return (a>>23) & 0xFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat32Sign(float32 a) -{ - return a>>31; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig) -{ - return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_nan(float32 a) -{ - return (0xFF000000 < (Bit32u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_signaling_nan(float32 a) -{ - return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_denormal(float32 a) -{ - return (extractFloat32Exp(a) == 0) && (extractFloat32Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float32 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 float32_denormal_to_zero(float32 a) -{ - if (float32_is_denormal(a)) a &= 0x80000000; - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, struct float_status_t *status) -{ - commonNaNT z; - if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>31; - z.lo = 0; - z.hi = ((Bit64u) a)<<41; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a) -{ - return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41); -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes single-precision floating-point NaN `a' and returns the appropriate -| NaN result. If `a' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 propagateFloat32NaNOne(float32 a, struct float_status_t *status) -{ - if (float32_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - return a | 0x00400000; -} - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -extern const float64 float64_negative_inf; -extern const float64 float64_positive_inf; -extern const float64 float64_negative_zero; -extern const float64 float64_positive_zero; -extern const float64 float64_negative_one; -extern const float64 float64_positive_one; -extern const float64 float64_max_float; -extern const float64 float64_min_float; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float64 float64_default_nan; - -#define float64_fraction extractFloat64Frac -#define float64_exp extractFloat64Exp -#define float64_sign extractFloat64Sign - -#define FLOAT64_EXP_BIAS 0x3FF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a) -{ - return a & BX_CONST64(0x000FFFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a) -{ - return (Bit16s)(a>>52) & 0x7FF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat64Sign(float64 a) -{ - return (int)(a>>63); -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| double-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig) -{ - return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_nan(float64 a) -{ - return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_signaling_nan(float64 a) -{ - return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_denormal(float64 a) -{ - return (extractFloat64Exp(a) == 0) && (extractFloat64Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float64 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 float64_denormal_to_zero(float64 a) -{ - if (float64_is_denormal(a)) a &= ((Bit64u)(1) << 63); - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, struct float_status_t *status) -{ - commonNaNT z; - if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a>>63); - z.lo = 0; - z.hi = a<<12; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a) -{ - return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12); -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes double-precision floating-point NaN `a' and returns the appropriate -| NaN result. If `a' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 propagateFloat64NaNOne(float64 a, struct float_status_t *status) -{ - if (float64_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - return a | BX_CONST64(0x0008000000000000); -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_exp 0xFFFF -#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) - -#define floatx80_fraction extractFloatx80Frac -#define floatx80_exp extractFloatx80Exp -#define floatx80_sign extractFloatx80Sign - -#define FLOATX80_EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a) -{ - return a.fraction; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a) -{ - return a.exp & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloatx80Sign(floatx80 a) -{ - return a.exp>>15; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig) -{ - floatx80 z; - z.fraction = zSig; - z.exp = (zSign << 15) + zExp; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_nan(floatx80 a) -{ - // return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1); - return ((a.exp & 0x7FFF) == 0x7FFF) && (((Bit64s) (a.fraction<<1)) != 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a) -{ - Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000); - return ((a.exp & 0x7FFF) == 0x7FFF) && - ((Bit64u) (aLow<<1)) && (a.fraction == aLow); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is an -| unsupported; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a) -{ - return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, struct float_status_t *status) -{ - commonNaNT z; - if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a.exp >> 15; - z.lo = 0; - z.hi = a.fraction << 1; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a) -{ - floatx80 z; - z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1); - z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF; - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 propagateFloatx80NaNOne(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - a.fraction |= BX_CONST64(0xC000000000000000); - - return a; -} - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000) -#define float128_default_nan_lo BX_CONST64(0x0000000000000000) - -#define float128_exp extractFloat128Exp - -/*---------------------------------------------------------------------------- -| Returns the least-significant 64 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a) -{ - return a.lo; -} - -/*---------------------------------------------------------------------------- -| Returns the most-significant 48 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a) -{ - return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the quadruple-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a) -{ - return ((Bit32s)(a.hi>>48)) & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat128Sign(float128 a) -{ - return (int)(a.hi >> 63); -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 packFloat128Four(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1) -{ - float128 z; - z.lo = zSig1; - z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0; - return z; -} - -/*---------------------------------------------------------------------------- -| Packs two 64-bit precision integers into into the quadruple-precision -| floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo) -{ - float128 z; - z.lo = zLo; - z.hi = zHi; - return z; -} - -#ifdef _MSC_VER -#define PACK_FLOAT_128(hi,lo) { lo, hi } -#else -#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_nan(float128 a) -{ - return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1)) - && (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_signaling_nan(float128 a) -{ - return (((a.hi>>47) & 0xFFFF) == 0xFFFE) - && (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, struct float_status_t *status) -{ - commonNaNT z; - if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a.hi>>63); - shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a) -{ - float128 z; - shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo); - z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000); - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float128 float128_default_nan; - -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat.cc b/src/cpu/softfloat/softfloat.cc deleted file mode 100644 index 0802089b9..000000000 --- a/src/cpu/softfloat/softfloat.cc +++ /dev/null @@ -1,4012 +0,0 @@ -/*============================================================================ -This C source 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. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#define USE_estimateDiv128To64 -#define USE_estimateSqrt32 -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -const unsigned float_all_exceptions_mask = 0x3f; - -float32 int32_to_float32(Bit32s a, struct float_status_t *status) -{ - if (a == 0) return 0; - if (a == (Bit32s) 0x80000000) return packFloat32(1, 0x9E, 0); - int zSign = (a < 0); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 int32_to_float64(Bit32s a) -{ - if (a == 0) return 0; - int zSign = (a < 0); - Bit32u absA = zSign ? -a : a; - int shiftCount = countLeadingZeros32(absA) + 21; - Bit64u zSig = absA; - return packFloat64(zSign, 0x432 - shiftCount, zSig<> 1, status); - return normalizeRoundAndPackFloat32(0, 0x9C, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit unsigned integer `a' to the -| double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 uint32_to_float64(Bit32u a) -{ - if (a == 0) return 0; - int shiftCount = countLeadingZeros32(a) + 21; - Bit64u zSig = a; - return packFloat64(0, 0x432 - shiftCount, zSig<> 1, status); - return normalizeRoundAndPackFloat64(0, 0x43C, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float32_to_int32(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - if ((aExp == 0xFF) && aSig) aSign = 0; - if (aExp) aSig |= 0x00800000; - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - int shiftCount = 0xAF - aExp; - Bit64u aSig64 = Bit64u(aSig) << 32; - if (0 < shiftCount) aSig64 = shift64RightJamming(aSig64, shiftCount); - return roundAndPackInt32(aSign, aSig64, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float32_to_int32_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit32s z; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0x9E; - if (0 <= shiftCount) { - if (a != 0xCF000000) { - float_raise(status, float_flag_invalid); - } - return (Bit32s)(int32_indefinite); - } - else if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig = (aSig | 0x800000)<<8; - z = aSig>>(-shiftCount); - if ((Bit32u) (aSig<<(shiftCount & 31))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or conversion overflows, the largest positive integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float32_to_uint32_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0x9E; - - if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - else if (0 < shiftCount || aSign) { - float_raise(status, float_flag_invalid); - return uint32_indefinite; - } - - aSig = (aSig | 0x800000)<<8; - Bit32u z = aSig >> (-shiftCount); - if (aSig << (shiftCount & 31)) { - float_raise(status, float_flag_inexact); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s float32_to_int64(float32 a, struct float_status_t *status) -{ - Bit64u aSig64, aSigExtra; - - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - int shiftCount = 0xBE - aExp; - if (shiftCount < 0) { - float_raise(status, float_flag_invalid); - return (Bit64s)(int64_indefinite); - } - if (aExp) aSig |= 0x00800000; - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackInt64(aSign, aSig64, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s float32_to_int64_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit64u aSig64; - Bit64s z; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0xBE; - if (0 <= shiftCount) { - if (a != 0xDF000000) { - float_raise(status, float_flag_invalid); - } - return (Bit64s)(int64_indefinite); - } - else if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>(-shiftCount); - if ((Bit64u) (aSig64<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or the conversion overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float32_to_uint64_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit64u aSig64; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0xBE; - - if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - else if (0 < shiftCount || aSign) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - Bit64u z = aSig64>>(-shiftCount); - if ((Bit64u) (aSig64<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float32_to_uint64(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, shiftCount; - Bit32u aSig; - Bit64u aSig64, aSigExtra; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if ((aSign) && (aExp > 0x7E)) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - shiftCount = 0xBE - aExp; - if (aExp) aSig |= 0x00800000; - - if (shiftCount < 0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackUint64(aSign, aSig64, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float32_to_uint32(float32 a, struct float_status_t *status) -{ - Bit64u val_64 = float32_to_uint64(a, status); - - if (val_64 > 0xffffffff) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return uint32_indefinite; - } - - return (Bit32u) val_64; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return commonNaNToFloat64(float32ToCommonNaN(a, status)); - return packFloat64(aSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat64(aSign, 0, 0); - - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - --aExp; - } - return packFloat64(aSign, aExp + 0x380, ((Bit64u) aSig)<<29); -} - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int(float32 a, Bit8u scale, struct float_status_t *status) -{ - Bit32u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - Bit16s aExp = extractFloat32Exp(a); - scale &= 0xf; - - if ((aExp == 0xFF) && extractFloat32Frac(a)) { - return propagateFloat32NaNOne(a, status); - } - - aExp += scale; // scale the exponent - - if (0x96 <= aExp) { - return a; - } - - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - } - - if (aExp <= 0x7E) { - if ((Bit32u) (a<<1) == 0) return a; - float_raise(status, float_flag_inexact); - int aSign = extractFloat32Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x7E) && extractFloat32Frac(a)) { - return packFloat32(aSign, 0x7F - scale, 0); - } - break; - case float_round_down: - return aSign ? packFloat32(1, 0x7F - scale, 0) : float32_positive_zero; - case float_round_up: - return aSign ? float32_negative_zero : packFloat32(0, 0x7F - scale, 0); - } - return packFloat32(aSign, 0, 0); - } - - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - float32 z = a; - if (roundingMode == float_round_nearest_even) { - z += lastBitMask>>1; - if ((z & roundBitsMask) == 0) z &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloat32Sign(z) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != a) float_raise(status, float_flag_inexact); - return z; -} - -/*---------------------------------------------------------------------------- -| Extracts the fractional portion of single-precision floating-point value `a', -| and returns the result as a single-precision floating-point value. The -| fractional results are precise. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_frc(float32 a, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (aExp >= 0x96) { - return packFloat32(roundingMode == float_round_down, 0, 0); - } - - if (aExp < 0x7F) { - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat32(roundingMode == float_round_down, 0, 0); - - float_raise(status, float_flag_denormal); - if (! float_exception_masked(status, float_flag_underflow)) - float_raise(status, float_flag_underflow); - - if(get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(aSign, 0, 0); - } - } - return a; - } - - Bit32u lastBitMask = 1 << (0x96 - aExp); - Bit32u roundBitsMask = lastBitMask - 1; - - aSig &= roundBitsMask; - aSig <<= 7; - aExp--; - - if (aSig == 0) - return packFloat32(roundingMode == float_round_down, 0, 0); - - return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the exponent portion of single-precision floating-point value 'a', -| and returns the result as a single-precision floating-point value -| representing unbiased integer exponent. The operation is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_getexp(float32 a, struct float_status_t *status) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - return float32_positive_inf; - } - - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return float32_negative_inf; - - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - - return int32_to_float32(aExp - 0x7F, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the mantissa of single-precision floating-point value 'a' and -| returns the result as a single-precision floating-point after applying -| the mantissa interval normalization and sign control. The operation is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - } - return packFloat32(~sign_ctrl & aSign, 0x7F, 0); - } - - if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { - return packFloat32(~sign_ctrl & aSign, 0x7F, 0); - } - - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); -// aExp += 0x7E; - aSig &= 0x7FFFFF; - } - - switch(interv) { - case 0x0: // interval [1,2) - aExp = 0x7F; - break; - case 0x1: // interval [1/2,2) - aExp -= 0x7F; - aExp = 0x7F - (aExp & 0x1); - break; - case 0x2: // interval [1/2,1) - aExp = 0x7E; - break; - case 0x3: // interval [3/4,3/2) - aExp = 0x7F - ((aSig >> 22) & 0x1); - break; - } - - return packFloat32(~sign_ctrl & aSign, aExp, aSig); -} - -/*---------------------------------------------------------------------------- -| Return the result of a floating point scale of the single-precision floating -| point value `a' by multiplying it by 2 power of the single-precision -| floating point value 'b' converted to integral value. If the result cannot -| be represented in single precision, then the proper overflow response (for -| positive scaling operand), or the proper underflow response (for negative -| scaling operand) is issued. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_scalef(float32 a, float32 b, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - Bit32u bSig = extractFloat32Frac(b); - Bit16s bExp = extractFloat32Exp(b); - int bSign = extractFloat32Sign(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - } - - if (aExp == 0xFF) { - if (aSig) { - int aIsSignalingNaN = (aSig & 0x00400000) == 0; - if (aIsSignalingNaN || bExp != 0xFF || bSig) - return propagateFloat32NaN(a, b, status); - - return bSign ? 0 : float32_positive_inf; - } - - if (bExp == 0xFF && bSign) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - return a; - } - - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0xFF && ! bSign) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - return a; - } - float_raise(status, float_flag_denormal); - } - - if ((bExp | bSig) == 0) return a; - - if (bExp == 0xFF) { - if (bSign) return packFloat32(aSign, 0, 0); - return packFloat32(aSign, 0xFF, 0); - } - - if (bExp >= 0x8E) { - // handle obvious overflow/underflow result - return roundAndPackFloat32(aSign, bSign ? -0x7F : 0xFF, aSig, status); - } - - int scale = 0; - - if (bExp <= 0x7E) { - if (bExp == 0) - float_raise(status, float_flag_denormal); - scale = -bSign; - } - else { - int shiftCount = bExp - 0x9E; - bSig = (bSig | 0x800000)<<8; - scale = bSig>>(-shiftCount); - - if (bSign) { - if ((Bit32u) (bSig<<(shiftCount & 31))) scale++; - scale = -scale; - } - - if (scale > 0x200) scale = 0x200; - if (scale < -0x200) scale = -0x200; - } - - if (aExp != 0) { - aSig |= 0x00800000; - } else { - aExp++; - } - - aExp += scale - 1; - aSig <<= 7; - return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - - if (0 < expDiff) { - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= 0x20000000; - - bSig = shift32RightJamming(bSig, expDiff); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= 0x20000000; - - aSig = shift32RightJamming(aSig, -expDiff); - zExp = bExp; - } - else { - if (aExp == 0xFF) { - if (aSig | bSig) return propagateFloat32NaN(a, b, status); - return a; - } - if (aExp == 0) { - zSig = (aSig + bSig) >> 6; - if (aSig | bSig) { - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status) && (extractFloat32Frac(zSig) == zSig)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(zSign, 0, 0); - } - if (! float_exception_masked(status, float_flag_underflow)) { - if (extractFloat32Frac(zSig) == zSig) - float_raise(status, float_flag_underflow); - } - } - return packFloat32(zSign, 0, zSig); - } - zSig = 0x40000000 + aSig + bSig; - return roundAndPackFloat32(zSign, aExp, zSig, status); - } - aSig |= 0x20000000; - zSig = (aSig + bSig)<<1; - --zExp; - if ((Bit32s) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0xFF) { - if (aSig | bSig) return propagateFloat32NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aExp == 0) { - if (aSig | bSig) float_raise(status, float_flag_denormal); - aExp = 1; - bExp = 1; - } - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); - bExpBigger: - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign ^ 1, 0xFF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= 0x40000000; - - aSig = shift32RightJamming(aSig, -expDiff); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= 0x40000000; - - bSig = shift32RightJamming(bSig, expDiff); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add(float32 a, float32 b, struct float_status_t *status) -{ - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - - if (aSign == bSign) { - return addFloat32Sigs(a, b, aSign, status); - } - else { - return subFloat32Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub(float32 a, float32 b, struct float_status_t *status) -{ - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - - if (aSign == bSign) { - return subFloat32Sigs(a, b, aSign, status); - } - else { - return addFloat32Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul(float32 a, float32 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig; - Bit64u zSig64; - Bit32u zSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0xFF) { - if (aSig || ((bExp == 0xFF) && bSig)) - return propagateFloat32NaN(a, b, status); - - if ((bExp | bSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloat32(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x7F; - aSig = (aSig | 0x00800000)<<7; - bSig = (bSig | 0x00800000)<<8; - zSig64 = shift64RightJamming(((Bit64u) aSig) * bSig, 32); - zSig = (Bit32u) zSig64; - if (0 <= (Bit32s) (zSig<<1)) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div(float32 a, float32 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat32(zSign, 0xFF, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloat32(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x7D; - aSig = (aSig | 0x00800000)<<7; - bSig = (bSig | 0x00800000)<<8; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = (((Bit64u) aSig)<<32) / bSig; - if ((zSig & 0x3F) == 0) { - zSig |= ((Bit64u) bSig * zSig != ((Bit64u) aSig)<<32); - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, zExp; - Bit32u aSig, zSig; - Bit64u rem, term; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign) { - if ((aExp | aSig) == 0) return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aExp == 0) { - if (aSig == 0) return 0; - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x7F)>>1) + 0x7E; - aSig = (aSig | 0x00800000)<<8; - zSig = estimateSqrt32(aExp, aSig) + 2; - if ((zSig & 0x7F) <= 5) { - if (zSig < 2) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ((Bit64u) zSig) * zSig; - rem = (((Bit64u) aSig)<<32) - term; - while ((Bit64s) rem < 0) { - --zSig; - rem += (((Bit64u) zSig)<<1) | 1; - } - zSig |= (rem != 0); - } - zSig = shift32RightJamming(zSig, 1); - roundAndPack: - return roundAndPackFloat32(0, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Determine single-precision floating-point number class. -*----------------------------------------------------------------------------*/ - -float_class_t float32_class(float32 a) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if(aExp == 0xFF) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & 0x00400000) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int float32_compare(float32 a, float32 b, int quiet, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - float_class_t aClass = float32_class(a); - float_class_t bClass = float32_class(b); - - if (aClass == float_SNaN || bClass == float_SNaN) { - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal; - - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - if (aSign != bSign) - return (aSign) ? float_relation_less : float_relation_greater; - - if (aSign ^ (a < b)) return float_relation_less; - return float_relation_greater; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| smaller of them. -*----------------------------------------------------------------------------*/ - -float32 float32_min(float32 a, float32 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - return (float32_compare_two(a, b, status) == float_relation_less) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| larger of them. -*----------------------------------------------------------------------------*/ - -float32 float32_max(float32 a, float32 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - return (float32_compare_two(a, b, status) == float_relation_greater) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| smaller/larger of them. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - if (float32_is_nan(a) || float32_is_nan(b)) { - if (float32_is_signaling_nan(a)) { - return propagateFloat32NaNOne(a, status); - } - if (float32_is_signaling_nan(b) ) { - return propagateFloat32NaNOne(b, status); - } - if (! float32_is_nan(b)) { - if (float32_is_denormal(b)) - float_raise(status, float_flag_denormal); - return b; - } - if (! float32_is_nan(a)) { - if (float32_is_denormal(a)) - float_raise(status, float_flag_denormal); - return a; - } - return propagateFloat32NaN(a, b, status); - } - - float32 tmp_a = a, tmp_b = b; - if (is_abs) { - tmp_a &= ~0x80000000; // clear the sign bit - tmp_b &= ~0x80000000; - } - - int aSign = extractFloat32Sign(tmp_a); - int bSign = extractFloat32Sign(tmp_b); - - if (float32_is_denormal(a) || float32_is_denormal(b)) - float_raise(status, float_flag_denormal); - - if (aSign != bSign) { - if (! is_max) { - return aSign ? a : b; - } else { - return aSign ? b : a; - } - } else { - if (! is_max) { - return (aSign ^ (tmp_a < tmp_b)) ? a : b; - } else { - return (aSign ^ (tmp_a < tmp_b)) ? b : a; - } - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float64_to_int32(float64 a, struct float_status_t *status) -{ - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - if ((aExp == 0x7FF) && aSig) aSign = 0; - if (aExp) aSig |= BX_CONST64(0x0010000000000000); - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - int shiftCount = 0x42C - aExp; - if (0 < shiftCount) aSig = shift64RightJamming(aSig, shiftCount); - return roundAndPackInt32(aSign, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float64_to_int32_round_to_zero(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig, savedASig; - Bit32s z; - int shiftCount; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (0x41E < aExp) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - else if (aExp < 0x3FF) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp || aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig |= BX_CONST64(0x0010000000000000); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (Bit32s) aSig; - if (aSign) z = -z; - if ((z < 0) ^ aSign) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if ((aSig<>= shiftCount; - if ((aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or the conversion overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float64_to_uint64_round_to_zero(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig, z; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp < 0x3FE) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - - if (0x43E <= aExp || aSign) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (aExp) aSig |= BX_CONST64(0x0010000000000000); - int shiftCount = aExp - 0x433; - - if (0 <= shiftCount) { - z = aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float64_to_uint32(float64 a, struct float_status_t *status) -{ - Bit64u val_64 = float64_to_uint64(a, status); - - if (val_64 > 0xffffffff) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return uint32_indefinite; - } - - return (Bit32u) val_64; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float64_to_uint64(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, shiftCount; - Bit64u aSig, aSigExtra; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign && (aExp > 0x3FE)) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (aExp) { - aSig |= BX_CONST64(0x0010000000000000); - } - shiftCount = 0x433 - aExp; - if (shiftCount <= 0) { - if (0x43E < aExp) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - aSigExtra = 0; - aSig <<= -shiftCount; - } else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - - return roundAndPackUint64(aSign, aSig, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig; - Bit32u zSig; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) return commonNaNToFloat32(float64ToCommonNaN(a, status)); - return packFloat32(aSign, 0xFF, 0); - } - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_denormal); - } - aSig = shift64RightJamming(aSig, 22); - zSig = (Bit32u) aSig; - if (aExp || zSig) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32(aSign, aExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int(float64 a, Bit8u scale, struct float_status_t *status) -{ - Bit64u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - Bit16s aExp = extractFloat64Exp(a); - scale &= 0xf; - - if ((aExp == 0x7FF) && extractFloat64Frac(a)) { - return propagateFloat64NaNOne(a, status); - } - - aExp += scale; // scale the exponent - - if (0x433 <= aExp) { - return a; - } - - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - } - - if (aExp < 0x3FF) { - if ((Bit64u) (a<<1) == 0) return a; - float_raise(status, float_flag_inexact); - int aSign = extractFloat64Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x3FE) && extractFloat64Frac(a)) { - return packFloat64(aSign, 0x3FF - scale, 0); - } - break; - case float_round_down: - return aSign ? packFloat64(1, 0x3FF - scale, 0) : float64_positive_zero; - case float_round_up: - return aSign ? float64_negative_zero : packFloat64(0, 0x3FF - scale, 0); - } - return packFloat64(aSign, 0, 0); - } - - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - float64 z = a; - if (roundingMode == float_round_nearest_even) { - z += lastBitMask>>1; - if ((z & roundBitsMask) == 0) z &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloat64Sign(z) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != a) float_raise(status, float_flag_inexact); - return z; -} - -/*---------------------------------------------------------------------------- -| Extracts the fractional portion of double-precision floating-point value `a', -| and returns the result as a double-precision floating-point value. The -| fractional results are precise. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_frc(float64 a, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (aExp >= 0x433) { - return packFloat64(roundingMode == float_round_down, 0, 0); - } - - if (aExp < 0x3FF) { - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat64(roundingMode == float_round_down, 0, 0); - - float_raise(status, float_flag_denormal); - if (! float_exception_masked(status, float_flag_underflow)) - float_raise(status, float_flag_underflow); - - if(get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(aSign, 0, 0); - } - } - return a; - } - - Bit64u lastBitMask = BX_CONST64(1) << (0x433 - aExp); - Bit64u roundBitsMask = lastBitMask - 1; - - aSig &= roundBitsMask; - aSig <<= 10; - aExp--; - - if (aSig == 0) - return packFloat64(roundingMode == float_round_down, 0, 0); - - return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the exponent portion of double-precision floating-point value 'a', -| and returns the result as a double-precision floating-point value -| representing unbiased integer exponent. The operation is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_getexp(float64 a, struct float_status_t *status) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - return float64_positive_inf; - } - - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return float64_negative_inf; - - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - - return int32_to_float64(aExp - 0x3FF); -} - -/*---------------------------------------------------------------------------- -| Extracts the mantissa of double-precision floating-point value 'a' and -| returns the result as a double-precision floating-point after applying -| the mantissa interval normalization and sign control. The operation is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - int aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - } - return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); - } - - if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { - return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); - } - - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); -// aExp += 0x3FE; - aSig &= BX_CONST64(0xFFFFFFFFFFFFFFFF); - } - - switch(interv) { - case 0x0: // interval [1,2) - aExp = 0x3FF; - break; - case 0x1: // interval [1/2,2) - aExp -= 0x3FF; - aExp = 0x3FF - (aExp & 0x1); - break; - case 0x2: // interval [1/2,1) - aExp = 0x3FE; - break; - case 0x3: // interval [3/4,3/2) - aExp = 0x3FF - ((aSig >> 51) & 0x1); - break; - } - - return packFloat64(~sign_ctrl & aSign, aExp, aSig); -} - -/*---------------------------------------------------------------------------- -| Return the result of a floating point scale of the double-precision floating -| point value `a' by multiplying it by 2 power of the double-precision -| floating point value 'b' converted to integral value. If the result cannot -| be represented in double precision, then the proper overflow response (for -| positive scaling operand), or the proper underflow response (for negative -| scaling operand) is issued. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_scalef(float64 a, float64 b, struct float_status_t *status) -{ - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - Bit64u bSig = extractFloat64Frac(b); - Bit16s bExp = extractFloat64Exp(b); - int bSign = extractFloat64Sign(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - } - - if (aExp == 0x7FF) { - if (aSig) { - int aIsSignalingNaN = (aSig & BX_CONST64(0x0008000000000000)) == 0; - if (aIsSignalingNaN || bExp != 0x7FF || bSig) - return propagateFloat64NaN(a, b, status); - - return bSign ? 0 : float64_positive_inf; - } - - if (bExp == 0x7FF && bSign) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - return a; - } - - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0x7FF && ! bSign) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - return a; - } - float_raise(status, float_flag_denormal); - } - - if ((bExp | bSig) == 0) return a; - - if (bExp == 0x7FF) { - if (bSign) return packFloat64(aSign, 0, 0); - return packFloat64(aSign, 0x7FF, 0); - } - - if (0x40F <= bExp) { - // handle obvious overflow/underflow result - return roundAndPackFloat64(aSign, bSign ? -0x3FF : 0x7FF, aSig, status); - } - - int scale = 0; - - if (bExp < 0x3FF) { - if (bExp == 0) - float_raise(status, float_flag_denormal); - scale = -bSign; - } - else { - bSig |= BX_CONST64(0x0010000000000000); - int shiftCount = 0x433 - bExp; - Bit64u savedBSig = bSig; - bSig >>= shiftCount; - scale = (Bit32s) bSig; - if (bSign) { - if ((bSig< 0x1000) scale = 0x1000; - if (scale < -0x1000) scale = -0x1000; - } - - if (aExp != 0) { - aSig |= BX_CONST64(0x0010000000000000); - } else { - aExp++; - } - - aExp += scale - 1; - aSig <<= 10; - return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if (0 < expDiff) { - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= BX_CONST64(0x2000000000000000); - - bSig = shift64RightJamming(bSig, expDiff); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= BX_CONST64(0x2000000000000000); - - aSig = shift64RightJamming(aSig, -expDiff); - zExp = bExp; - } - else { - if (aExp == 0x7FF) { - if (aSig | bSig) return propagateFloat64NaN(a, b, status); - return a; - } - if (aExp == 0) { - zSig = (aSig + bSig) >> 9; - if (aSig | bSig) { - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status) && (extractFloat64Frac(zSig) == zSig)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(zSign, 0, 0); - } - if (! float_exception_masked(status, float_flag_underflow)) { - if (extractFloat64Frac(zSig) == zSig) - float_raise(status, float_flag_underflow); - } - } - return packFloat64(zSign, 0, zSig); - } - zSig = BX_CONST64(0x4000000000000000) + aSig + bSig; - return roundAndPackFloat64(zSign, aExp, zSig, status); - } - aSig |= BX_CONST64(0x2000000000000000); - zSig = (aSig + bSig)<<1; - --zExp; - if ((Bit64s) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0x7FF) { - if (aSig | bSig) return propagateFloat64NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aExp == 0) { - if (aSig | bSig) float_raise(status, float_flag_denormal); - aExp = 1; - bExp = 1; - } - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); - bExpBigger: - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign ^ 1, 0x7FF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= BX_CONST64(0x4000000000000000); - - aSig = shift64RightJamming(aSig, -expDiff); - bSig |= BX_CONST64(0x4000000000000000); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= BX_CONST64(0x4000000000000000); - - bSig = shift64RightJamming(bSig, expDiff); - aSig |= BX_CONST64(0x4000000000000000); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add(float64 a, float64 b, struct float_status_t *status) -{ - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - - if (aSign == bSign) { - return addFloat64Sigs(a, b, aSign, status); - } - else { - return subFloat64Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub(float64 a, float64 b, struct float_status_t *status) -{ - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - - if (aSign == bSign) { - return subFloat64Sigs(a, b, aSign, status); - } - else { - return addFloat64Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul(float64 a, float64 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0x7FF) { - if (aSig || ((bExp == 0x7FF) && bSig)) { - return propagateFloat64NaN(a, b, status); - } - if ((bExp | bSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloat64(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FF; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - mul64To128(aSig, bSig, &zSig0, &zSig1); - zSig0 |= (zSig1 != 0); - if (0 <= (Bit64s) (zSig0<<1)) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div(float64 a, float64 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit64u rem0, rem1; - Bit64u term0, term1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat64(zSign, 0x7FF, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloat64(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FD; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64(aSig, 0, bSig); - if ((zSig & 0x1FF) <= 2) { - mul64To128(bSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig |= (rem1 != 0); - } - return roundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, zExp; - Bit64u aSig, zSig, doubleZSig; - Bit64u rem0, rem1, term0, term1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign) { - if ((aExp | aSig) == 0) return packFloat64(aSign, 0, 0); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aExp == 0) { - if (aSig == 0) return 0; - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x3FF)>>1) + 0x3FE; - aSig |= BX_CONST64(0x0010000000000000); - zSig = estimateSqrt32(aExp, (Bit32u)(aSig>>21)); - aSig <<= 9 - (aExp & 1); - zSig = estimateDiv128To64(aSig, 0, zSig<<32) + (zSig<<30); - if ((zSig & 0x1FF) <= 5) { - doubleZSig = zSig<<1; - mul64To128(zSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig; - doubleZSig -= 2; - add128(rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1); - } - zSig |= ((rem0 | rem1) != 0); - } - return roundAndPackFloat64(0, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Determine double-precision floating-point number class -*----------------------------------------------------------------------------*/ - -float_class_t float64_class(float64 a) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - int aSign = extractFloat64Sign(a); - - if(aExp == 0x7FF) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & BX_CONST64(0x0008000000000000)) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) - return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int float64_compare(float64 a, float64 b, int quiet, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - float_class_t aClass = float64_class(a); - float_class_t bClass = float64_class(b); - - if (aClass == float_SNaN || bClass == float_SNaN) { - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal; - - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - if (aSign != bSign) - return (aSign) ? float_relation_less : float_relation_greater; - - if (aSign ^ (a < b)) return float_relation_less; - return float_relation_greater; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| smaller of them. -*----------------------------------------------------------------------------*/ - -float64 float64_min(float64 a, float64 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - return (float64_compare_two(a, b, status) == float_relation_less) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| larger of them. -*----------------------------------------------------------------------------*/ - -float64 float64_max(float64 a, float64 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - return (float64_compare_two(a, b, status) == float_relation_greater) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| smaller/larger of them. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - if (float64_is_nan(a) || float64_is_nan(b)) { - if (float64_is_signaling_nan(a)) { - return propagateFloat64NaNOne(a, status); - } - if (float64_is_signaling_nan(b)) { - return propagateFloat64NaNOne(b, status); - } - if (! float64_is_nan(b)) { - if (float64_is_denormal(b)) - float_raise(status, float_flag_denormal); - return b; - } - if (! float64_is_nan(a)) { - if (float64_is_denormal(a)) - float_raise(status, float_flag_denormal); - return a; - } - return propagateFloat64NaN(a, b, status); - } - - float64 tmp_a = a, tmp_b = b; - if (is_abs) { - tmp_a &= ~BX_CONST64(0x8000000000000000); // clear the sign bit - tmp_b &= ~BX_CONST64(0x8000000000000000); - } - - int aSign = extractFloat64Sign(tmp_a); - int bSign = extractFloat64Sign(tmp_b); - - if (float64_is_denormal(a) || float64_is_denormal(b)) - float_raise(status, float_flag_denormal); - - if (aSign != bSign) { - if (! is_max) { - return aSign ? a : b; - } else { - return aSign ? b : a; - } - } else { - if (! is_max) { - return (aSign ^ (tmp_a < tmp_b)) ? a : b; - } else { - return (aSign ^ (tmp_a < tmp_b)) ? b : a; - } - } -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 int32_to_floatx80(Bit32s a) -{ - if (a == 0) return packFloatx80(0, 0, 0); - int zSign = (a < 0); - Bit32u absA = zSign ? -a : a; - int shiftCount = countLeadingZeros32(absA) + 32; - Bit64u zSig = absA; - return packFloatx80(zSign, 0x403E - shiftCount, zSig< 0x401E) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if (aExp < 0x3FFF) { - if (aExp || aSig) float_raise(status, float_flag_inexact); - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (Bit32s) aSig; - if (aSign) z = -z; - if ((z < 0) ^ aSign) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if ((aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32(floatx80 a, struct float_status_t *status) -{ - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return commonNaNToFloat32(floatx80ToCommonNaN(a, status)); - - return packFloat32(aSign, 0xFF, 0); - } - aSig = shift64RightJamming(aSig, 33); - if (aExp || aSig) aExp -= 0x3F81; - return roundAndPackFloat32(aSign, aExp, (Bit32u) aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64(floatx80 a, struct float_status_t *status) -{ - Bit32s aExp; - Bit64u aSig, zSig; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) { - return commonNaNToFloat64(floatx80ToCommonNaN(a, status)); - } - return packFloat64(aSign, 0x7FF, 0); - } - zSig = shift64RightJamming(aSig, 1); - if (aExp || aSig) aExp -= 0x3C01; - return roundAndPackFloat64(aSign, aExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended double-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int(floatx80 a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign; - Bit64u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - floatx80 z; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - Bit32s aExp = extractFloatx80Exp(a); - Bit64u aSig = extractFloatx80Frac(a); - if (0x403E <= aExp) { - if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) { - return propagateFloatx80NaNOne(a, status); - } - return a; - } - if (aExp < 0x3FFF) { - if (aExp == 0) { - if ((aSig<<1) == 0) return a; - float_raise(status, float_flag_denormal); - } - float_raise(status, float_flag_inexact); - aSign = extractFloatx80Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x3FFE) && (Bit64u) (aSig<<1)) { - set_float_rounding_up(status); - return packFloatx80(aSign, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - break; - case float_round_down: - if (aSign) { - set_float_rounding_up(status); - return packFloatx80(1, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - else { - return packFloatx80(0, 0, 0); - } - case float_round_up: - if (aSign) { - return packFloatx80(1, 0, 0); - } - else { - set_float_rounding_up(status); - return packFloatx80(0, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - } - return packFloatx80(aSign, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - if (roundingMode == float_round_nearest_even) { - z.fraction += lastBitMask>>1; - if ((z.fraction & roundBitsMask) == 0) z.fraction &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloatx80Sign(z) ^ (roundingMode == float_round_up)) - z.fraction += roundBitsMask; - } - z.fraction &= ~roundBitsMask; - if (z.fraction == 0) { - z.exp++; - z.fraction = BX_CONST64(0x8000000000000000); - } - if (z.fraction != a.fraction) { - float_raise(status, float_flag_inexact); - if (z.fraction > a.fraction || z.exp > a.exp) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - return propagateFloatx80NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp == 0) && bSig) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, bExp, bSig, 0, status); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, aExp, aSig, 0, status); - - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - Bit32s expDiff = aExp - bExp; - zExp = aExp; - if (0 < expDiff) { - shift64ExtraRightJamming(bSig, 0, expDiff, &bSig, &zSig1); - } - else if (expDiff < 0) { - shift64ExtraRightJamming(aSig, 0, -expDiff, &aSig, &zSig1); - zExp = bExp; - } - else { - zSig0 = aSig + bSig; - zSig1 = 0; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ((Bit64s) zSig0 < 0) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= BX_CONST64(0x8000000000000000); - zExp++; - roundAndPack: - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign ^ 1, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0) { - if (bSig) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign ^ 1, bExp, bSig, 0, status); - } - return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign ^ 1, bExp, bSig, 0, status); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, aExp, aSig, 0, status); - - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - Bit32s expDiff = aExp - bExp; - if (0 < expDiff) { - shift128RightJamming(bSig, 0, expDiff, &bSig, &zSig1); - goto aBigger; - } - if (expDiff < 0) { - shift128RightJamming(aSig, 0, -expDiff, &aSig, &zSig1); - goto bBigger; - } - zSig1 = 0; - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); - bBigger: - sub128(bSig, 0, aSig, zSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aBigger: - sub128(aSig, 0, bSig, zSig1, &zSig0, &zSig1); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aSign == bSign) - return addFloatx80Sigs(a, b, aSign, status); - else - return subFloatx80Sigs(a, b, aSign, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aSign == bSign) - return subFloatx80Sigs(a, b, aSign, status); - else - return addFloatx80Sigs(a, b, aSign, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - invalid: - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - return propagateFloatx80NaN(a, b, status); - } - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128(aSig, bSig, &zSig0, &zSig1); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - Bit64u rem0, rem1, rem2, term0, term1, term2; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if (bSig <= aSig) { - shift128Right(aSig, 0, 1, &aSig, &rem1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig, rem1, bSig); - mul64To128(bSig, zSig0, &term0, &term1); - sub128(aSig, rem1, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig0; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, bSig); - if ((Bit64u) (zSig1<<1) <= 8) { - mul64To128(bSig, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - while ((Bit64s) rem1 < 0) { - --zSig1; - add128(rem1, rem2, 0, bSig, &rem1, &rem2); - } - zSig1 |= ((rem1 | rem2) != 0); - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt(floatx80 a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign; - Bit32s aExp, zExp; - Bit64u aSig0, aSig1, zSig0, zSig1, doubleZSig0; - Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) return propagateFloatx80NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (aSign) { - if ((aExp | aSig0) == 0) return a; - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (aExp == 0) { - if (aSig0 == 0) return packFloatx80(0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - zExp = ((aExp - 0x3FFF)>>1) + 0x3FFF; - zSig0 = estimateSqrt32(aExp, aSig0>>32); - shift128Right(aSig0, 0, 2 + (aExp & 1), &aSig0, &aSig1); - zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0<<32) + (zSig0<<30); - doubleZSig0 = zSig0<<1; - mul64To128(zSig0, zSig0, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig0; - doubleZSig0 -= 2; - add128(rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0); - if ((zSig1 & BX_CONST64(0x3FFFFFFFFFFFFFFF)) <= 5) { - if (zSig1 == 0) zSig1 = 1; - mul64To128(doubleZSig0, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - mul64To128(zSig1, zSig1, &term2, &term3); - sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3); - while ((Bit64s) rem1 < 0) { - --zSig1; - shortShift128Left(0, zSig1, 1, &term2, &term3); - term3 |= 1; - term2 |= doubleZSig0; - add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shortShift128Left(0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80(get_float_rounding_precision(status), - 0, zExp, zSig0, zSig1, status); -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128(floatx80 a, struct float_status_t *status) -{ - Bit64u zSig0, zSig1; - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) - return commonNaNToFloat128(floatx80ToCommonNaN(a, status)); - - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - return packFloat128Four(aSign, aExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80(float128 a, struct float_status_t *status) -{ - Bit32s aExp; - Bit64u aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - int aSign = extractFloat128Sign(a); - - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return commonNaNToFloatx80(float128ToCommonNaN(a, status)); - - return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloatx80(aSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - else aSig0 |= BX_CONST64(0x0001000000000000); - - shortShift128Left(aSig0, aSig1, 15, &aSig0, &aSig1); - return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point value `a' and quadruple-precision floating point value `b'. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2; - int aSign, bSign, zSign; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - invalid: - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig0 = extractFloat128Frac0(b); - bSig1 = extractFloat128Frac1(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (bSig0 | bSig1))) - { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); - return propagateFloatx80NaN(a, r, status); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); - return propagateFloatx80NaN(a, r, status); - } - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp == 0) && (bSig0 | bSig1)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - else bSig0 |= BX_CONST64(0x0001000000000000); - - zExp = aExp + bExp - 0x3FFE; - shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1); - mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) -{ - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - Bit32s expDiff; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - expDiff = aExp - bExp; - - if (0 < expDiff) { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - return a; - } - if (bExp == 0) --expDiff; - else bSig0 |= BX_CONST64(0x0001000000000000); - shift128ExtraRightJamming(bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) ++expDiff; - else aSig0 |= BX_CONST64(0x0001000000000000); - shift128ExtraRightJamming(aSig0, aSig1, 0, -expDiff, &aSig0, &aSig1, &zSig2); - zExp = bExp; - } - else { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) - return propagateFloat128NaN(a, b, status); - - return a; - } - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - if (aExp == 0) return packFloat128Four(zSign, 0, zSig0, zSig1); - zSig2 = 0; - zSig0 |= BX_CONST64(0x0002000000000000); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= BX_CONST64(0x0001000000000000); - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - --zExp; - if (zSig0 < BX_CONST64(0x0002000000000000)) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); - roundAndPack: - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) -{ - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - Bit32s expDiff; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - - expDiff = aExp - bExp; - shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1); - shortShift128Left(bSig0, bSig1, 14, &bSig0, &bSig1); - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) - return propagateFloat128NaN(a, b, status); - - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - if (bSig0 < aSig0) goto aBigger; - if (aSig0 < bSig0) goto bBigger; - if (bSig1 < aSig1) goto aBigger; - if (aSig1 < bSig1) goto bBigger; - return packFloat128(0, 0); - - bExpBigger: - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign ^ 1, 0x7FFF, 0, 0); - } - if (aExp == 0) ++expDiff; - else { - aSig0 |= BX_CONST64(0x4000000000000000); - } - shift128RightJamming(aSig0, aSig1, - expDiff, &aSig0, &aSig1); - bSig0 |= BX_CONST64(0x4000000000000000); - bBigger: - sub128(bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - return a; - } - if (bExp == 0) --expDiff; - else { - bSig0 |= BX_CONST64(0x4000000000000000); - } - shift128RightJamming(bSig0, bSig1, expDiff, &bSig0, &bSig1); - aSig0 |= BX_CONST64(0x4000000000000000); - aBigger: - sub128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add(float128 a, float128 b, struct float_status_t *status) -{ - int aSign = extractFloat128Sign(a); - int bSign = extractFloat128Sign(b); - - if (aSign == bSign) { - return addFloat128Sigs(a, b, aSign, status); - } - else { - return subFloat128Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub(float128 a, float128 b, struct float_status_t *status) -{ - int aSign = extractFloat128Sign(a); - int bSign = extractFloat128Sign(b); - - if (aSign == bSign) { - return subFloat128Sigs(a, b, aSign, status); - } - else { - return addFloat128Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul(float128 a, float128 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { - return propagateFloat128NaN(a, b, status); - } - if ((bExp | bSig0 | bSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - if ((aExp | aSig0 | aSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= BX_CONST64(0x0001000000000000); - shortShift128Left(bSig0, bSig1, 16, &bSig0, &bSig1); - mul128To256(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); - add128(zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1); - zSig2 |= (zSig3 != 0); - if (BX_CONST64(0x0002000000000000) <= zSig0) { - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); - ++zExp; - } - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div(float128 a, float128 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign, 0, 0, 0); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) { - if ((aExp | aSig0 | aSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | BX_CONST64(0x0001000000000000), aSig1, 15, &aSig0, &aSig1); - shortShift128Left( - bSig0 | BX_CONST64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1); - if (le128(bSig0, bSig1, aSig0, aSig1)) { - shift128Right(aSig0, aSig1, 1, &aSig0, &aSig1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig0, aSig1, bSig0); - mul128By64To192(bSig0, bSig1, zSig0, &term0, &term1, &term2); - sub192(aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2); - while ((Bit64s) rem0 < 0) { - --zSig0; - add192(rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2); - } - zSig1 = estimateDiv128To64(rem1, rem2, bSig0); - if ((zSig1 & 0x3FFF) <= 4) { - mul128By64To192(bSig0, bSig1, zSig1, &term1, &term2, &term3); - sub192(rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3); - while ((Bit64s) rem1 < 0) { - --zSig1; - add192(rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shift128ExtraRightJamming(zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2); - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit two's complement integer `a' to -| the quadruple-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 int64_to_float128(Bit64s a) -{ - Bit64u zSig0, zSig1; - - if (a == 0) return packFloat128Four(0, 0, 0, 0); - int zSign = (a < 0); - Bit64u absA = zSign ? - a : a; - Bit8u shiftCount = countLeadingZeros64(absA) + 49; - Bit32s zExp = 0x406E - shiftCount; - if (64 <= shiftCount) { - zSig1 = 0; - zSig0 = absA; - shiftCount -= 64; - } - else { - zSig1 = absA; - zSig0 = 0; - } - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - return packFloat128Four(zSign, zExp, zSig0, zSig1); -} - -#endif diff --git a/src/cpu/softfloat/softfloat.h b/src/cpu/softfloat/softfloat.h deleted file mode 100644 index 1d1b0f08f..000000000 --- a/src/cpu/softfloat/softfloat.h +++ /dev/null @@ -1,488 +0,0 @@ -/*============================================================================ -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. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "config.h" /* generated by configure script from config.h.in */ - -#ifndef _SOFTFLOAT_H_ -#define _SOFTFLOAT_H_ - -#define FLOAT16 -#define FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -#ifdef FLOAT16 -typedef Bit16u float16; -#endif -typedef Bit32u float32; -typedef Bit64u float64; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point class. -*----------------------------------------------------------------------------*/ -typedef enum { - float_zero, - float_SNaN, - float_QNaN, - float_negative_inf, - float_positive_inf, - float_denormal, - float_normalized -} float_class_t; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point NaN operands handling mode. -*----------------------------------------------------------------------------*/ -enum float_nan_handling_mode_t { - float_larger_significand_nan = 0, // this mode used by x87 FPU - float_first_operand_nan = 1 // this mode used by SSE -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum float_round_t { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -enum float_exception_flag_t { - float_flag_invalid = 0x01, - float_flag_denormal = 0x02, - float_flag_divbyzero = 0x04, - float_flag_overflow = 0x08, - float_flag_underflow = 0x10, - float_flag_inexact = 0x20 -}; - -extern const unsigned float_all_exceptions_mask; - -#ifdef FLOATX80 -#define RAISE_SW_C1 0x0200 -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point ordering relations -*----------------------------------------------------------------------------*/ -enum { - float_relation_less = -1, - float_relation_equal = 0, - float_relation_greater = 1, - float_relation_unordered = 2 -}; - -/*---------------------------------------------------------------------------- -| Options to indicate which negations to perform in float*_muladd() -| Using these differs from negating an input or output before calling -| the muladd function in that this means that a NaN doesn't have its -| sign bit inverted before it is propagated. -*----------------------------------------------------------------------------*/ -enum { - float_muladd_negate_c = 1, - float_muladd_negate_product = 2, - float_muladd_negate_result = float_muladd_negate_c | float_muladd_negate_product -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point status structure. -*----------------------------------------------------------------------------*/ -struct float_status_t -{ -#ifdef FLOATX80 - int float_rounding_precision; /* floatx80 only */ -#endif - int float_rounding_mode; - int float_exception_flags; - int float_exception_masks; - int float_suppress_exception; - int float_nan_handling_mode; /* flag register */ - int flush_underflow_to_zero; /* flag register */ - int denormals_are_zeros; /* flag register */ -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void float_raise(struct float_status_t *status, int flags) -{ - status->float_exception_flags |= flags; -} - -/*---------------------------------------------------------------------------- -| Returns raised IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_exception_flags(const struct float_status_t *status) -{ - return status->float_exception_flags & ~status->float_suppress_exception; -} - -/*---------------------------------------------------------------------------- -| Routine to check if any or all of the software IEC/IEEE floating-point -| exceptions are masked. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float_exception_masked(const struct float_status_t *status, int flag) -{ - return status->float_exception_masks & flag; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point rounding mode specified by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_rounding_mode(const struct float_status_t *status) -{ - return status->float_rounding_mode; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point precision (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE int get_float_rounding_precision(const struct float_status_t *status) -{ - return status->float_rounding_precision; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns current floating point NaN operands handling mode specified -| by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_nan_handling_mode(const struct float_status_t *status) -{ - return status->float_nan_handling_mode; -} - -/*---------------------------------------------------------------------------- -| Raise floating point precision lost up flag (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE void set_float_rounding_up(struct float_status_t *status) -{ - status->float_exception_flags |= RAISE_SW_C1; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the feature is supported; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_denormals_are_zeros(const struct float_status_t *status) -{ - return status->denormals_are_zeros; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the feature is supported; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_flush_underflow_to_zero(const struct float_status_t *status) -{ - return status->flush_underflow_to_zero; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32(Bit32s, struct float_status_t *status); -float64 int32_to_float64(Bit32s); -float32 int64_to_float32(Bit64s, struct float_status_t *status); -float64 int64_to_float64(Bit64s, struct float_status_t *status); - -float32 uint32_to_float32(Bit32u, struct float_status_t *status); -float64 uint32_to_float64(Bit32u); -float32 uint64_to_float32(Bit64u, struct float_status_t *status); -float64 uint64_to_float64(Bit64u, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -Bit32s float32_to_int32(float32, struct float_status_t *status); -Bit32s float32_to_int32_round_to_zero(float32, struct float_status_t *status); -Bit64s float32_to_int64(float32, struct float_status_t *status); -Bit64s float32_to_int64_round_to_zero(float32, struct float_status_t *status); -Bit32u float32_to_uint32(float32, struct float_status_t *status); -Bit32u float32_to_uint32_round_to_zero(float32, struct float_status_t *status); -Bit64u float32_to_uint64(float32, struct float_status_t *status); -Bit64u float32_to_uint64_round_to_zero(float32, struct float_status_t *status); -float64 float32_to_float64(float32, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int(float32, Bit8u scale, struct float_status_t *status); -float32 float32_add(float32, float32, struct float_status_t *status); -float32 float32_sub(float32, float32, struct float_status_t *status); -float32 float32_mul(float32, float32, struct float_status_t *status); -float32 float32_div(float32, float32, struct float_status_t *status); -float32 float32_sqrt(float32, struct float_status_t *status); -float32 float32_frc(float32, struct float_status_t *status); -float32 float32_muladd(float32, float32, float32, int flags, struct float_status_t *status); -float32 float32_scalef(float32, float32, struct float_status_t *status); -int float32_compare(float32, float32, int quiet, struct float_status_t *status); - -BX_CPP_INLINE float32 float32_round_to_int_one(float32 a, struct float_status_t *status) -{ - return float32_round_to_int(a, 0, status); -} - -BX_CPP_INLINE float32 float32_fmadd(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, 0, status); -} - -BX_CPP_INLINE float32 float32_fmsub(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_c, status); -} - -BX_CPP_INLINE float32 float32_fnmadd(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_product, status); -} - -BX_CPP_INLINE float32 float32_fnmsub(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_result, status); -} - -BX_CPP_INLINE int float32_compare_two(float32 a, float32 b, struct float_status_t *status) -{ - return float32_compare(a, b, 0, status); -} - -BX_CPP_INLINE int float32_compare_quiet(float32 a, float32 b, struct float_status_t *status) -{ - return float32_compare(a, b, 1, status); -} - -float_class_t float32_class(float32); - -float32 float32_min(float32 a, float32 b, struct float_status_t *status); -float32 float32_max(float32 a, float32 b, struct float_status_t *status); - -float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status); -float32 float32_getexp(float32 a, struct float_status_t *status); -float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -Bit32s float64_to_int32(float64, struct float_status_t *status); -Bit32s float64_to_int32_round_to_zero(float64, struct float_status_t *status); -Bit64s float64_to_int64(float64, struct float_status_t *status); -Bit64s float64_to_int64_round_to_zero(float64, struct float_status_t *status); -Bit32u float64_to_uint32(float64, struct float_status_t *status); -Bit32u float64_to_uint32_round_to_zero(float64, struct float_status_t *status); -Bit64u float64_to_uint64(float64, struct float_status_t *status); -Bit64u float64_to_uint64_round_to_zero(float64, struct float_status_t *status); -float32 float64_to_float32(float64, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int(float64, Bit8u scale, struct float_status_t *status); -float64 float64_add(float64, float64, struct float_status_t *status); -float64 float64_sub(float64, float64, struct float_status_t *status); -float64 float64_mul(float64, float64, struct float_status_t *status); -float64 float64_div(float64, float64, struct float_status_t *status); -float64 float64_sqrt(float64, struct float_status_t *status); -float64 float64_frc(float64, struct float_status_t *status); -float64 float64_muladd(float64, float64, float64, int flags, struct float_status_t *status); -float64 float64_scalef(float64, float64, struct float_status_t *status); -int float64_compare(float64, float64, int quiet, struct float_status_t *status); - -BX_CPP_INLINE float64 float64_round_to_int_one(float64 a, struct float_status_t *status) -{ - return float64_round_to_int(a, 0, status); -} - -BX_CPP_INLINE float64 float64_fmadd(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, 0, status); -} - -BX_CPP_INLINE float64 float64_fmsub(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_c, status); -} - -BX_CPP_INLINE float64 float64_fnmadd(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_product, status); -} - -BX_CPP_INLINE float64 float64_fnmsub(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_result, status); -} - -BX_CPP_INLINE int float64_compare_two(float64 a, float64 b, struct float_status_t *status) -{ - return float64_compare(a, b, 0, status); -} - -BX_CPP_INLINE int float64_compare_quiet(float64 a, float64 b, struct float_status_t *status) -{ - return float64_compare(a, b, 1, status); -} - -float_class_t float64_class(float64); - -float64 float64_min(float64 a, float64 b, struct float_status_t *status); -float64 float64_max(float64 a, float64 b, struct float_status_t *status); - -float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status); -float64 float64_getexp(float64 a, struct float_status_t *status); -float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv); - -#ifdef FLOAT16 -float32 float16_to_float32(float16, struct float_status_t *status); -float16 float32_to_float16(float32, struct float_status_t *status); - -float_class_t float16_class(float16); -#endif - -#ifdef FLOATX80 -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ - -#ifdef BX_BIG_ENDIAN -typedef struct floatx80 { // leave alignment to compiler - Bit16u exp; - Bit64u fraction; -}; floatx80 -#else -typedef struct floatx80 { - Bit64u fraction; - Bit16u exp; -} floatx80; -#endif - -#ifdef __cplusplus -extern "C" { -#endif -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -floatx80 int32_to_floatx80(Bit32s); -floatx80 int64_to_floatx80(Bit64s); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -floatx80 float32_to_floatx80(float32, struct float_status_t *status); -floatx80 float64_to_floatx80(float64, struct float_status_t *status); - -Bit32s floatx80_to_int32(floatx80, struct float_status_t *status); -Bit32s floatx80_to_int32_round_to_zero(floatx80, struct float_status_t *status); -Bit64s floatx80_to_int64(floatx80, struct float_status_t *status); -Bit64s floatx80_to_int64_round_to_zero(floatx80, struct float_status_t *status); - -float32 floatx80_to_float32(floatx80, struct float_status_t *status); -float64 floatx80_to_float64(floatx80, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int(floatx80, struct float_status_t *status); -floatx80 floatx80_add(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_sub(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_mul(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_div(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_sqrt(floatx80, struct float_status_t *status); - -float_class_t floatx80_class(floatx80); -#ifdef __cplusplus -} -#endif -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -#ifdef BX_BIG_ENDIAN -typedef struct float128 { - Bit64u hi, lo; -} float128; -#else -typedef struct float128 { - Bit64u lo, hi; -} float128; -#endif - -#ifdef __cplusplus -extern "C" { -#endif -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -float128 floatx80_to_float128(floatx80 a, struct float_status_t *status); -floatx80 float128_to_floatx80(float128 a, struct float_status_t *status); - -float128 int64_to_float128(Bit64s a); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_add(float128 a, float128 b, struct float_status_t *status); -float128 float128_sub(float128 a, float128 b, struct float_status_t *status); -float128 float128_mul(float128 a, float128 b, struct float_status_t *status); -float128 float128_div(float128 a, float128 b, struct float_status_t *status); -#ifdef __cplusplus -} -#endif -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat16.cc b/src/cpu/softfloat/softfloat16.cc deleted file mode 100644 index 8c17d3a86..000000000 --- a/src/cpu/softfloat/softfloat16.cc +++ /dev/null @@ -1,129 +0,0 @@ -/*============================================================================ -This C source 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. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" - -#ifdef FLOAT16 - -#include "softfloat-round-pack.h" -#include "softfloat-specialize.h" -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Determine half-precision floating-point number class -*----------------------------------------------------------------------------*/ - -float_class_t float16_class(float16 a) -{ - Bit16s aExp = extractFloat16Exp(a); - Bit16u aSig = extractFloat16Frac(a); - int aSign = extractFloat16Sign(a); - - if(aExp == 0x1F) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & 0x200) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float16_to_float32(float16 a, struct float_status_t *status) -{ - Bit16u aSig = extractFloat16Frac(a); - Bit16s aExp = extractFloat16Exp(a); - int aSign = extractFloat16Sign(a); - - if (aExp == 0x1F) { - if (aSig) return commonNaNToFloat32(float16ToCommonNaN(a, status)); - return packFloat32(aSign, 0xFF, 0); - } - if (aExp == 0) { - // ignore denormals_are_zeros flag - if (aSig == 0) return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat16Subnormal(aSig, &aExp, &aSig); - --aExp; - } - - return packFloat32(aSign, aExp + 0x70, ((Bit32u) aSig)<<13); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the half-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float16 float32_to_float16(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return commonNaNToFloat16(float32ToCommonNaN(a, status)); - return packFloat16(aSign, 0x1F, 0); - } - if (aExp == 0) { - if (get_denormals_are_zeros(status)) aSig = 0; - if (aSig == 0) return packFloat16(aSign, 0, 0); - float_raise(status, float_flag_denormal); - } - - aSig = shift32RightJamming(aSig, 9); - Bit16u zSig = (Bit16u) aSig; - if (aExp || zSig) { - zSig |= 0x4000; - aExp -= 0x71; - } - - return roundAndPackFloat16(aSign, aExp, zSig, status); -} - -#endif diff --git a/src/cpu/softfloat/softfloatx80.cc b/src/cpu/softfloat/softfloatx80.cc deleted file mode 100644 index fc2409601..000000000 --- a/src/cpu/softfloat/softfloatx80.cc +++ /dev/null @@ -1,384 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -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. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include -#include -#include <86box/86box.h> -#include "../cpu.h" - -#include "softfloatx80.h" -#include "softfloat-round-pack.h" -#include "softfloat-macros.h" - -const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); -const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); -const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); -const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); -const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc)); -const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); -const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799)); -const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac)); -const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000)); - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -const float32 float32_negative_inf = 0xff800000; -const float32 float32_positive_inf = 0x7f800000; -const float32 float32_negative_zero = 0x80000000; -const float32 float32_positive_zero = 0x00000000; -const float32 float32_negative_one = 0xbf800000; -const float32 float32_positive_one = 0x3f800000; -const float32 float32_max_float = 0x7f7fffff; -const float32 float32_min_float = 0xff7fffff; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -const float32 float32_default_nan = 0xffc00000; - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000); -const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000); -const float64 float64_negative_zero = BX_CONST64(0x8000000000000000); -const float64 float64_positive_zero = BX_CONST64(0x0000000000000000); -const float64 float64_negative_one = BX_CONST64(0xbff0000000000000); -const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000); -const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff); -const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic - which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit16s floatx80_to_int16(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); - return int16_indefinite; - } - - Bit32s v32 = floatx80_to_int32(a, status); - - if ((v32 > 32767) || (v32 < -32768)) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN or the conversion overflows, the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit16s floatx80_to_int16_round_to_zero(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); - return int16_indefinite; - } - - Bit32s v32 = floatx80_to_int32_round_to_zero(a, status); - - if ((v32 > 32767) || (v32 < -32768)) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} - -/*---------------------------------------------------------------------------- -| Separate the source extended double-precision floating point value `a' -| into its exponent and significand, store the significant back to the -| 'a' and return the exponent. The operation performed is a superset of -| the IEC/IEEE recommended logb(x) function. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit64u aSig = extractFloatx80Frac(*a); - Bit32s aExp = extractFloatx80Exp(*a); - int aSign = extractFloatx80Sign(*a); - - if (floatx80_is_unsupported(*a)) - { - float_raise(status, float_flag_invalid); - *a = floatx80_default_nan; - return *a; - } - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - { - *a = propagateFloatx80NaNOne(*a, status); - return *a; - } - return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) - { - if (aSig == 0) { - float_raise(status, float_flag_divbyzero); - *a = packFloatx80(aSign, 0, 0); - return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - a->exp = (aSign << 15) + 0x3FFF; - a->fraction = aSig; - return int32_to_floatx80(aExp - 0x3FFF); -} - -/*---------------------------------------------------------------------------- -| Scales extended double-precision floating-point value in operand `a' by -| value `b'. The function truncates the value in the second operand 'b' to -| an integral value and adds that value to the exponent of the operand 'a'. -| The operation performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp; - Bit64u aSig, bSig; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); - } - if ((bExp == 0x7FFF) && bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if ((aExp | aSig) == 0) { - if (! bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - return a; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - if (bSign) return packFloatx80(aSign, 0, 0); - return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - if (aSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - if (bExp < 0x3FFF) - return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status); - } - if (bExp == 0) { - if (bSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - if (bExp > 0x400E) { - /* generate appropriate overflow/underflow */ - return roundAndPackFloatx80(80, aSign, - bSign ? -0x3FFF : 0x7FFF, aSig, 0, status); - } - - if (bExp < 0x3FFF) return a; - - int shiftCount = 0x403E - bExp; - bSig >>= shiftCount; - Bit32s scale = (Bit32s) bSig; - if (bSign) scale = -scale; /* -32768..32767 */ - return - roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status); -} - -/*---------------------------------------------------------------------------- -| Determine extended-precision floating-point number class. -*----------------------------------------------------------------------------*/ - -float_class_t floatx80_class(floatx80 a) -{ - Bit32s aExp = extractFloatx80Exp(a); - Bit64u aSig = extractFloatx80Frac(a); - - if(aExp == 0) { - if (aSig == 0) - return float_zero; - - /* denormal or pseudo-denormal */ - return float_denormal; - } - - /* valid numbers have the MS bit set */ - if (!(aSig & BX_CONST64(0x8000000000000000))) - return float_SNaN; /* report unsupported as SNaNs */ - - if(aExp == 0x7fff) { - int aSign = extractFloatx80Sign(a); - - if (((Bit64u) (aSig<< 1)) == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & BX_CONST64(0x4000000000000000)) ? float_QNaN : float_SNaN; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two extended precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *status) -{ - float_class_t aClass = floatx80_class(a); - float_class_t bClass = floatx80_class(b); - - if (fpu_type < FPU_287XL) { - if ((aClass == float_positive_inf) && (bClass == float_negative_inf)) - { - return float_relation_equal; - } - - if ((aClass == float_negative_inf) && (bClass == float_positive_inf)) - { - return float_relation_equal; - } - } - - if (aClass == float_SNaN || bClass == float_SNaN) - { - /* unsupported reported as SNaN */ - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aClass == float_zero) { - if (bClass == float_zero) return float_relation_equal; - return bSign ? float_relation_greater : float_relation_less; - } - - if (bClass == float_zero || aSign != bSign) { - return aSign ? float_relation_less : float_relation_greater; - } - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - - if (aClass == float_denormal) - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - - if (bClass == float_denormal) - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - - if (aExp == bExp && aSig == bSig) - return float_relation_equal; - - int less_than = - aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) - : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); - - if (less_than) return float_relation_less; - return float_relation_greater; -} - - -int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status) -{ - return floatx80_compare(a, b, 0, status); -} - -int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status) -{ - return floatx80_compare(a, b, 1, status); -} diff --git a/src/cpu/softfloat/softfloatx80.h b/src/cpu/softfloat/softfloatx80.h deleted file mode 100644 index 1f96141b4..000000000 --- a/src/cpu/softfloat/softfloatx80.h +++ /dev/null @@ -1,121 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -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. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOATX80_EXTENSIONS_H_ -#define _SOFTFLOATX80_EXTENSIONS_H_ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -Bit16s floatx80_to_int16(floatx80, struct float_status_t *status); -Bit16s floatx80_to_int16_round_to_zero(floatx80, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status); -floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status); -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); -floatx80 f2xm1(floatx80 a, struct float_status_t *status); -floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status); -floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status); -floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision trigonometric functions. -*----------------------------------------------------------------------------*/ - -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status); -int fsin(floatx80 *a, struct float_status_t *status); -int fcos(floatx80 *a, struct float_status_t *status); -int ftan(floatx80 *a, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision compare. -*----------------------------------------------------------------------------*/ - -int floatx80_compare(floatx80, floatx80, int quiet, struct float_status_t *status); -int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status); -int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status); - -#ifdef __cplusplus -} -#endif - -/*----------------------------------------------------------------------------- -| Calculates the absolute value of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®) -#else -BX_CPP_INLINE floatx80 floatx80_abs(floatx80 reg) -#endif -{ - reg.exp &= 0x7FFF; - return reg; -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®) -#else -BX_CPP_INLINE floatx80 floatx80_chs(floatx80 reg) -#endif -{ - reg.exp ^= 0x8000; - return reg; -} - -/*----------------------------------------------------------------------------- -| Commonly used extended double-precision floating-point constants. -*----------------------------------------------------------------------------*/ - -extern const floatx80 Const_Z; -extern const floatx80 Const_1; -extern const floatx80 Const_L2T; -extern const floatx80 Const_L2E; -extern const floatx80 Const_PI; -extern const floatx80 Const_LG2; -extern const floatx80 Const_LN2; -extern const floatx80 Const_INF; -#endif diff --git a/src/cpu/softfloat3e/CMakeLists.txt b/src/cpu/softfloat3e/CMakeLists.txt new file mode 100644 index 000000000..5565460c8 --- /dev/null +++ b/src/cpu/softfloat3e/CMakeLists.txt @@ -0,0 +1,56 @@ +# +# 86Box A hypervisor and IBM PC system emulator that specializes in +# running old operating systems and software designed for IBM +# PC systems and compatibles from 1981 through fairly recent +# system designs based on the PCI bus. +# +# This file is part of the 86Box distribution. +# +# CMake build script. +# +# Authors: David Hrdlička, +# +# Copyright 2020-2021 David Hrdlička. +# + +add_library(softfloat3e OBJECT extF80_addsub.cc extF80_class.cc extF80_compare.cc + extF80_div.cc extF80_extract.cc extF80_mul.cc extF80_rem.cc extF80_roundToInt.cc + extF80_scale.cc extF80_sqrt.cc extF80_to_f16.cc extF80_to_f32.cc extF80_to_f64.cc + extF80_to_f128.cc extF80_to_i32.cc extF80_to_i32_r_minMag.cc extF80_to_i64.cc + extF80_to_i64_r_minMag.cc extF80_to_ui32.cc extF80_to_ui32_r_minMag.cc extF80_to_ui64.cc + extF80_to_ui64_r_minMag.cc f16_addsub.c f16_class.c f16_compare.c f16_div.c f16_getExp.c + f16_getMant.c f16_minmax.c f16_mul.c f16_mulAdd.c f16_range.c f16_roundToInt.c + f16_sqrt.c f16_to_extF80.cc f16_to_f32.c f16_to_f64.c f16_to_i32.c f16_to_i32_r_minMag.c + f16_to_i64.c f16_to_i64_r_minMag.c f16_to_ui32.c f16_to_ui32_r_minMag.c f16_to_ui64.c + f16_to_ui64_r_minMag.c f32_addsub.c f32_class.c f32_compare.c f32_div.c f32_frc.c + f32_getExp.c f32_getMant.c f32_minmax.c f32_mul.c f32_mulAdd.c f32_range.c + f32_roundToInt.c f32_scalef.c f32_sqrt.c f32_to_extF80.cc f32_to_f16.c f32_to_f64.c + f32_to_f128.cc f32_to_i32.c f32_to_i32_r_minMag.c f32_to_i64.c f32_to_i64_r_minMag.c + f32_to_ui32.c f32_to_ui32_r_minMag.c f32_to_ui64.c f32_to_ui64_r_minMag.c f64_addsub.c + f64_class.c f64_compare.c f64_div.c f64_frc.c f64_getExp.c f64_getMant.c f64_minmax.c + f64_mul.c f64_mulAdd.c f64_range.c f64_roundToInt.c f64_scalef.c f64_sqrt.c f64_to_extF80.cc + f64_to_f16.c f64_to_f32.c f64_to_f128.cc f64_to_i32.c f64_to_i32_r_minMag.c f64_to_i64.c + f64_to_i64_r_minMag.c f64_to_ui32.c f64_to_ui32_r_minMag.c f64_to_ui64.c f64_to_ui64_r_minMag.c + f128_addsub.cc f128_div.cc f128_mul.cc f128_mulAdd.cc f128_roundToInt.cc f128_to_extF80.cc + f128_to_f32.cc f128_to_f64.cc f128_to_i32.cc f128_to_i32_r_minMag.cc f128_to_i64.cc + f128_to_i64_r_minMag.cc f128_to_ui32.cc f128_to_ui32_r_minMag.cc f128_to_ui64.cc + f128_to_ui64_r_minMag.cc i32_to_extF80.cc i32_to_f16.c i32_to_f32.c i32_to_f64.c + i32_to_f128.cc i64_to_extF80.cc i64_to_f16.c i64_to_f32.c i64_to_f64.c i64_to_f128.cc + isNaN.cc isSignalingNaN.cc s_add128.cc s_add256M.c s_addMagsExtF80.cc s_addMagsF16.c + s_addMagsF32.c s_addMagsF64.c s_addMagsF128.cc s_approxRecip_1Ks.c s_approxRecipSqrt_1Ks.c + s_approxRecipSqrt32_1.c s_commonNaNToExtF80UI.cc s_commonNaNToF16UI.c s_commonNaNToF32UI.c + s_commonNaNToF64UI.c s_commonNaNToF128UI.cc s_countLeadingZeros8.c s_countLeadingZeros16.c + s_countLeadingZeros32.c s_countLeadingZeros64.c s_eq128.c s_le128.c s_lt128.c + s_mul64ByShifted32To128.cc s_mul64To128.cc s_mul128By32.cc s_mul128To256M.cc + s_normRoundPackToExtF80.cc s_normRoundPackToF16.c s_normRoundPackToF32.c s_normRoundPackToF64.c + s_normRoundPackToF128.cc s_normSubnormalExtF80Sig.cc s_normSubnormalF16Sig.c + s_normSubnormalF32Sig.c s_normSubnormalF64Sig.c s_normSubnormalF128Sig.cc s_packToExtF80.cc + s_propagateNaNExtF80UI.cc s_propagateNaNF16UI.c s_propagateNaNF32UI.c s_propagateNaNF64UI.c + s_propagateNaNF128UI.cc s_roundPackToExtF80.cc s_roundPackToF16.c s_roundPackToF32.c + s_roundPackToF64.c s_roundPackToF128.cc s_roundToI32.c s_roundToI64.c s_roundToUI32.c + s_roundToUI64.c s_shiftRightJam32.c s_shiftRightJam64.c s_shiftRightJam64Extra.c + s_shiftRightJam256M.c s_shortShiftLeft128.cc s_shortShiftRight128.cc s_shortShiftRightJam64.c + s_shortShiftRightJam64Extra.c s_sub128.cc s_sub256M.c s_subMagsExtF80.cc s_subMagsF16.c + s_subMagsF32.c s_subMagsF64.c s_subMagsF128.cc ui32_to_extF80.cc ui32_to_f16.c ui32_to_f32.c + ui32_to_f64.c ui32_to_f128.cc ui64_to_extF80.cc ui64_to_f16.c ui64_to_f32.c ui64_to_f64.c + ui64_to_f128.cc f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc poly.cc consts.cc) \ No newline at end of file diff --git a/src/cpu/softfloat3e/COPYING.txt b/src/cpu/softfloat3e/COPYING.txt new file mode 100644 index 000000000..b5690face --- /dev/null +++ b/src/cpu/softfloat3e/COPYING.txt @@ -0,0 +1,37 @@ + +License for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +The following applies to the whole of SoftFloat Release 3e as well as to +each source file individually. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/cpu/softfloat3e/README.html b/src/cpu/softfloat3e/README.html new file mode 100644 index 000000000..e695c2bd8 --- /dev/null +++ b/src/cpu/softfloat3e/README.html @@ -0,0 +1,49 @@ + + + + +Berkeley SoftFloat Package Overview + + + + +

Package Overview for Berkeley SoftFloat Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +SoftFloat is distributed in the form of C source code. +Building the SoftFloat sources generates a library file (typically +softfloat.a or libsoftfloat.a) containing the +floating-point subroutines. +

+ +

+The SoftFloat package is documented in the following files in the +doc subdirectory: +

+ + + + + + + + + + + + + +
SoftFloat.htmlDocumentation for using the SoftFloat functions.
SoftFloat-source.htmlDocumentation for building SoftFloat.
SoftFloat-history.html   History of the major changes to SoftFloat.
+
+Other files in the package comprise the source code for SoftFloat. +

+ + + diff --git a/src/cpu/softfloat3e/README.txt b/src/cpu/softfloat3e/README.txt new file mode 100644 index 000000000..1613c7671 --- /dev/null +++ b/src/cpu/softfloat3e/README.txt @@ -0,0 +1,21 @@ + +Package Overview for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat +is distributed in the form of C source code. Building the SoftFloat sources +generates a library file (typically "softfloat.a" or "libsoftfloat.a") +containing the floating-point subroutines. + +The SoftFloat package is documented in the following files in the "doc" +subdirectory: + + SoftFloat.html Documentation for using the SoftFloat functions. + SoftFloat-source.html Documentation for building SoftFloat. + SoftFloat-history.html History of the major changes to SoftFloat. + +Other files in the package comprise the source code for SoftFloat. + diff --git a/src/cpu/softfloat3e/config.h b/src/cpu/softfloat3e/config.h new file mode 100644 index 000000000..9febce242 --- /dev/null +++ b/src/cpu/softfloat3e/config.h @@ -0,0 +1,14 @@ +#ifndef EMU_SF_CONFIG_H +#define EMU_SF_CONFIG_H + +/*---------------------------------------------------------------------------- +| The `LIT64' macro takes as its argument a textual integer literal and +| if necessary ``marks'' the literal as having a 64-bit integer type. +| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +| appended with the letters `LL' standing for `long long', which is `gcc's +| name for the 64-bit integer type. Some compilers may allow `LIT64' to be +| defined as the identity macro: `#define LIT64( a ) a'. +*----------------------------------------------------------------------------*/ +#define BX_CONST64(a) a##LL + +#endif /*EMU_SF_CONFIG_H*/ diff --git a/src/cpu/softfloat3e/consts.cc b/src/cpu/softfloat3e/consts.cc new file mode 100644 index 000000000..235a03996 --- /dev/null +++ b/src/cpu/softfloat3e/consts.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include <86box/86box.h> +#include "../cpu.h" + +#include "softfloat-specialize.h" + +const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); +const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); +const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc)); +const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); +const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799)); +const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac)); +const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000)); diff --git a/src/cpu/softfloat3e/doc/SoftFloat-history.html b/src/cpu/softfloat3e/doc/SoftFloat-history.html new file mode 100644 index 000000000..d81c6bc5a --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat-history.html @@ -0,0 +1,258 @@ + + + + +Berkeley SoftFloat History + + + + +

History of Berkeley SoftFloat, to Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Release 3e (2018 January)

+ +
    + +
  • +Changed the default numeric code for optional rounding mode odd +(round to odd, also known as jamming) from 5 to 6. + +
  • +Modified the behavior of rounding mode odd when rounding to an +integer value (either conversion to an integer format or a +‘roundToInt’ function). +Previously, for those cases only, rounding mode odd acted the same +as rounding to minimum magnitude. +Now all operations are rounded consistently. + +
  • +Fixed some errors in the specialization code modeling Intel x86 floating-point, +specifically the integers returned on invalid operations and the propagation of +NaN payloads in a few rare cases. + +
  • +Added specialization code modeling ARM floating-point, conforming to VFPv2 or +later. + +
  • +Added an example target for ARM processors. + +
  • +Fixed a minor bug whereby function f16_to_ui64 might return a +different integer than expected in the case that the floating-point operand is +negative. + +
  • +Added example target-specific optimization for GCC, employing GCC instrinsics +and support for 128-bit integer arithmetic. + +
  • +Made other minor improvements. + +
+ + +

Release 3d (2017 August)

+ +
    + +
  • +Fixed bugs in the square root functions for 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +For 64-bit double-precision (f64_sqrt), the result +could sometimes be off by 1 unit in the last place +(1 ulp) from what it should be. +For the larger formats, the square root could be wrong in a large portion of +the less-significant bits. +(A bug in f128_sqrt was first reported by Alexei Sibidanov.) + +
+ + +

Release 3c (2017 February)

+ +
    + +
  • +Added optional rounding mode odd (round to odd, also known as +jamming). + +
  • +Corrected the documentation concerning non-canonical representations in +80-bit double-extended-precision. + +
+ + +

Release 3b (2016 July)

+ +
    + +
  • +Implemented the common 16-bit “half-precision” +floating-point format (float16_t). + +
  • +Made the integer values returned on invalid conversions to integer formats +be determined by the port-specific specialization instead of being the same for +all ports. + +
  • +Added preprocessor macro THREAD_LOCAL to allow the floating-point +state (modes and exception flags) to be made per-thread. + +
  • +Modified the provided Makefiles to allow some options to be overridden from the +make command. + +
  • +Made other minor improvements. + +
+ + +

Release 3a (2015 October)

+ +
    + +
  • +Replaced the license text supplied by the University of California, Berkeley. + +
+ + +

Release 3 (2015 February)

+ +
    + +
  • +Complete rewrite, funded by the University of California, Berkeley, and +consequently having a different use license than earlier releases. +Major changes included renaming most types and functions, upgrading some +algorithms, restructuring the source files, and making SoftFloat into a true +library. + +
  • +Added functions to convert between floating-point and unsigned integers, both +32-bit and 64-bit (uint32_t and +uint64_t). + +
  • +Added functions for fused multiply-add, for all supported floating-point +formats except 80-bit double-extended-precision. + +
  • +Added support for a fifth rounding mode, near_maxMag (round to +nearest, with ties to maximum magnitude, away from zero). + +
  • +Dropped the timesoftfloat program (now part of the Berkeley +TestFloat package). + +
+ + +

Release 2c (2015 January)

+ +
    + +
  • +Fixed mistakes affecting some 64-bit processors. + +
  • +Further improved the documentation and the wording for the legal restrictions +on using SoftFloat releases through 2c (not applicable to +Release 3 or later). + +
+ + +

Release 2b (2002 May)

+ +
    + +
  • +Made minor updates to the documentation, including improved wording for the +legal restrictions on using SoftFloat. + +
+ + +

Release 2a (1998 December)

+ +
    + +
  • +Added functions to convert between 64-bit integers +(int64) and all supported floating-point formats. + +
  • +Fixed a bug in all 64-bit-version square root functions except +float32_sqrt that caused the result sometimes to be off by +1 unit in the last place (1 ulp) from what it should +be. +(Bug discovered by Paul Donahue.) + +
  • +Improved the Makefiles. +
+ + +

Release 2 (1997 June)

+ +
    + +
  • +Created the 64-bit (bits64) version, adding the +floatx80 and float128 formats. + +
  • +Changed the source directory structure, splitting the sources into a +bits32 and a bits64 version. +Renamed environment.h to milieu.h to avoid confusion +with environment variables. + +
  • +Fixed a small error that caused float64_round_to_int often to +round the wrong way in nearest/even mode when the operand was between +220 and 221 and halfway between two integers. + +
+ + +

Release 1a (1996 July)

+ +
    + +
  • +Corrected a mistake that caused borderline underflow cases not to raise the +underflow flag when they should have. +(Problem reported by Doug Priest.) + +
  • +Added the float_detect_tininess variable to control whether +tininess is detected before or after rounding. + +
+ + +

Release 1 (1996 July)

+ +
    + +
  • +Original release, based on work done for the International Computer Science +Institute (ICSI) in Berkeley, California. + +
+ + + + diff --git a/src/cpu/softfloat3e/doc/SoftFloat-source.html b/src/cpu/softfloat3e/doc/SoftFloat-source.html new file mode 100644 index 000000000..4ff9d4c45 --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat-source.html @@ -0,0 +1,686 @@ + + + + +Berkeley SoftFloat Source Documentation + + + + +

Berkeley SoftFloat Release 3e: Source Documentation

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. SoftFloat Package Directory Structure
5. Issues for Porting SoftFloat to a New Target
5.1. Standard Headers <stdbool.h> and + <stdint.h>
5.2. Specializing Floating-Point Behavior
5.3. Macros for Build Options
5.4. Adapting a Template Target Directory
5.5. Target-Specific Optimization of Primitive Functions
6. Testing SoftFloat
7. Providing SoftFloat as a Common Library for Applications
8. Contact Information
+
+ + +

1. Introduction

+ +

+This document gives information needed for compiling and/or porting Berkeley +SoftFloat, a library of C functions implementing binary floating-point +conforming to the IEEE Standard for Floating-Point Arithmetic. +For basic documentation about SoftFloat refer to +SoftFloat.html. +

+ +

+The source code for SoftFloat is intended to be relatively machine-independent +and should be compilable with any ISO-Standard C compiler that also supports +64-bit integers. +SoftFloat has been successfully compiled with the GNU C Compiler +(gcc) for several platforms. +

+ +

+Release 3 of SoftFloat was a complete rewrite relative to +Release 2 or earlier. +Changes to the interface of SoftFloat functions are documented in +SoftFloat.html. +The current version of SoftFloat is Release 3e. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of either 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+C Standard header files <stdbool.h> and +<stdint.h> are required for defining standard Boolean and +integer types. +If these headers are not supplied with the C compiler, minimal substitutes must +be provided. +SoftFloat’s dependence on these headers is detailed later in +section 5.1, Standard Headers <stdbool.h> +and <stdint.h>. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. SoftFloat Package Directory Structure

+ +

+Because SoftFloat is targeted to multiple platforms, its source code is +slightly scattered between target-specific and target-independent directories +and files. +The supplied directory structure is as follows: +

+
+doc
+source
+    include
+    8086
+    8086-SSE
+    ARM-VFPv2
+    ARM-VFPv2-defaultNaN
+build
+    template-FAST_INT64
+    template-not-FAST_INT64
+    Linux-386-GCC
+    Linux-386-SSE2-GCC
+    Linux-x86_64-GCC
+    Linux-ARM-VFPv2-GCC
+    Win32-MinGW
+    Win32-SSE2-MinGW
+    Win64-MinGW-w64
+
+
+The majority of the SoftFloat sources are provided in the source +directory. +The include subdirectory contains several header files +(unsurprisingly), while the other subdirectories of source contain +source files that specialize the floating-point behavior to match particular +processor families: +
+
+
8086
+
+Intel’s older, 8087-derived floating-point, extended to all supported +floating-point types +
+
8086-SSE
+
+Intel’s x86 processors with Streaming SIMD Extensions (SSE) and later +compatible extensions, having 8087 behavior for 80-bit +double-extended-precision (extFloat80_t) and SSE behavior for +other floating-point types +
+
ARM-VFPv2
+
+ARM’s VFPv2 or later floating-point, with NaN payload propagation +
+
ARM-VFPv2-defaultNaN
+
+ARM’s VFPv2 or later floating-point, with the “default NaN” +option +
+
+
+If other specializations are attempted, these would be expected to be other +subdirectories of source alongside the ones listed above. +Specialization is covered later, in section 5.2, Specializing +Floating-Point Behavior. +

+ +

+The build directory is intended to contain a subdirectory for each +target platform for which a build of the SoftFloat library may be created. +For each build target, the target’s subdirectory is where all derived +object files and the completed SoftFloat library (typically +softfloat.a or libsoftfloat.a) are created. +The two template subdirectories are not actual build targets but +contain sample files for creating new target directories. +(The meaning of FAST_INT64 will be explained later.) +

+ +

+Ignoring the template directories, the supplied target directories +are intended to follow a naming system of +<execution-environment>-<compiler>. +For the example targets, +<execution-environment> is +Linux-386, Linux-386-SSE2, +Linux-x86_64, +Linux-ARM-VFPv2, Win32, +Win32-SSE2, or Win64, and +<compiler> is GCC, +MinGW, or MinGW-w64. +

+ +

+All of the supplied target directories are merely examples that may or may not +be correct for compiling on any particular system. +Despite requests, there are currently no plans to include and maintain in the +SoftFloat package the build files needed for a great many users’ +compilation environments, which can span a huge range of operating systems, +compilers, and other tools. +

+ +

+As supplied, each target directory contains two files: +

+
+Makefile
+platform.h
+
+
+The provided Makefile is written for GNU make. +A build of SoftFloat for the specific target is begun by executing the +make command with the target directory as the current directory. +A completely different build tool can be used if an appropriate +Makefile equivalent is created. +

+ +

+The platform.h header file exists to provide a location for +additional C declarations specific to the build target. +Every C source file of SoftFloat contains a #include for +platform.h. +In many cases, the contents of platform.h can be as simple as one +or two lines of code. +At the other extreme, to get maximal performance from SoftFloat, it may be +desirable to include in header platform.h (directly or via +#include) declarations for numerous target-specific optimizations. +Such possibilities are discussed in the next section, Issues for Porting +SoftFloat to a New Target. +If the target’s compiler or library has bugs or other shortcomings, +workarounds for these issues may also be possible with target-specific +declarations in platform.h, avoiding the need to modify the main +SoftFloat sources. +

+ + +

5. Issues for Porting SoftFloat to a New Target

+ +

5.1. Standard Headers <stdbool.h> and <stdint.h>

+ +

+The SoftFloat sources make use of standard headers +<stdbool.h> and <stdint.h>, which have +been part of the ISO C Standard Library since 1999. +With any recent compiler, these standard headers are likely to be supported, +even if the compiler does not claim complete conformance to the latest ISO C +Standard. +For older or nonstandard compilers, substitutes for +<stdbool.h> and <stdint.h> may need to be +created. +SoftFloat depends on these names from <stdbool.h>: +

+
+bool
+true
+false
+
+
+and on these names from <stdint.h>: +
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+UINT64_C
+INT64_C
+uint_least8_t
+uint_fast8_t
+uint_fast16_t
+uint_fast32_t
+uint_fast64_t
+int_fast8_t
+int_fast16_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

5.2. Specializing Floating-Point Behavior

+ +

+The IEEE Floating-Point Standard allows for some flexibility in a conforming +implementation, particularly concerning NaNs. +The SoftFloat source directory is supplied with some +specialization subdirectories containing possible definitions for this +implementation-specific behavior. +For example, the 8086 and 8086-SSE +subdirectories have source files that specialize SoftFloat’s behavior to +match that of Intel’s x86 line of processors. +The files in a specialization subdirectory must determine: +

    +
  • +whether tininess for underflow is detected before or after rounding by default; +
  • +how signaling NaNs are distinguished from quiet NaNs; +
  • +what (if anything) special happens when exceptions are raised; +
  • +the default generated quiet NaNs; +
  • +how NaNs are propagated from function inputs to output; and +
  • +the integer results returned when conversions to integer type raise the +invalid exception. +
+

+ +

+As provided, the build process for a target expects to involve exactly +one specialization directory that defines all of these +implementation-specific details for the target. +A specialization directory such as 8086 is expected to contain a +header file called specialize.h, together with whatever other +source files are needed to complete the specialization. +

+ +

+A new build target may use an existing specialization, such as the ones +provided by the 8086 and 8086-SSE +subdirectories. +If a build target needs a new specialization, different from any existing ones, +it is recommended that a new specialization directory be created for this +purpose. +The specialize.h header file from any of the provided +specialization subdirectories can be used as a model for what definitions are +needed. +

+ + +

5.3. Macros for Build Options

+ +

+The SoftFloat source files adapt the floating-point implementation according to +several C preprocessor macros: +

+
+
LITTLEENDIAN +
+Must be defined for little-endian machines; must not be defined for big-endian +machines. +
INLINE +
+Specifies the sequence of tokens used to indicate that a C function should be +inlined. +If macro INLINE_LEVEL is defined with a value of 1 or higher, this +macro must be defined; otherwise, this macro is ignored and need not be +defined. +For compilers that conform to the C Standard’s rules for inline +functions, this macro can be defined as the single keyword inline. +For other compilers that follow a convention pre-dating the standardization of +inline, this macro may need to be defined to extern +inline. +
THREAD_LOCAL +
+Can be defined to a sequence of tokens that, when appearing at the start of a +variable declaration, indicates to the C compiler that the variable is +per-thread, meaning that each execution thread gets its own separate +instance of the variable. +This macro is used in header softfloat.h in the declarations of +variables softfloat_roundingMode, +softfloat_detectTininess, extF80_roundingPrecision, +and softfloat_exceptionFlags. +If macro THREAD_LOCAL is left undefined, these variables will +default to being ordinary global variables. +Depending on the compiler, possible valid definitions of this macro include +_Thread_local and __thread. +
+
+
SOFTFLOAT_ROUND_ODD +
+Can be defined to enable support for optional rounding mode +softfloat_round_odd. +
+
+
INLINE_LEVEL +
+Can be defined to an integer to determine the degree of inlining requested of +the compiler. +Larger numbers request that more inlining be done. +If this macro is not defined or is defined to a value less than 1 +(zero or negative), no inlining is requested. +The maximum effective value is no higher than 5. +Defining this macro to a value greater than 5 is the same as defining it +to 5. +
SOFTFLOAT_FAST_INT64 +
+Can be defined to indicate that the build target’s implementation of +64-bit arithmetic is efficient. +For newer 64-bit processors, this macro should usually be defined. +For very small microprocessors whose buses and registers are 8-bit +or 16-bit in size, this macro should usually not be defined. +Whether this macro should be defined for a 32-bit processor may +depend on the target machine and the applications that will use SoftFloat. +
SOFTFLOAT_FAST_DIV32TO16 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 32-bit unsigned integer by a 16-bit +unsigned integer. +Setting this macro may affect the performance of function f16_div. +
SOFTFLOAT_FAST_DIV64TO32 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 64-bit unsigned integer by a 32-bit +unsigned integer. +Setting this macro may affect the performance of division, remainder, and +square root operations other than f16_div. +
+
+

+ +

+Following the usual custom for C, for most of these macros (all +except INLINE, THREAD_LOCAL, and +INLINE_LEVEL), the content of any definition is irrelevant; +what matters is a macro’s effect on #ifdef directives. +

+ +

+It is recommended that any definitions of macros LITTLEENDIAN, +INLINE, and THREAD_LOCAL be made in a build +target’s platform.h header file, because these macros are +expected to be determined inflexibly by the target machine and compiler. +The other five macros select options and control optimization, and thus might +be better located in the target’s Makefile (or its equivalent). +

+ + +

5.4. Adapting a Template Target Directory

+ +

+In the build directory, two template subdirectories +provide models for new target directories. +Two different templates exist because different functions are needed in the +SoftFloat library depending on whether macro SOFTFLOAT_FAST_INT64 +is defined. +If macro SOFTFLOAT_FAST_INT64 will be defined, +template-FAST_INT64 is the template to use; +otherwise, template-not-FAST_INT64 is the appropriate +template. +A new target directory can be created by copying the correct template directory +and editing the files inside. +To avoid confusion, it would be wise to refrain from editing the files within a +template directory directly. +

+ + +

5.5. Target-Specific Optimization of Primitive Functions

+ +

+Header file primitives.h (in directory +source/include) declares macros and functions for numerous +underlying arithmetic operations upon which many of SoftFloat’s +floating-point functions are ultimately built. +The SoftFloat sources include implementations of all of these functions/macros, +written as standard C code, so a complete and correct SoftFloat library can be +created using only the supplied code for all functions. +However, for many targets, SoftFloat’s performance can be improved by +substituting target-specific implementations of some of the functions/macros +declared in primitives.h. +

+ +

+For example, primitives.h declares a function called +softfloat_countLeadingZeros32 that takes an unsigned +32-bit integer as an argument and returns the number of the +integer’s most-significant bits that are zeros. +While the SoftFloat sources include an implementation of this function written +in standard C, many processors can perform this same function +directly in only one or two machine instructions. +An alternative, target-specific implementation that maps to those instructions +is likely to be more efficient than the generic C code from the SoftFloat +package. +

+ +

+A build target can replace the supplied version of any function or macro of +primitives.h by defining a macro with the same name in the +target’s platform.h header file. +For this purpose, it may be helpful for platform.h to +#include header file primitiveTypes.h, which defines +types used for arguments and results of functions declared in +primitives.h. +When a desired replacement implementation is a function, not a macro, it is +sufficient for platform.h to include the line +

+
+#define <function-name> <function-name>
+
+
+where <function-name> is the name of the +function. +This technically defines <function-name> +as a macro, but one that resolves to the same name, which may then be a +function. +(A preprocessor that conforms to the C Standard is required to limit recursive +macro expansion from being applied more than once.) +

+ +

+The supplied header file opts-GCC.h (in directory +source/include) provides an example of target-specific +optimization for the GCC compiler. +Each GCC target example in the build directory has +

+#include "opts-GCC.h" +
+in its platform.h header file. +Before opts-GCC.h is included, the following macros must be +defined (or not) to control which features are invoked: +
+
+
SOFTFLOAT_BUILTIN_CLZ
+
+If defined, SoftFloat’s internal +‘countLeadingZeros’ functions use intrinsics +__builtin_clz and __builtin_clzll. +
+
SOFTFLOAT_INTRINSIC_INT128
+
+If defined, SoftFloat makes use of GCC’s nonstandard 128-bit +integer type __int128. +
+
+
+On some machines, these improvements are observed to increase the speeds of +f64_mul and f128_mul by around 20 to 25%, although +other functions receive less dramatic boosts, or none at all. +Results can vary greatly across different platforms. +

+ + +

6. Testing SoftFloat

+ +

+SoftFloat can be tested using the testsoftfloat program by the +same author. +This program is part of the Berkeley TestFloat package available at the Web +page +http://www.jhauser.us/arithmetic/TestFloat.html. +The TestFloat package also has a program called timesoftfloat that +measures the speed of SoftFloat’s floating-point functions. +

+ + +

7. Providing SoftFloat as a Common Library for Applications

+ +

+Header file softfloat.h defines the SoftFloat interface as seen by +clients. +If the SoftFloat library will be made a common library for programs on a +system, the supplied softfloat.h has a couple of deficiencies for +this purpose: +

    +
  • +As supplied, softfloat.h depends on another header, +softfloat_types.h, that is not intended for public use but which +must also be visible to the programmer’s compiler. +
  • +More troubling, at the time softfloat.h is included in a C source +file, macros SOFTFLOAT_FAST_INT64 and THREAD_LOCAL +must be defined, or not defined, consistent with how these macro were defined +when the SoftFloat library was built. +
+In the situation that new programs may regularly #include header +file softfloat.h, it is recommended that a custom, self-contained +version of this header file be created that eliminates these issues. +

+ + +

8. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/cpu/softfloat3e/doc/SoftFloat.html b/src/cpu/softfloat3e/doc/SoftFloat.html new file mode 100644 index 000000000..b72b407f4 --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat.html @@ -0,0 +1,1527 @@ + + + + +Berkeley SoftFloat Library Interface + + + + +

Berkeley SoftFloat Release 3e: Library Interface

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. Types and Functions
4.1. Boolean and Integer Types
4.2. Floating-Point Types
4.3. Supported Floating-Point Functions
4.4. Non-canonical Representations in extFloat80_t
4.5. Conventions for Passing Arguments and Results
5. Reserved Names
6. Mode Variables
6.1. Rounding Mode
6.2. Underflow Detection
6.3. Rounding Precision for the 80-Bit Extended Format
7. Exceptions and Exception Flags
8. Function Details
8.1. Conversions from Integer to Floating-Point
8.2. Conversions from Floating-Point to Integer
8.3. Conversions Among Floating-Point Types
8.4. Basic Arithmetic Functions
8.5. Fused Multiply-Add Functions
8.6. Remainder Functions
8.7. Round-to-Integer Functions
8.8. Comparison Functions
8.9. Signaling NaN Test Functions
8.10. Raise-Exception Function
9. Changes from SoftFloat Release 2
9.1. Name Changes
9.2. Changes to Function Arguments
9.3. Added Capabilities
9.4. Better Compatibility with the C Language
9.5. New Organization as a Library
9.6. Optimization Gains (and Losses)
10. Future Directions
11. Contact Information
+
+ + +

1. Introduction

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +The current release supports five binary formats: 16-bit +half-precision, 32-bit single-precision, 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +The following functions are supported for each format: +

    +
  • +addition, subtraction, multiplication, division, and square root; +
  • +fused multiply-add as defined by the IEEE Standard, except for +80-bit double-extended-precision; +
  • +remainder as defined by the IEEE Standard; +
  • +round to integral value; +
  • +comparisons; +
  • +conversions to/from other supported formats; and +
  • +conversions to/from 32-bit and 64-bit integers, +signed and unsigned. +
+All operations required by the original 1985 version of the IEEE Floating-Point +Standard are implemented, except for conversions to and from decimal. +

+ +

+This document gives information about the types defined and the routines +implemented by SoftFloat. +It does not attempt to define or explain the IEEE Floating-Point Standard. +Information about the standard is available elsewhere. +

+ +

+The current version of SoftFloat is Release 3e. +This release modifies the behavior of the rarely used odd rounding mode +(round to odd, also known as jamming), and also adds some new +specialization and optimization examples for those compiling SoftFloat. +

+ +

+The previous Release 3d fixed bugs that were found in the square +root functions for the 64-bit, 80-bit, and +128-bit floating-point formats. +(Thanks to Alexei Sibidanov at the University of Victoria for reporting an +incorrect result.) +The bugs affected all prior Release-3 versions of SoftFloat +through 3c. +The flaw in the 64-bit floating-point square root function was of +very minor impact, causing a 1-ulp error (1 unit in +the last place) a few times out of a billion. +The bugs in the 80-bit and 128-bit square root +functions were more serious. +Although incorrect results again occurred only a few times out of a billion, +when they did occur a large portion of the less-significant bits could be +wrong. +

+ +

+Among earlier releases, 3b was notable for adding support for the +16-bit half-precision format. +For more about the evolution of SoftFloat releases, see +SoftFloat-history.html. +

+ +

+The functional interface of SoftFloat Release 3 and later differs +in many details from the releases that came before. +For specifics of these differences, see section 9 below, +Changes from SoftFloat Release 2. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+Most operations not required by the original 1985 version of the IEEE +Floating-Point Standard but added in the 2008 version are not yet supported in +SoftFloat Release 3e. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. Types and Functions

+ +

+The types and functions of SoftFloat are declared in header file +softfloat.h. +

+ +

4.1. Boolean and Integer Types

+ +

+Header file softfloat.h depends on standard headers +<stdbool.h> and <stdint.h> to define type +bool and several integer types. +These standard headers have been part of the ISO C Standard Library since 1999. +With any recent compiler, they are likely to be supported, even if the compiler +does not claim complete conformance to the latest ISO C Standard. +For older or nonstandard compilers, a port of SoftFloat may have substitutes +for these headers. +Header softfloat.h depends only on the name bool from +<stdbool.h> and on these type names from +<stdint.h>: +

+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+uint_fast8_t
+uint_fast32_t
+uint_fast64_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

4.2. Floating-Point Types

+ +

+The softfloat.h header defines five floating-point types: +

+ + + + + + + + + + + + + + + + + + + + + +
float16_t16-bit half-precision binary format
float32_t32-bit single-precision binary format
float64_t64-bit double-precision binary format
extFloat80_t   80-bit double-extended-precision binary format (old Intel or +Motorola format)
float128_t128-bit quadruple-precision binary format
+
+The non-extended types are each exactly the size specified: +16 bits for float16_t, 32 bits for +float32_t, 64 bits for float64_t, and +128 bits for float128_t. +Aside from these size requirements, the definitions of all these types may +differ for different ports of SoftFloat to specific systems. +A given port of SoftFloat may or may not define some of the floating-point +types as aliases for the C standard types float, +double, and long double. +

+ +

+Header file softfloat.h also defines a structure, +struct extFloat80M, for the representation of +80-bit double-extended-precision floating-point values in memory. +This structure is the same size as type extFloat80_t and contains +at least these two fields (not necessarily in this order): +

+
+uint16_t signExp;
+uint64_t signif;
+
+
+Field signExp contains the sign and exponent of the floating-point +value, with the sign in the most significant bit (bit 15) and the +encoded exponent in the other 15 bits. +Field signif is the complete 64-bit significand of +the floating-point value. +(In the usual encoding for 80-bit extended floating-point, the +leading 1 bit of normalized numbers is not implicit but is stored +in the most significant bit of the significand.) +

+ +

4.3. Supported Floating-Point Functions

+ +

+SoftFloat implements these arithmetic operations for its floating-point types: +

    +
  • +conversions between any two floating-point formats; +
  • +for each floating-point format, conversions to and from signed and unsigned +32-bit and 64-bit integers; +
  • +for each format, the usual addition, subtraction, multiplication, division, and +square root operations; +
  • +for each format except extFloat80_t, the fused multiply-add +operation defined by the IEEE Standard; +
  • +for each format, the floating-point remainder operation defined by the IEEE +Standard; +
  • +for each format, a “round to integer” operation that rounds to the +nearest integer value in the same format; and +
  • +comparisons between two values in the same floating-point format. +
+

+ +

+The following operations required by the 2008 IEEE Floating-Point Standard are +not supported in SoftFloat Release 3e: +

    +
  • +nextUp, nextDown, minNum, maxNum, minNumMag, +maxNumMag, scaleB, and logB; +
  • +conversions between floating-point formats and decimal or hexadecimal character +sequences; +
  • +all “quiet-computation” operations (copy, negate, +abs, and copySign, which all involve only simple copying and/or +manipulation of the floating-point sign bit); and +
  • +all “non-computational” operations other than isSignaling +(which is supported). +
+

+ +

4.4. Non-canonical Representations in extFloat80_t

+ +

+Because the 80-bit double-extended-precision format, +extFloat80_t, stores an explicit leading significand bit, many +finite floating-point numbers are encodable in this type in multiple equivalent +forms. +Of these multiple encodings, there is always a unique one with the least +encoded exponent value, and this encoding is considered the canonical +representation of the floating-point number. +Any other equivalent representations (having a higher encoded exponent value) +are non-canonical. +For a value in the subnormal range (including zero), the canonical +representation always has an encoded exponent of zero and a leading significand +bit of 0. +For finite values outside the subnormal range, the canonical representation +always has an encoded exponent that is nonzero and a leading significand bit +of 1. +

+ +

+For an infinity or NaN, the leading significand bit is similarly expected to +be 1. +An infinity or NaN with a leading significand bit of 0 is again +considered non-canonical. +Hence, altogether, to be canonical, a value of type extFloat80_t +must have a leading significand bit of 1, unless the value is +subnormal or zero, in which case the leading significand bit and the encoded +exponent must both be zero. +

+ +

+SoftFloat’s functions are not guaranteed to operate as expected when +inputs of type extFloat80_t are non-canonical. +Assuming all of a function’s extFloat80_t inputs (if any) +are canonical, function outputs of type extFloat80_t will always +be canonical. +

+ +

4.5. Conventions for Passing Arguments and Results

+ +

+Values that are at most 64 bits in size (i.e., not the +80-bit or 128-bit floating-point formats) are in all +cases passed as function arguments by value. +Likewise, when an output of a function is no more than 64 bits, it +is always returned directly as the function result. +Thus, for example, the SoftFloat function for adding two 64-bit +floating-point values has this simple signature: +

+float64_t f64_add( float64_t, float64_t ); +
+

+ +

+The story is more complex when function inputs and outputs are +80-bit and 128-bit floating-point. +For these types, SoftFloat always provides a function that passes these larger +values into or out of the function indirectly, via pointers. +For example, for adding two 128-bit floating-point values, +SoftFloat supplies this function: +

+void f128M_add( const float128_t *, const float128_t *, float128_t * ); +
+The first two arguments point to the values to be added, and the last argument +points to the location where the sum will be stored. +The M in the name f128M_add is mnemonic for the fact +that the 128-bit inputs and outputs are “in memory”, +pointed to by pointer arguments. +

+ +

+All ports of SoftFloat implement these pass-by-pointer functions for +types extFloat80_t and float128_t. +At the same time, SoftFloat ports may also implement alternate versions of +these same functions that pass extFloat80_t and +float128_t by value, like the smaller formats. +Thus, besides the function with name f128M_add shown above, a +SoftFloat port may also supply an equivalent function with this signature: +

+float128_t f128_add( float128_t, float128_t ); +
+

+ +

+As a general rule, on computers where the machine word size is +32 bits or smaller, only the pass-by-pointer versions of functions +(e.g., f128M_add) are provided for types extFloat80_t +and float128_t, because passing such large types directly can have +significant extra cost. +On computers where the word size is 64 bits or larger, both +function versions (f128M_add and f128_add) are +provided, because the cost of passing by value is then more reasonable. +Applications that must be portable accross both classes of computers must use +the pointer-based functions, as these are always implemented. +However, if it is known that SoftFloat includes the by-value functions for all +platforms of interest, programmers can use whichever version they prefer. +

+ + +

5. Reserved Names

+ +

+In addition to the variables and functions documented here, SoftFloat defines +some symbol names for its own private use. +These private names always begin with the prefix +‘softfloat_’. +When a program includes header softfloat.h or links with the +SoftFloat library, all names with prefix ‘softfloat_’ +are reserved for possible use by SoftFloat. +Applications that use SoftFloat should not define their own names with this +prefix, and should reference only such names as are documented. +

+ + +

6. Mode Variables

+ +

+The following global variables control rounding mode, underflow detection, and +the 80-bit extended format’s rounding precision: +

+softfloat_roundingMode
+softfloat_detectTininess
+extF80_roundingPrecision +
+These mode variables are covered in the next several subsections. +For some SoftFloat ports, these variables may be per-thread (declared +thread_local), meaning that different execution threads have their +own separate copies of the variables. +

+ +

6.1. Rounding Mode

+ +

+All five rounding modes defined by the 2008 IEEE Floating-Point Standard are +implemented for all operations that require rounding. +Some ports of SoftFloat may also implement the round-to-odd mode. +

+ +

+The rounding mode is selected by the global variable +

+uint_fast8_t softfloat_roundingMode; +
+This variable may be set to one of the values +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
softfloat_round_near_evenround to nearest, with ties to even
softfloat_round_near_maxMag  round to nearest, with ties to maximum magnitude (away from zero)
softfloat_round_minMaground to minimum magnitude (toward zero)
softfloat_round_minround to minimum (down)
softfloat_round_maxround to maximum (up)
softfloat_round_oddround to odd (jamming), if supported by the SoftFloat port
+
+Variable softfloat_roundingMode is initialized to +softfloat_round_near_even. +

+ +

+When softfloat_round_odd is the rounding mode for a function that +rounds to an integer value (either conversion to an integer format or a +‘roundToInt’ function), if the input is not already an +integer, the rounded result is the closest odd integer. +For other operations, this rounding mode acts as though the floating-point +result is first rounded to minimum magnitude, the same as +softfloat_round_minMag, and then, if the result is inexact, the +least-significant bit of the result is set to 1. +Rounding to odd is also known as jamming. +

+ +

6.2. Underflow Detection

+ +

+In the terminology of the IEEE Standard, SoftFloat can detect tininess for +underflow either before or after rounding. +The choice is made by the global variable +

+uint_fast8_t softfloat_detectTininess; +
+which can be set to either +
+softfloat_tininess_beforeRounding
+softfloat_tininess_afterRounding +
+Detecting tininess after rounding is usually better because it results in fewer +spurious underflow signals. +The other option is provided for compatibility with some systems. +Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat +always detects loss of accuracy for underflow as an inexact result. +

+ +

6.3. Rounding Precision for the 80-Bit Extended Format

+ +

+For extFloat80_t only, the rounding precision of the basic +arithmetic operations is controlled by the global variable +

+uint_fast8_t extF80_roundingPrecision; +
+The operations affected are: +
+extF80_add
+extF80_sub
+extF80_mul
+extF80_div
+extF80_sqrt +
+When extF80_roundingPrecision is set to its default value of 80, +these operations are rounded to the full precision of the 80-bit +double-extended-precision format, like occurs for other formats. +Setting extF80_roundingPrecision to 32 or to 64 causes the +operations listed to be rounded to 32-bit precision (equivalent to +float32_t) or to 64-bit precision (equivalent to +float64_t), respectively. +When rounding to reduced precision, additional bits in the result significand +beyond the rounding point are set to zero. +The consequences of setting extF80_roundingPrecision to a value +other than 32, 64, or 80 is not specified. +Operations other than the ones listed above are not affected by +extF80_roundingPrecision. +

+ + +

7. Exceptions and Exception Flags

+ +

+All five exception flags required by the IEEE Floating-Point Standard are +implemented. +Each flag is stored as a separate bit in the global variable +

+uint_fast8_t softfloat_exceptionFlags; +
+The positions of the exception flag bits within this variable are determined by +the bit masks +
+softfloat_flag_inexact
+softfloat_flag_underflow
+softfloat_flag_overflow
+softfloat_flag_infinite
+softfloat_flag_invalid +
+Variable softfloat_exceptionFlags is initialized to all zeros, +meaning no exceptions. +

+ +

+For some SoftFloat ports, softfloat_exceptionFlags may be +per-thread (declared thread_local), meaning that different +execution threads have their own separate instances of it. +

+ +

+An individual exception flag can be cleared with the statement +

+softfloat_exceptionFlags &= ~softfloat_flag_<exception>; +
+where <exception> is the appropriate name. +To raise a floating-point exception, function softfloat_raiseFlags +should normally be used. +

+ +

+When SoftFloat detects an exception other than inexact, it calls +softfloat_raiseFlags. +The default version of this function simply raises the corresponding exception +flags. +Particular ports of SoftFloat may support alternate behavior, such as exception +traps, by modifying the default softfloat_raiseFlags. +A program may also supply its own softfloat_raiseFlags function to +override the one from the SoftFloat library. +

+ +

+Because inexact results occur frequently under most circumstances (and thus are +hardly exceptional), SoftFloat does not ordinarily call +softfloat_raiseFlags for inexact exceptions. +It does always raise the inexact exception flag as required. +

+ + +

8. Function Details

+ +

+In this section, <float> appears in function names as +a substitute for one of these abbreviations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
f16indicates float16_t, passed by value
f32indicates float32_t, passed by value
f64indicates float64_t, passed by value
extF80M   indicates extFloat80_t, passed indirectly via pointers
extF80indicates extFloat80_t, passed by value
f128Mindicates float128_t, passed indirectly via pointers
f128indicates float128_t, passed by value
+
+The circumstances under which values of floating-point types +extFloat80_t and float128_t may be passed either by +value or indirectly via pointers was discussed earlier in +section 4.5, Conventions for Passing Arguments and Results. +

+ +

8.1. Conversions from Integer to Floating-Point

+ +

+All conversions from a 32-bit or 64-bit integer, +signed or unsigned, to a floating-point format are supported. +Functions performing these conversions have these names: +

+ui32_to_<float>
+ui64_to_<float>
+i32_to_<float>
+i64_to_<float> +
+Conversions from 32-bit integers to 64-bit +double-precision and larger formats are always exact, and likewise conversions +from 64-bit integers to 80-bit +double-extended-precision and 128-bit quadruple-precision are also +always exact. +

+ +

+Each conversion function takes one input of the appropriate type and generates +one output. +The following illustrates the signatures of these functions in cases when the +floating-point result is passed either by value or via pointers: +

+
+float64_t i32_to_f64( int32_t a );
+
+
+void i32_to_f128M( int32_t a, float128_t *destPtr );
+
+
+

+ +

8.2. Conversions from Floating-Point to Integer

+ +

+Conversions from a floating-point format to a 32-bit or +64-bit integer, signed or unsigned, are supported with these +functions: +

+<float>_to_ui32
+<float>_to_ui64
+<float>_to_i32
+<float>_to_i64 +
+The functions have signatures as follows, depending on whether the +floating-point input is passed by value or via pointers: +
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+int_fast32_t
+ f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact );
+
+
+

+ +

+The roundingMode argument specifies the rounding mode for +the conversion. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

+A conversion from floating-point to integer format raises the invalid +exception if the source value cannot be rounded to a representable integer of +the desired size (32 or 64 bits). +In such circumstances, the integer result returned is determined by the +particular port of SoftFloat, although typically this value will be either the +maximum or minimum value of the integer format. +The functions that convert to integer types never raise the floating-point +overflow exception. +

+ +

+Because languages such as C require that conversions to integers +be rounded toward zero, the following functions are provided for improved speed +and convenience: +

+<float>_to_ui32_r_minMag
+<float>_to_ui64_r_minMag
+<float>_to_i32_r_minMag
+<float>_to_i64_r_minMag +
+These functions round only toward zero (to minimum magnitude). +The signatures for these functions are the same as above without the redundant +roundingMode argument: +
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact );
+
+
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact );
+
+
+

+ +

8.3. Conversions Among Floating-Point Types

+ +

+Conversions between floating-point formats are done by functions with these +names: +

+<float>_to_<float> +
+All combinations of source and result type are supported where the source and +result are different formats. +There are four different styles of signature for these functions, depending on +whether the input and the output floating-point values are passed by value or +via pointers: +
+
+float32_t f64_to_f32( float64_t a );
+
+
+float32_t f128M_to_f32( const float128_t *aPtr );
+
+
+void f32_to_f128M( float32_t a, float128_t *destPtr );
+
+
+void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *destPtr );
+
+
+

+ +

+Conversions from a smaller to a larger floating-point format are always exact +and so require no rounding. +

+ +

8.4. Basic Arithmetic Functions

+ +

+The following basic arithmetic functions are provided: +

+<float>_add
+<float>_sub
+<float>_mul
+<float>_div
+<float>_sqrt +
+Each floating-point operation takes two operands, except for sqrt +(square root) which takes only one. +The operands and result are all of the same floating-point format. +Signatures for these functions take the following forms: +
+
+float64_t f64_add( float64_t a, float64_t b );
+
+
+void
+ f128M_add(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+float64_t f64_sqrt( float64_t a );
+
+
+void f128M_sqrt( const float128_t *aPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to the input +operands, and the last argument, destPtr, points to the +location where the result is stored. +

+ +

+Rounding of the 80-bit double-extended-precision +(extFloat80_t) functions is affected by variable +extF80_roundingPrecision, as explained earlier in +section 6.3, +Rounding Precision for the 80-Bit Extended Format. +

+ +

8.5. Fused Multiply-Add Functions

+ +

+The 2008 version of the IEEE Floating-Point Standard defines a fused +multiply-add operation that does a combined multiplication and addition +with only a single rounding. +SoftFloat implements fused multiply-add with functions +

+<float>_mulAdd +
+Unlike other operations, fused multiple-add is not supported for the +80-bit double-extended-precision format, +extFloat80_t. +

+ +

+Depending on whether floating-point values are passed by value or via pointers, +the fused multiply-add functions have signatures of these forms: +

+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c );
+
+
+void
+ f128M_mulAdd(
+     const float128_t *aPtr,
+     const float128_t *bPtr,
+     const float128_t *cPtr,
+     float128_t *destPtr
+ );
+
+
+The functions compute +(a × b) + + c +with a single rounding. +When floating-point values are passed indirectly through pointers, arguments +aPtr, bPtr, and +cPtr point to operands a, +b, and c respectively, and +destPtr points to the location where the result is stored. +

+ +

+If one of the multiplication operands a and +b is infinite and the other is zero, these functions raise +the invalid exception even if operand c is a quiet NaN. +

+ +

8.6. Remainder Functions

+ +

+For each format, SoftFloat implements the remainder operation defined by the +IEEE Floating-Point Standard. +The remainder functions have names +

+<float>_rem +
+Each remainder operation takes two floating-point operands of the same format +and returns a result in the same format. +Depending on whether floating-point values are passed by value or via pointers, +the remainder functions have signatures of these forms: +
+
+float64_t f64_rem( float64_t a, float64_t b );
+
+
+void
+ f128M_rem(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to operands +a and b respectively, and +destPtr points to the location where the result is stored. +

+ +

+The IEEE Standard remainder operation computes the value +a + − n × b, +where n is the integer closest to +a ÷ b. +If a ÷ b is exactly +halfway between two integers, n is the even integer closest to +a ÷ b. +The IEEE Standard’s remainder operation is always exact and so requires +no rounding. +

+ +

+Depending on the relative magnitudes of the operands, the remainder +functions can take considerably longer to execute than the other SoftFloat +functions. +This is an inherent characteristic of the remainder operation itself and is not +a flaw in the SoftFloat implementation. +

+ +

8.7. Round-to-Integer Functions

+ +

+For each format, SoftFloat implements the round-to-integer operation specified +by the IEEE Floating-Point Standard. +These functions are named +

+<float>_roundToInt +
+Each round-to-integer operation takes a single floating-point operand. +This operand is rounded to an integer according to a specified rounding mode, +and the resulting integer value is returned in the same floating-point format. +(Note that the result is not an integer type.) +

+ +

+The signatures of the round-to-integer functions are similar to those for +conversions to an integer type: +

+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+void
+ f128M_roundToInt(
+     const float128_t *aPtr,
+     uint_fast8_t roundingMode,
+     bool exact,
+     float128_t *destPtr
+ );
+
+
+When floating-point values are passed indirectly through pointers, +aPtr points to the input operand and +destPtr points to the location where the result is stored. +

+ +

+The roundingMode argument specifies the rounding mode to +apply. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

8.8. Comparison Functions

+ +

+For each format, the following floating-point comparison functions are +provided: +

+<float>_eq
+<float>_le
+<float>_lt +
+Each comparison takes two operands of the same type and returns a Boolean. +The abbreviation eq stands for “equal” (=); +le stands for “less than or equal” (≤); +and lt stands for “less than” (<). +Depending on whether the floating-point operands are passed by value or via +pointers, the comparison functions have signatures of these forms: +
+
+bool f64_eq( float64_t a, float64_t b );
+
+
+bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr );
+
+
+

+ +

+The usual greater-than (>), greater-than-or-equal (≥), and not-equal +(≠) comparisons are easily obtained from the functions provided. +The not-equal function is just the logical complement of the equal function. +The greater-than-or-equal function is identical to the less-than-or-equal +function with the arguments in reverse order, and likewise the greater-than +function is identical to the less-than function with the arguments reversed. +

+ +

+The IEEE Floating-Point Standard specifies that the less-than-or-equal and +less-than comparisons by default raise the invalid exception if either +operand is any kind of NaN. +Equality comparisons, on the other hand, are defined by default to raise the +invalid exception only for signaling NaNs, not quiet NaNs. +For completeness, SoftFloat provides these complementary functions: +

+<float>_eq_signaling
+<float>_le_quiet
+<float>_lt_quiet +
+The signaling equality comparisons are identical to the default +equality comparisons except that the invalid exception is raised for any +NaN input, not just for signaling NaNs. +Similarly, the quiet comparison functions are identical to their +default counterparts except that the invalid exception is not raised for +quiet NaNs. +

+ +

8.9. Signaling NaN Test Functions

+ +

+Functions for testing whether a floating-point value is a signaling NaN are +provided with these names: +

+<float>_isSignalingNaN +
+The functions take one floating-point operand and return a Boolean indicating +whether the operand is a signaling NaN. +Accordingly, the functions have the forms +
+
+bool f64_isSignalingNaN( float64_t a );
+
+
+bool f128M_isSignalingNaN( const float128_t *aPtr );
+
+
+

+ +

8.10. Raise-Exception Function

+ +

+SoftFloat provides a single function for raising floating-point exceptions: +

+
+void softfloat_raiseFlags( uint_fast8_t exceptions );
+
+
+The exceptions argument is a mask indicating the set of +exceptions to raise. +(See earlier section 7, Exceptions and Exception Flags.) +In addition to setting the specified exception flags in variable +softfloat_exceptionFlags, the softfloat_raiseFlags +function may cause a trap or abort appropriate for the current system. +

+ + +

9. Changes from SoftFloat Release 2

+ +

+Apart from a change in the legal use license, Release 3 of +SoftFloat introduced numerous technical differences compared to earlier +releases. +

+ +

9.1. Name Changes

+ +

+The most obvious and pervasive difference compared to Release 2 +is that the names of most functions and variables have changed, even when the +behavior has not. +First, the floating-point types, the mode variables, the exception flags +variable, the function to raise exceptions, and various associated constants +have been renamed as follows: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
old name, Release 2:new name, Release 3:
float32float32_t
float64float64_t
floatx80extFloat80_t
float128float128_t
float_rounding_modesoftfloat_roundingMode
float_round_nearest_evensoftfloat_round_near_even
float_round_to_zerosoftfloat_round_minMag
float_round_downsoftfloat_round_min
float_round_upsoftfloat_round_max
float_detect_tininesssoftfloat_detectTininess
float_tininess_before_rounding    softfloat_tininess_beforeRounding
float_tininess_after_roundingsoftfloat_tininess_afterRounding
floatx80_rounding_precisionextF80_roundingPrecision
float_exception_flagssoftfloat_exceptionFlags
float_flag_inexactsoftfloat_flag_inexact
float_flag_underflowsoftfloat_flag_underflow
float_flag_overflowsoftfloat_flag_overflow
float_flag_divbyzerosoftfloat_flag_infinite
float_flag_invalidsoftfloat_flag_invalid
float_raisesoftfloat_raiseFlags
+
+

+ +

+Furthermore, Release 3 adopted the following new abbreviations for +function names: +

+ + + + + + + + + + + +
used in names in Release 2:    used in names in Release 3:
int32 i32
int64 i64
float32 f32
float64 f64
floatx80 extF80
float128 f128
+
+Thus, for example, the function to add two 32-bit floating-point +numbers, previously called float32_add in Release 2, +is now f32_add. +Lastly, there have been a few other changes to function names: +
+ + + + + + + + + + + + + + + + + + + + + +
used in names in Release 2:   used in names in Release 3:   relevant functions:
_round_to_zero_r_minMagconversions from floating-point to integer (section 8.2)
round_to_introundToIntround-to-integer functions (section 8.7)
is_signaling_nan    isSignalingNaNsignaling NaN test functions (section 8.9)
+
+

+ +

9.2. Changes to Function Arguments

+ +

+Besides simple name changes, some operations were given a different interface +in Release 3 than they had in Release 2: +

    + +
  • +

    +Since Release 3, integer arguments and results of functions have +standard types from header <stdint.h>, such as +uint32_t, whereas previously their types could be defined +differently for each port of SoftFloat, usually using traditional C types such +as unsigned int. +Likewise, functions in Release 3 and later pass Booleans as +standard type bool from <stdbool.h>, whereas +previously these were again passed as a port-specific type (usually +int). +

    + +
  • +

    +As explained earlier in section 4.5, Conventions for Passing +Arguments and Results, SoftFloat functions in Release 3 and +later may pass 80-bit and 128-bit floating-point +values through pointers, meaning that functions take pointer arguments and then +read or write floating-point values at the locations indicated by the pointers. +In Release 2, floating-point arguments and results were always +passed by value, regardless of their size. +

    + +
  • +

    +Functions that round to an integer have additional +roundingMode and exact arguments that +they did not have in Release 2. +Refer to sections 8.2 and 8.7 for descriptions of these functions +since Release 3. +For Release 2, the rounding mode, when needed, was taken from the +same global variable that affects the basic arithmetic operations (now called +softfloat_roundingMode but previously known as +float_rounding_mode). +Also, for Release 2, if the original floating-point input was not +an exact integer value, and if the invalid exception was not raised by +the function, the inexact exception was always raised. +Release 2 had no option to suppress raising inexact in this +case. +Applications using SoftFloat Release 3 or later can get the same +effect as Release 2 by passing variable +softfloat_roundingMode for argument +roundingMode and true for argument +exact. +

    + +
+

+ +

9.3. Added Capabilities

+ +

+With Release 3, some new features have been added that were not +present in Release 2: +

    + +
  • +

    +A port of SoftFloat can now define any of the floating-point types +float32_t, float64_t, extFloat80_t, and +float128_t as aliases for C’s standard floating-point types +float, double, and long +double, using either #define or typedef. +This potential convenience was not supported under Release 2. +

    + +

    +(Note, however, that there may be a performance cost to defining +SoftFloat’s floating-point types this way, depending on the platform and +the applications using SoftFloat. +Ports of SoftFloat may choose to forgo the convenience in favor of better +speed.) +

    + +

    +

  • +As of Release 3b, 16-bit half-precision, +float16_t, is supported. +

    + +

    +

  • +Functions have been added for converting between the floating-point types and +unsigned integers. +Release 2 supported only signed integers, not unsigned. +

    + +

    +

  • +Fused multiply-add functions have been added for all floating-point formats +except 80-bit double-extended-precision, +extFloat80_t. +

    + +

    +

  • +New rounding modes are supported: +softfloat_round_near_maxMag (round to nearest, with ties to +maximum magnitude, away from zero), and, as of Release 3c, +optional softfloat_round_odd (round to odd, also known as +jamming). +

    + +
+

+ +

9.4. Better Compatibility with the C Language

+ +

+Release 3 of SoftFloat was written to conform better to the ISO C +Standard’s rules for portability. +For example, older releases of SoftFloat employed type conversions in ways +that, while commonly practiced, are not fully defined by the C Standard. +Such problematic type conversions have generally been replaced by the use of +unions, the behavior around which is more strictly regulated these days. +

+ +

9.5. New Organization as a Library

+ +

+Starting with Release 3, SoftFloat now builds as a library. +Previously, SoftFloat compiled into a single, monolithic object file containing +all the SoftFloat functions, with the consequence that a program linking with +SoftFloat would get every SoftFloat function in its binary file even if only a +few functions were actually used. +With SoftFloat in the form of a library, a program that is linked by a standard +linker will include only those functions of SoftFloat that it needs and no +others. +

+ +

9.6. Optimization Gains (and Losses)

+ +

+Individual SoftFloat functions have been variously improved in +Release 3 compared to earlier releases. +In particular, better, faster algorithms have been deployed for the operations +of division, square root, and remainder. +For functions operating on the larger 80-bit and +128-bit formats, extFloat80_t and +float128_t, code size has also generally been reduced. +

+ +

+However, because Release 2 compiled all of SoftFloat together as a +single object file, compilers could make optimizations across function calls +when one SoftFloat function calls another. +Now that the functions of SoftFloat are compiled separately and only afterward +linked together into a program, there is not usually the same opportunity to +optimize across function calls. +Some loss of speed has been observed due to this change. +

+ + +

10. Future Directions

+ +

+The following improvements are anticipated for future releases of SoftFloat: +

    +
  • +more functions from the 2008 version of the IEEE Floating-Point Standard; +
  • +consistent, defined behavior for non-canonical representations of extended +format extFloat80_t (discussed in section 4.4, +Non-canonical Representations in extFloat80_t). + +
+

+ + +

11. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/cpu/softfloat3e/extF80_addsub.cc b/src/cpu/softfloat3e/extF80_addsub.cc new file mode 100644 index 000000000..a60d2c6be --- /dev/null +++ b/src/cpu/softfloat3e/extF80_addsub.cc @@ -0,0 +1,106 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extern extFloat80_t softfloat_addMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *); +extern extFloat80_t softfloat_subMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *); + +extFloat80_t extF80_add(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + a.signExp = defaultNaNExtF80UI64; + a.signif = defaultNaNExtF80UI0; + return a; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + + if (signA == signB) { + return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} + +extFloat80_t extF80_sub(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + a.signExp = defaultNaNExtF80UI64; + a.signif = defaultNaNExtF80UI0; + return a; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + + if (signA == signB) { + return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} diff --git a/src/cpu/softfloat3e/extF80_class.cc b/src/cpu/softfloat3e/extF80_class.cc new file mode 100644 index 000000000..155dc51a2 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_class.cc @@ -0,0 +1,71 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t extF80_class(extFloat80_t a) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + + if (! expA) { + if (! sigA) return softfloat_zero; + return softfloat_denormal; /* denormal or pseudo-denormal */ + } + + /* valid numbers have the MS bit set */ + if (!(sigA & UINT64_C(0x8000000000000000))) + return softfloat_SNaN; /* report unsupported as SNaNs */ + + if (expA == 0x7FFF) { + if ((sigA<<1) == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & UINT64_C(0x4000000000000000)) ? softfloat_QNaN : softfloat_SNaN; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/extF80_compare.cc b/src/cpu/softfloat3e/extF80_compare.cc new file mode 100644 index 000000000..f8a360a41 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_compare.cc @@ -0,0 +1,147 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include <86box/86box.h> +#include "../cpu.h" + +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two extended precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int extF80_compare(extFloat80_t a, extFloat80_t b, int quiet, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + softfloat_class_t aClass = extF80_class(a); + softfloat_class_t bClass = extF80_class(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (fpu_type < FPU_287XL) { + if ((aClass == softfloat_positive_inf) && (bClass == softfloat_negative_inf)) + { + return softfloat_relation_equal; + } + + if ((aClass == softfloat_negative_inf) && (bClass == softfloat_positive_inf)) + { + return softfloat_relation_equal; + } + } + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) + { + /* unsupported reported as SNaN */ + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_denormal || bClass == softfloat_denormal) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_zero) { + if (bClass == softfloat_zero) return softfloat_relation_equal; + return signB ? softfloat_relation_greater : softfloat_relation_less; + } + + if (bClass == softfloat_zero || signA != signB) { + return signA ? softfloat_relation_less : softfloat_relation_greater; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_denormal) { + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp + 1; + sigA = normExpSig.sig; + } + if (bClass == softfloat_denormal) { + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expA == expB && sigA == sigB) + return softfloat_relation_equal; + + int less_than = + signA ? ((expB < expA) || ((expB == expA) && (sigB < sigA))) + : ((expA < expB) || ((expA == expB) && (sigA < sigB))); + + if (less_than) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/extF80_div.cc b/src/cpu/softfloat3e/extF80_div.cc new file mode 100644 index 000000000..e4b1fbb24 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_div.cc @@ -0,0 +1,188 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + bool signZ; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint128 rem; + uint32_t recip32; + uint64_t sigZ; + int ix; + uint64_t q64; + uint32_t q; + struct uint128 term; + uint64_t sigZExtra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + goto invalid; + } + if (! expB && sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + if (! expA && sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) { + if (! sigA) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) return packToExtF80(signZ, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFF; + if (sigA < sigB) { + --expZ; + rem = softfloat_shortShiftLeft128(0, sigA, 32); + } else { + rem = softfloat_shortShiftLeft128(0, sigA, 31); + } + recip32 = softfloat_approxRecip32_1(sigB>>32); + sigZ = 0; + ix = 2; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if (ix < 0) break; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB>>32, sigB<<32); + } + sigZ = (sigZ<<29) + q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (((q + 1) & 0x3FFFFF) < 2) { + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + term = softfloat_shortShiftLeft128(0, sigB, 32); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, term.v64, term.v0); + } else if (softfloat_le128(term.v64, term.v0, rem.v64, rem.v0)) { + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + } + if (rem.v64 | rem.v0) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ = (sigZ<<6) + (q>>23); + sigZExtra = (uint64_t) ((uint64_t) q<<41); + return + softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); +} diff --git a/src/cpu/softfloat3e/extF80_extract.cc b/src/cpu/softfloat3e/extF80_extract.cc new file mode 100644 index 000000000..692190a47 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_extract.cc @@ -0,0 +1,97 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Separate the source extended double-precision floating point value `a' +| into its exponent and significand, store the significant back to the +| 'a' and return the exponent. The operation performed is a superset of +| the IEC/IEEE recommended logb(x) function. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_extract(extFloat80_t *a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(*a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + *a = packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + return *a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a->signExp; + uiA0 = a->signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA<<1) { + *a = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); + return *a; + } + return packToExtF80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + softfloat_raiseFlags(status, softfloat_flag_divbyzero); + *a = packToExtF80(signA, 0, 0); + return packToExtF80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + + *a = packToExtF80(signA, 0x3FFF, sigA); + return i32_to_extF80(expA - 0x3FFF); +} diff --git a/src/cpu/softfloat3e/extF80_mul.cc b/src/cpu/softfloat3e/extF80_mul.cc new file mode 100644 index 000000000..d38e97f02 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_mul.cc @@ -0,0 +1,153 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + bool signZ; + uint64_t magBits; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint128 sig128Z; + uint16_t uiZ64; + uint64_t uiZ0; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) { + goto propagateNaN; + } + magBits = expB | sigB; + goto infArg; + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) { + if (! expB && sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) return packToExtF80(signZ, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sig128Z = softfloat_mul64To128(sigA, sigB); + if (sig128Z.v64 < UINT64_C(0x8000000000000000)) { + --expZ; + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); + } + return + softfloat_roundPackToExtF80(signZ, expZ, sig128Z.v64, sig128Z.v0, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + } else { + if ((! expA && sigA) || (! expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + uiZ64 = packToExtF80UI64(signZ, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/extF80_rem.cc b/src/cpu/softfloat3e/extF80_rem.cc new file mode 100644 index 000000000..39d233a7e --- /dev/null +++ b/src/cpu/softfloat3e/extF80_rem.cc @@ -0,0 +1,199 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + int32_t expDiff; + struct uint128 rem, shiftedSigB; + uint32_t q, recip32; + uint64_t q64; + struct uint128 term, altRem, meanRem; + bool signRem; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) { + goto propagateNaN; + } + goto invalid; + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + /*-------------------------------------------------------------------- + | Argument b is an infinity. Doubling `expB' is an easy way to ensure + | that `expDiff' later is less than -1, which will result in returning + | a canonicalized version of argument a. + *--------------------------------------------------------------------*/ + expB += expB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) goto invalid; + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) { + expA = 0; + goto copyA; + } + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (expDiff < -1) goto copyA; + rem = softfloat_shortShiftLeft128(0, sigA, 32); + shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 32); + if (expDiff < 1) { + if (expDiff) { + --expB; + shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 33); + q = 0; + } else { + q = (sigB <= sigA); + if (q) { + rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } + } + } else { + recip32 = softfloat_approxRecip32_1(sigB>>32); + expDiff -= 30; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32; + if (expDiff < 0) break; + q = (q64 + 0x80000000)>>32; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + rem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, expDiff + 30); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + altRem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } while (! (rem.v64 & UINT64_C(0x8000000000000000))); + selectRem: + meanRem = softfloat_add128(rem.v64, rem.v0, altRem.v64, altRem.v0); + if ((meanRem.v64 & UINT64_C(0x8000000000000000)) || (! (meanRem.v64 | meanRem.v0) && (q & 1))) { + rem = altRem; + } + signRem = signA; + if (rem.v64 & UINT64_C(0x8000000000000000)) { + signRem = ! signRem; + rem = softfloat_sub128(0, 0, rem.v64, rem.v0); + } + return softfloat_normRoundPackToExtF80(signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + if (expA < 1) { + sigA >>= 1 - expA; + expA = 0; + } + return packToExtF80(signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/extF80_roundToInt.cc b/src/cpu/softfloat3e/extF80_roundToInt.cc new file mode 100644 index 000000000..f71cdfc50 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_roundToInt.cc @@ -0,0 +1,123 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + extF80_roundToInt(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64, signUI64; + int32_t exp; + uint64_t sigA; + uint16_t uiZ64; + uint64_t sigZ; + uint64_t lastBitMask, roundBitsMask; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + signUI64 = uiA64 & packToExtF80UI64(1, 0); + exp = expExtF80UI64(uiA64); + sigA = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x403E <= exp) { + if ((exp == 0x7FFF) && (uint64_t) (sigA<<1)) { + return softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp <= 0x3FFE) { + if (! exp) { + if ((sigA<<1) == 0) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + switch (roundingMode) { + case softfloat_round_near_even: + if (!(sigA & UINT64_C(0x7FFFFFFFFFFFFFFF))) break; + case softfloat_round_near_maxMag: + if (exp == 0x3FFE) goto mag1; + break; + case softfloat_round_min: + if (signUI64) goto mag1; + break; + case softfloat_round_max: + if (!signUI64) goto mag1; + break; + } + return packToExtF80(signUI64, 0, 0); + mag1: + softfloat_setRoundingUp(status); + return packToExtF80(signUI64, 0x3FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = signUI64 | exp; + lastBitMask = (uint64_t) 1<<(0x403E - exp); + roundBitsMask = lastBitMask - 1; + sigZ = sigA; + if (roundingMode == softfloat_round_near_maxMag) { + sigZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + sigZ += lastBitMask>>1; + if (!(sigZ & roundBitsMask)) sigZ &= ~lastBitMask; + } else if (roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)) { + sigZ += roundBitsMask; + } + sigZ &= ~roundBitsMask; + if (!sigZ) { + ++uiZ64; + sigZ = UINT64_C(0x8000000000000000); + softfloat_setRoundingUp(status); + } + if (sigZ != sigA) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sigZ > sigA) + softfloat_setRoundingUp(status); + } + return packToExtF80_twoargs(uiZ64, sigZ); +} diff --git a/src/cpu/softfloat3e/extF80_scale.cc b/src/cpu/softfloat3e/extF80_scale.cc new file mode 100644 index 000000000..48bd53afd --- /dev/null +++ b/src/cpu/softfloat3e/extF80_scale.cc @@ -0,0 +1,136 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_scale(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + + if (expA == 0x7FFF) { + if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expB == 0x7FFF) && signB) goto invalid; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return a; + } + if (expB == 0x7FFF) { + if (sigB<<1) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expA | sigA) == 0) { + if (! signB) goto invalid; + return a; + } + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (signB) return packToExtF80(signA, 0, 0); + return packToExtF80(signA, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (! expA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + if (expB < 0x3FFF) + return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80, status); + } + if (!expB) { + if (!sigB) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expB > 0x400E) { + /* generate appropriate overflow/underflow */ + return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80, status); + } + + if (expB < 0x3FFF) return a; + + int shiftCount = 0x403E - expB; + sigB >>= shiftCount; + int32_t scale = (int32_t) sigB; + if (signB) scale = -scale; /* -32768..32767 */ + + return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80, status); +} diff --git a/src/cpu/softfloat3e/extF80_sqrt.cc b/src/cpu/softfloat3e/extF80_sqrt.cc new file mode 100644 index 000000000..1a5d52e5d --- /dev/null +++ b/src/cpu/softfloat3e/extF80_sqrt.cc @@ -0,0 +1,159 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + struct exp32_sig64 normExpSig; + int32_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + struct uint128 rem; + uint64_t q, x64, sigZ; + struct uint128 y, term; + uint64_t sigZExtra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if ((expA | sigA) == 0) return packToExtF80(signA, 0, 0); + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) return packToExtF80(signA, 0, 0); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; + expA &= 1; + sig32A = sigA>>32; + recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if (expA) { + sig32Z >>= 1; + rem = softfloat_shortShiftLeft128(0, sigA, 61); + } else { + rem = softfloat_shortShiftLeft128(0, sigA, 62); + } + rem.v64 -= (uint64_t) sig32Z * sig32Z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint32_t) (rem.v64>>2) * (uint64_t) recipSqrt32)>>32; + x64 = (uint64_t) sig32Z<<32; + sigZ = x64 + (q<<3); + y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + /*------------------------------------------------------------------------ + | (Repeating this loop is a rare occurrence.) + *------------------------------------------------------------------------*/ + for (;;) { + term = softfloat_mul64ByShifted32To128(x64 + sigZ, q); + rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0); + if (! (rem.v64 & UINT64_C(0x8000000000000000))) break; + --q; + sigZ -= 1<<3; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((rem.v64>>2) * recipSqrt32)>>32) + 2; + x64 = sigZ; + sigZ = (sigZ<<1) + (q>>25); + sigZExtra = (uint64_t) (q<<39); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((q & 0xFFFFFF) <= 2) { + q &= ~(uint64_t) 0xFFFF; + sigZExtra = (uint64_t) (q<<39); + term = softfloat_mul64ByShifted32To128(x64 + (q>>27), q); + x64 = (uint32_t) (q<<5) * (uint64_t) (uint32_t) q; + term = softfloat_add128(term.v64, term.v0, 0, x64); + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 28); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + if (! sigZExtra) --sigZ; + --sigZExtra; + } else { + if (rem.v64 | rem.v0) sigZExtra |= 1; + } + } + return + softfloat_roundPackToExtF80(0, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); +} diff --git a/src/cpu/softfloat3e/extF80_to_f128.cc b/src/cpu/softfloat3e/extF80_to_f128.cc new file mode 100644 index 000000000..24e523cac --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f128.cc @@ -0,0 +1,75 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t extF80_to_f128(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + uint16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + bool sign; + struct uint128 frac128; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + exp = expExtF80UI64(uiA64); + frac = uiA0 & UINT64_C(0x7FFFFFFFFFFFFFFF); + if ((exp == 0x7FFF) && frac) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + sign = signExtF80UI64(uiA64); + frac128 = softfloat_shortShiftLeft128(0, frac, 49); + uiZ.v64 = packToF128UI64(sign, exp, frac128.v64); + uiZ.v0 = frac128.v0; + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/extF80_to_f16.cc b/src/cpu/softfloat3e/extF80_to_f16.cc new file mode 100644 index 000000000..5078e689c --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f16.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint16_t uiZ, sig16; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig16 = softfloat_shortShiftRightJam64(sig, 49); + if (! (exp | sig16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3FF1; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x40) exp = -0x40; + } + return softfloat_roundPackToF16(sign, exp, sig16, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_f32.cc b/src/cpu/softfloat3e/extF80_to_f32.cc new file mode 100644 index 000000000..558df4c23 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f32.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint32_t uiZ, sig32; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = softfloat_shortShiftRightJam64(sig, 33); + if (! (exp | sig32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3F81; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF32(sign, exp, sig32, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_f64.cc b/src/cpu/softfloat3e/extF80_to_f64.cc new file mode 100644 index 000000000..4ba4174e3 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f64.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint64_t uiZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! (exp | sig)) { + return packToF64UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = softfloat_shortShiftRightJam64(sig, 1); + exp -= 0x3C01; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF64(sign, exp, sig, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i32.cc b/src/cpu/softfloat3e/extF80_to_i32.cc new file mode 100644 index 000000000..ea6c94484 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i32.cc @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t extF80_to_i32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x4032 - exp; + if (shiftDist <= 0) shiftDist = 1; + sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc new file mode 100644 index 000000000..42415c459 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc @@ -0,0 +1,93 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t extF80_to_i32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + int32_t absZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (shiftDist < 33) { + if ((uiA64 == packToExtF80UI64(1, 0x401E)) && (sig < UINT64_C(0x8000000100000000))) { + if (exact && (sig & UINT64_C(0x00000000FFFFFFFF))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + absZ = sig>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t extF80_to_i64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + uint64_t sigExtra; + struct uint64_extra sig64Extra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigExtra = 0; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return softfloat_roundToI64(sign, sig, sigExtra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc new file mode 100644 index 000000000..3500b20d2 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc @@ -0,0 +1,90 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t extF80_to_i64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + int64_t absZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (shiftDist <= 0) { + if ((uiA64 == packToExtF80UI64(1, 0x403E)) && (sig == UINT64_C(0x8000000000000000))) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + absZ = sig>>shiftDist; + if (exact && (uint64_t) (sig<<(-shiftDist & 63))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return sign ? -absZ : absZ; +} diff --git a/src/cpu/softfloat3e/extF80_to_ui32.cc b/src/cpu/softfloat3e/extF80_to_ui32.cc new file mode 100644 index 000000000..449cafa88 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui32.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t + extF80_to_ui32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x4032 - exp; + if (shiftDist <= 0) shiftDist = 1; + sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToUI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc new file mode 100644 index 000000000..7ef100139 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t extF80_to_ui32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + uint32_t z; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (sign || (shiftDist < 32)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z = sig>>shiftDist; + if (exact && ((uint64_t) z< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t extF80_to_ui64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + uint64_t sigExtra; + struct uint64_extra sig64Extra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigExtra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return softfloat_roundToUI64(sign, sig, sigExtra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc new file mode 100644 index 000000000..78b058754 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t extF80_to_ui64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + uint64_t z; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z = sig>>shiftDist; + if (exact && (z< +#include +#include "internals.h" +#include "softfloat.h" + +extern float128_t + softfloat_addMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float128_t + softfloat_subMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *); + +float128_t f128_add(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + uint64_t uiB64, uiB0; + bool signB; + + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + + if (signA == signB) { + return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} + +float128_t f128_sub(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + uint64_t uiB64, uiB0; + bool signB; + + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + + if (signA == signB) { + return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} diff --git a/src/cpu/softfloat3e/f128_div.cc b/src/cpu/softfloat3e/f128_div.cc new file mode 100644 index 000000000..837eb15aa --- /dev/null +++ b/src/cpu/softfloat3e/f128_div.cc @@ -0,0 +1,187 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_div(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + int32_t expA; + struct uint128 sigA; + uint64_t uiB64, uiB0; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signZ; + struct exp32_sig128 normExpSig; + int32_t expZ; + struct uint128 rem; + uint32_t recip32; + int ix; + uint64_t q64; + uint32_t q; + struct uint128 term; + uint32_t qs[3]; + uint64_t sigZExtra; + struct uint128 sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! (sigB.v64 | sigB.v0)) { + if (! (expA | sigA.v64 | sigA.v0)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFE; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB.v64 |= UINT64_C(0x0001000000000000); + rem = sigA; + if (softfloat_lt128(sigA.v64, sigA.v0, sigB.v64, sigB.v0)) { + --expZ; + rem = softfloat_add128(sigA.v64, sigA.v0, sigA.v64, sigA.v0); + } + recip32 = softfloat_approxRecip32_1(sigB.v64>>17); + ix = 3; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>19) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if (ix < 0) break; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul128By32(sigB.v64, sigB.v0, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } + qs[ix] = q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (((q + 1) & 7) < 2) { + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul128By32(sigB.v64, sigB.v0, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } else if (softfloat_le128(sigB.v64, sigB.v0, rem.v64, rem.v0)) { + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } + if (rem.v64 | rem.v0) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZExtra = (uint64_t) ((uint64_t) q<<60); + term = softfloat_shortShiftLeft128(0, qs[1], 54); + sigZ = softfloat_add128((uint64_t) qs[2]<<19, ((uint64_t) qs[0]<<25) + (q>>4), term.v64, term.v0); + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64(signZ, 0, 0); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_mul.cc b/src/cpu/softfloat3e/f128_mul.cc new file mode 100644 index 000000000..fd63a4590 --- /dev/null +++ b/src/cpu/softfloat3e/f128_mul.cc @@ -0,0 +1,148 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_mul(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + int32_t expA; + struct uint128 sigA; + uint64_t uiB64, uiB0; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signZ; + uint64_t magBits; + struct exp32_sig128 normExpSig; + int32_t expZ; + uint64_t sig256Z[4]; + uint64_t sigZExtra; + struct uint128 sigZ; + struct uint128_extra sig128Extra; + struct uint128 uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { + goto propagateNaN; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infArg; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + magBits = expA | sigA.v64 | sigA.v0; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! (sigB.v64 | sigB.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x4000; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 16); + softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); + sigZExtra = sig256Z[indexWord(4, 1)] | (sig256Z[indexWord(4, 0)] != 0); + sigZ = softfloat_add128(sig256Z[indexWord(4, 3)], sig256Z[indexWord(4, 2)], sigA.v64, sigA.v0); + if (UINT64_C(0x0002000000000000) <= sigZ.v64) { + ++expZ; + sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.v64, sigZ.v0, sigZExtra, 1); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64(signZ, 0, 0); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_mulAdd.cc b/src/cpu/softfloat3e/f128_mulAdd.cc new file mode 100644 index 000000000..749342f5f --- /dev/null +++ b/src/cpu/softfloat3e/f128_mulAdd.cc @@ -0,0 +1,332 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" +#include "softfloat.h" +#include "specialize.h" + +float128_t f128_mulAdd(float128_t a, float128_t b, float128_t c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int32_t expA; + struct uint128 sigA; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signC; + int32_t expC; + struct uint128 sigC; + bool signZ; + uint64_t magBits; + struct uint128 uiZ; + struct exp32_sig128 normExpSig; + int32_t expZ; + uint64_t sig256Z[4]; + struct uint128 sigZ; + int32_t shiftDist, expDiff; + struct uint128 x128; + uint64_t sig256C[4]; + static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0); + uint64_t sigZExtra, sig256Z0; + uint64_t uiA64, uiA0; + uint64_t uiB64, uiB0; + uint64_t uiC64, uiC0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + uiB64 = b.v64; + uiB0 = b.v0; + uiC64 = c.v64; + uiC0 = c.v0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF128UI64(uiC64); + sigC.v64 = fracF128UI64(uiC64); + sigC.v0 = uiC0; + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { + goto propagateNaN_ABC; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infProdArg; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN_ABC; + magBits = expA | sigA.v64 | sigA.v0; + goto infProdArg; + } + if (expC == 0x7FFF) { + if (sigC.v64 | sigC.v0) { + uiZ.v64 = 0; + uiZ.v0 = 0; + goto propagateNaN_ZC; + } + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! (sigB.v64 | sigB.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB.v64 |= UINT64_C(0x0001000000000000); + sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15); + softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + shiftDist = 0; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = -1; + } + if (! expC) { + if (! (sigC.v64 | sigC.v0)) { + shiftDist += 8; + goto sigZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC.v64 |= UINT64_C(0x0001000000000000); + sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + shiftDist -= expDiff; + if (shiftDist) { + sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist); + } + } else { + if (! shiftDist) { + x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1); + sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64; + sig256Z[indexWord(4, 0)] = x128.v0; + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1); + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + } + } + } else { + if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z); + if (! expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_shiftRightJam256M(sig256C, expDiff, sig256C); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 8; + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + } else { + softfloat_add256M(sig256Z, sig256C, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } + if (sigZ.v64 & UINT64_C(0x0200000000000000)) { + ++expZ; + shiftDist = 9; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + if (expDiff < -1) { + sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + if (sigZExtra) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1); + } + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto shiftRightRoundPack; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_sub256M(sig256C, sig256Z, sig256Z); + } + } else if (! expDiff) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0); + if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) { + goto completeCancellation; + } + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + if (sigZ.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + softfloat_sub256M(zero256, sig256Z, sig256Z); + } + } else { + softfloat_sub256M(sig256Z, sig256C, sig256Z); + if (1 < expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + sigZExtra = sig256Z[indexWord(4, 1)]; + sig256Z0 = sig256Z[indexWord(4, 0)]; + if (sigZ.v64) { + if (sig256Z0) sigZExtra |= 1; + } else { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = sig256Z0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = 0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = 0; + } + } + } + shiftDist = softfloat_countLeadingZeros64(sigZ.v64); + expZ += 7 - shiftDist; + shiftDist = 15 - shiftDist; + if (0 < shiftDist) goto shiftRightRoundPack; + if (shiftDist) { + shiftDist = -shiftDist; + sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist); + x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist); + sigZ.v0 |= x128.v64; + sigZExtra = x128.v0; + } + goto roundPack; + } + sigZ: + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + shiftRightRoundPack: + sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0); + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist); + roundPack: + return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC; + if (magBits) { + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + if (expC != 0x7FFF) return uiZ; + if (signZ == signC) return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) { + completeCancellation: + uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + uiZ.v0 = 0; + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_roundToInt.cc b/src/cpu/softfloat3e/f128_roundToInt.cc new file mode 100644 index 000000000..c3b728704 --- /dev/null +++ b/src/cpu/softfloat3e/f128_roundToInt.cc @@ -0,0 +1,142 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + f128_roundToInt(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + struct uint128 uiZ; + uint64_t lastBitMask0, roundBitsMask; + bool roundNearEven; + uint64_t lastBitMask64; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x402F <= exp) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (0x406F <= exp) { + if ((exp == 0x7FFF) && (fracF128UI64(uiA64) | uiA0)) { + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, 0, 0, status); + return uiZ; + } + return a; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + lastBitMask0 = (uint64_t) 2<<(0x406E - exp); + roundBitsMask = lastBitMask0 - 1; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + roundNearEven = (roundingMode == softfloat_round_near_even); + if (roundNearEven || (roundingMode == softfloat_round_near_maxMag)) { + if (exp == 0x402F) { + if (UINT64_C(0x8000000000000000) <= uiZ.v0) { + ++uiZ.v64; + if (roundNearEven && (uiZ.v0 == UINT64_C(0x8000000000000000))) { + uiZ.v64 &= ~1; + } + } + } else { + uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, lastBitMask0>>1); + if (roundNearEven && !(uiZ.v0 & roundBitsMask)) { + uiZ.v0 &= ~lastBitMask0; + } + } + } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) { + uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, roundBitsMask); + } + uiZ.v0 &= ~roundBitsMask; + lastBitMask64 = !lastBitMask0; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp < 0x3FFF) { + if (!((uiA64 & UINT64_C(0x7FFFFFFFFFFFFFFF)) | uiA0)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ.v64 = uiA64 & packToF128UI64(1, 0, 0); + uiZ.v0 = 0; + switch (roundingMode) { + case softfloat_round_near_even: + if (!(fracF128UI64(uiA64) | uiA0)) break; + case softfloat_round_near_maxMag: + if (exp == 0x3FFE) uiZ.v64 |= packToF128UI64(0, 0x3FFF, 0); + break; + case softfloat_round_min: + if (uiZ.v64) uiZ.v64 = packToF128UI64(1, 0x3FFF, 0); + break; + case softfloat_round_max: + if (!uiZ.v64) uiZ.v64 = packToF128UI64(0, 0x3FFF, 0); + break; + } + return uiZ; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + uiZ.v64 = uiA64; + uiZ.v0 = 0; + lastBitMask64 = (uint64_t) 1<<(0x402F - exp); + roundBitsMask = lastBitMask64 - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ.v64 += lastBitMask64>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ.v64 += lastBitMask64>>1; + if (!((uiZ.v64 & roundBitsMask) | uiA0)) { + uiZ.v64 &= ~lastBitMask64; + } + } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) { + uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask; + } + uiZ.v64 &= ~roundBitsMask; + lastBitMask0 = 0; + } + if ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_to_extF80.cc b/src/cpu/softfloat3e/f128_to_extF80.cc new file mode 100644 index 000000000..916820bc9 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_extF80.cc @@ -0,0 +1,94 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f128_to_extF80(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64, frac0; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp32_sig128 normExpSig; + struct uint128 sig128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64); + frac0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64 | frac0) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! (frac64 | frac0)) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(frac64, frac0); + exp = normExpSig.exp; + frac64 = normExpSig.sig.v64; + frac0 = normExpSig.sig.v0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig128 = softfloat_shortShiftLeft128(frac64 | UINT64_C(0x0001000000000000), frac0, 15); + return softfloat_roundPackToExtF80(sign, exp, sig128.v64, sig128.v0, 80, status); +} diff --git a/src/cpu/softfloat3e/f128_to_f32.cc b/src/cpu/softfloat3e/f128_to_f32.cc new file mode 100644 index 000000000..485d68a0c --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_f32.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f128_to_f32(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64; + struct commonNaN commonNaN; + uint32_t uiZ, frac32; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac32 = softfloat_shortShiftRightJam64(frac64, 18); + if (! (exp | frac32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3F81; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF32(sign, exp, frac32 | 0x40000000, status); +} diff --git a/src/cpu/softfloat3e/f128_to_f64.cc b/src/cpu/softfloat3e/f128_to_f64.cc new file mode 100644 index 000000000..0809c7102 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_f64.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f128_to_f64(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64, frac0; + struct commonNaN commonNaN; + uint64_t uiZ; + struct uint128 frac128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64); + frac0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64 | frac0) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac128 = softfloat_shortShiftLeft128(frac64, frac0, 14); + frac64 = frac128.v64 | (frac128.v0 != 0); + if (! (exp | frac64)) { + return packToF64UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3C01; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return + softfloat_roundPackToF64(sign, exp, frac64 | UINT64_C(0x4000000000000000), status); +} diff --git a/src/cpu/softfloat3e/f128_to_i32.cc b/src/cpu/softfloat3e/f128_to_i32.cc new file mode 100644 index 000000000..68cf2b3a7 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i32.cc @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f128_to_i32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig64 | sig0)) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sig64 |= (sig0 != 0); + shiftDist = 0x4023 - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc new file mode 100644 index 000000000..a62233d4d --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f128_to_i32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (49 <= shiftDist) { + if (exact && (exp | sig64)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF128UI64(uiA64); + if (shiftDist < 18) { + if (sign && (shiftDist == 17) && (sig64 < UINT64_C(0x0000000000020000))) { + if (exact && sig64) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && sig64 ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + absZ = sig64>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f128_to_i64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + struct uint128 sig128; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -15) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundToI64(sign, sig64, sig0, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc new file mode 100644 index 000000000..edeccf182 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc @@ -0,0 +1,104 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f128_to_i64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + int8_t negShiftDist; + uint64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist < 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -14) { + if ((uiA64 == UINT64_C(0xC03E000000000000)) && (sig0 < UINT64_C(0x0002000000000000))) { + if (exact && sig0) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FFF) && (sig64 | sig0) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + negShiftDist = -shiftDist; + absZ = sig64<>(shiftDist & 63); + if (exact && (uint64_t) (sig0<>shiftDist; + if (exact && (sig0 || (absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f128_to_ui32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FFF) && sig64) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + shiftDist = 0x4023 - exp; + if (0 < shiftDist) { + sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + } + return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc new file mode 100644 index 000000000..96007f6a1 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f128_to_ui32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (49 <= shiftDist) { + if (exact && (exp | sig64)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF128UI64(uiA64); + if (sign || (shiftDist < 17)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && sig64 ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + z = sig64>>shiftDist; + if (exact && ((uint64_t) z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f128_to_ui64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + struct uint128 sig128; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -15) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundToUI64(sign, sig64, sig0, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc new file mode 100644 index 000000000..8d30420b0 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc @@ -0,0 +1,99 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f128_to_ui64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + int8_t negShiftDist; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist < 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (sign || (shiftDist < -15)) goto invalid; + sig64 |= UINT64_C(0x0001000000000000); + negShiftDist = -shiftDist; + z = sig64<>(shiftDist & 63); + if (exact && (uint64_t) (sig0<>shiftDist; + if (exact && (sig0 || (z< +#include +#include "internals.h" +#include "softfloat.h" + +extern float16 softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); +extern float16 softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); + +float16 f16_add(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (signF16UI((uint16_t) a ^ (uint16_t) b)) { + return softfloat_subMagsF16(a, b, status); + } else { + return softfloat_addMagsF16(a, b, status); + } +} + +float16 f16_sub(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (signF16UI((uint16_t) a ^ (uint16_t) b)) { + return softfloat_addMagsF16(a, b, status); + } else { + return softfloat_subMagsF16(a, b, status); + } +} diff --git a/src/cpu/softfloat3e/f16_class.c b/src/cpu/softfloat3e/f16_class.c new file mode 100644 index 000000000..b375c1544 --- /dev/null +++ b/src/cpu/softfloat3e/f16_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f16_class(float16 a) +{ + bool signA; + int8_t expA; + uint16_t sigA; + + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & 0x200) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f16_compare.c b/src/cpu/softfloat3e/f16_compare.c new file mode 100644 index 000000000..1cfd56bec --- /dev/null +++ b/src/cpu/softfloat3e/f16_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f16_compare(float16 a, float16 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f16_class(a); + bClass = f16_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & 0x8000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & 0x8000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint16_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF16UI(a); + signB = signF16UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f16_div.c b/src/cpu/softfloat3e/f16_div.c new file mode 100644 index 000000000..c91760b03 --- /dev/null +++ b/src/cpu/softfloat3e/f16_div.c @@ -0,0 +1,149 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#define SOFTFLOAT_FAST_DIV32TO16 1 + +extern const uint16_t softfloat_approxRecip_1k0s[]; +extern const uint16_t softfloat_approxRecip_1k1s[]; + +float16 f16_div(float16 a, float16 b, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signZ; + struct exp8_sig16 normExpSig; + int8_t expZ; +#ifdef SOFTFLOAT_FAST_DIV32TO16 + uint32_t sig32A; + uint16_t sigZ; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA) goto propagateNaN; + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0xE; + sigA |= 0x0400; + sigB |= 0x0400; +#ifdef SOFTFLOAT_FAST_DIV32TO16 + if (sigA < sigB) { + --expZ; + sig32A = (uint32_t) sigA<<15; + } else { + sig32A = (uint32_t) sigA<<14; + } + sigZ = sig32A / sigB; + if (! (sigZ & 7)) sigZ |= ((uint32_t) sigB * sigZ != sig32A); +#endif + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF16UI(signZ, 0x1F, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF16UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f16_getExp.c b/src/cpu/softfloat3e/f16_getExp.c new file mode 100644 index 000000000..dfade995f --- /dev/null +++ b/src/cpu/softfloat3e/f16_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of half-precision floating-point value 'a', +| and returns the result as a half-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 f16_getExp(float16 a, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA) return softfloat_propagateNaNF16UI(a, 0, status); + return (float16)packToF32UI(0, 0x1F, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return (float16)packToF32UI(1, 0x1F, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f16((int32_t)(expA) - 0xF, status); +} diff --git a/src/cpu/softfloat3e/f16_getMant.c b/src/cpu/softfloat3e/f16_getMant.c new file mode 100644 index 000000000..f0d8d5482 --- /dev/null +++ b/src/cpu/softfloat3e/f16_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of half-precision floating-point value 'a' and +| returns the result as a half-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 f16_getMant(float16 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA) return softfloat_propagateNaNF16UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + } + return packToF16UI(~sign_ctrl & signA, 0x1F, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF16UI(~sign_ctrl & signA, 0x1F, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + } + + if (expA == 0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= 0x3ff; + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0xF; + break; + case 0x1: // interval [1/2,2) + expA -= 0xF; + expA = 0xF - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0xE; + break; + case 0x3: // interval [3/4,3/2) + expA = 0xF - ((sigA >> 9) & 0x1); + break; + } + + return packToF16UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f16_minmax.c b/src/cpu/softfloat3e/f16_minmax.c new file mode 100644 index 000000000..11922a1ba --- /dev/null +++ b/src/cpu/softfloat3e/f16_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float16 f16_min(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f16_denormal_to_zero(a); + b = f16_denormal_to_zero(b); + } + + return (f16_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float16 f16_max(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f16_denormal_to_zero(a); + b = f16_denormal_to_zero(b); + } + + return (f16_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f16_mul.c b/src/cpu/softfloat3e/f16_mul.c new file mode 100644 index 000000000..2e7e74826 --- /dev/null +++ b/src/cpu/softfloat3e/f16_mul.c @@ -0,0 +1,139 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_mul(float16 a, float16 b, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signZ; + uint16_t magBits; + struct exp8_sig16 normExpSig; + int8_t expZ; + uint32_t sig32Z; + uint16_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA || ((expB == 0x1F) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0xF; + sigA = (sigA | 0x0400)<<4; + sigB = (sigB | 0x0400)<<5; + sig32Z = (uint32_t) sigA * sigB; + sigZ = sig32Z>>16; + if (sig32Z & 0xFFFF) sigZ |= 1; + if (sigZ < 0x4000) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF16UI; + } else { + uiZ = packToF16UI(signZ, 0x1F, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF16UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f16_mulAdd.c b/src/cpu/softfloat3e/f16_mulAdd.c new file mode 100644 index 000000000..0e630a9b7 --- /dev/null +++ b/src/cpu/softfloat3e/f16_mulAdd.c @@ -0,0 +1,232 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float16 f16_mulAdd(float16 a, float16 b, float16 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signC; + int8_t expC; + uint16_t sigC; + bool signProd; + uint16_t magBits, uiA, uiB, uiC, uiZ; + struct exp8_sig16 normExpSig; + int8_t expProd; + uint32_t sigProd; + bool signZ; + int8_t expZ; + uint16_t sigZ; + int8_t expDiff; + uint32_t sig32Z, sig32C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(uiA); + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + signB = signF16UI(uiB); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF16UI(uiC); + sigC = fracF16UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x1F) && sigA; + bool bisNaN = (expB == 0x1F) && sigB; + bool cisNaN = (expC == 0x1F) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF16UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x1F) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x1F) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF16UI(signC, 0x1F, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0xE; + sigA = (sigA | 0x0400)<<4; + sigB = (sigB | 0x0400)<<4; + sigProd = (uint32_t) sigA * sigB; + if (sigProd < 0x20000000) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x0400)<<3; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff); + } else { + expZ = expProd; + sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff); + sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0); + } + if (sigZ < 0x4000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig32C = (uint32_t) sigC<<16; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig32Z = sigProd - sig32C; + if (! sig32Z) goto completeCancellation; + if (sig32Z & 0x80000000) { + signZ = ! signZ; + sig32Z = -sig32Z; + } + } else { + expZ = expProd; + sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff); + } + shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1; + expZ -= shiftDist; + shiftDist -= 16; + if (shiftDist < 0) { + sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0); + } else { + sigZ = (uint16_t) sig32Z< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_range(float16 a, float16 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool aIsNaN, bIsNaN; + uint16_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF16UI(a)) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + if (softfloat_isSigNaNF16UI(b)) { + return softfloat_propagateNaNF16UI(b, 0, status); + } + + aIsNaN = isNaNF16UI(a); + bIsNaN = isNaNF16UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF16UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF16UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float16 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~0x8000; // clear the sign bit + tmp_b = tmp_b & ~0x8000; + signA = 0; + } + + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~0x8000) | (a & 0x8000); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~0x8000; // zero out the sign bit + break; + case 3: + z = z | 0x8000; // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f16_roundToInt.c b/src/cpu/softfloat3e/f16_roundToInt.c new file mode 100644 index 000000000..ee9be0c0b --- /dev/null +++ b/src/cpu/softfloat3e/f16_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_roundToInt(float16 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + bool sign; + uint16_t uiZ, lastBitMask, roundBitsMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + sign = signF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x19 <= (exp + scale)) { + if ((exp == 0x1F) && frac) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF16UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0xE) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF16UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0xE) uiZ |= packToF16UI(0, 0xF - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF16UI(1, 0xF - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF16UI(0, 0xF - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint16_t) 1<<(0x19 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f16_sqrt.c b/src/cpu/softfloat3e/f16_sqrt.c new file mode 100644 index 000000000..f0f8afef1 --- /dev/null +++ b/src/cpu/softfloat3e/f16_sqrt.c @@ -0,0 +1,130 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; + +float16 f16_sqrt(float16 a, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + int8_t expZ; + int index; + uint16_t r0; + uint32_t ESqrR0; + uint16_t sigma0; + uint16_t recipSqrt16, sigZ, shiftedSigZ; + uint16_t negRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF16UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0xF)>>1) + 0xE; + expA &= 1; + sigA |= 0x0400; + index = (sigA>>6 & 0xE) + expA; + r0 = softfloat_approxRecipSqrt_1k0s[index] + - (((uint32_t) softfloat_approxRecipSqrt_1k1s[index] * (sigA & 0x7F)) >>11); + ESqrR0 = ((uint32_t) r0 * r0)>>1; + if (expA) ESqrR0 >>= 1; + sigma0 = ~(uint16_t) ((ESqrR0 * sigA)>>16); + recipSqrt16 = r0 + (((uint32_t) r0 * sigma0)>>25); + if (! (recipSqrt16 & 0x8000)) recipSqrt16 = 0x8000; + sigZ = ((uint32_t) (sigA<<5) * recipSqrt16)>>16; + if (expA) sigZ >>= 1; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + ++sigZ; + if (! (sigZ & 7)) { + shiftedSigZ = sigZ>>1; + negRem = shiftedSigZ * shiftedSigZ; + sigZ &= ~1; + if (negRem & 0x8000) { + sigZ |= 1; + } else { + if (negRem) --sigZ; + } + } + return softfloat_roundPackToF16(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; +} diff --git a/src/cpu/softfloat3e/f16_to_extF80.cc b/src/cpu/softfloat3e/f16_to_extF80.cc new file mode 100644 index 000000000..418be8083 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f16_to_extF80(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3FF0); + uiZ0 = (uint64_t) (frac | 0x0400)<<53; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f16_to_f32.c b/src/cpu/softfloat3e/f16_to_f32.c new file mode 100644 index 000000000..4d862161d --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_f32.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f16_to_f32(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + uint32_t uiZ; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF32UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF32UI(sign, exp + 0x70, (uint32_t) frac<<13); +} diff --git a/src/cpu/softfloat3e/f16_to_f64.c b/src/cpu/softfloat3e/f16_to_f64.c new file mode 100644 index 000000000..7d61b6357 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_f64.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f16_to_f64(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + uint64_t uiZ; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF64UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp + 0x3F0, (uint64_t) frac<<42); +} diff --git a/src/cpu/softfloat3e/f16_to_i32.c b/src/cpu/softfloat3e/f16_to_i32.c new file mode 100644 index 000000000..d00cfe236 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i32.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f16_to_i32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + int32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if (0 <= shiftDist) { + sig32 <<= shiftDist; + return sign ? -sig32 : sig32; + } + shiftDist = exp - 0x0D; + if (0 < shiftDist) sig32 <<= shiftDist; + } + else { + if (softfloat_denormalsAreZeros(status)) sig32 = 0; + } + return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f16_to_i32_r_minMag.c b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c new file mode 100644 index 000000000..9a6bbdf83 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f16_to_i32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + int32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (int32_t) (frac | 0x0400)<>= 10; + return sign ? -alignedSig : alignedSig; +} diff --git a/src/cpu/softfloat3e/f16_to_i64.c b/src/cpu/softfloat3e/f16_to_i64.c new file mode 100644 index 000000000..7dcbeaad8 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i64.c @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f16_to_i64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + int32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if (0 <= shiftDist) { + sig32 <<= shiftDist; + return sign ? -sig32 : sig32; + } + shiftDist = exp - 0x0D; + if (0 < shiftDist) sig32 <<= shiftDist; + } + else { + if (softfloat_denormalsAreZeros(status)) sig32 = 0; + } + return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f16_to_i64_r_minMag.c b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c new file mode 100644 index 000000000..4289c5352 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f16_to_i64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + int32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (int32_t) (frac | 0x0400)<>= 10; + return sign ? -alignedSig : alignedSig; +} diff --git a/src/cpu/softfloat3e/f16_to_ui32.c b/src/cpu/softfloat3e/f16_to_ui32.c new file mode 100644 index 000000000..d217b2627 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f16_to_ui32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + uint32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ((0 <= shiftDist) && ! sign) { + return sig32< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f16_to_ui32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + uint32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (sign || (exp == 0x1F)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (uint32_t) (frac | 0x0400)<>10; +} diff --git a/src/cpu/softfloat3e/f16_to_ui64.c b/src/cpu/softfloat3e/f16_to_ui64.c new file mode 100644 index 000000000..351edb32c --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui64.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f16_to_ui64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + uint32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ((0 <= shiftDist) && ! sign) { + return sig32<>12, (uint64_t) sig32<<52, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c new file mode 100644 index 000000000..d80d6e8f5 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f16_to_ui64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + uint32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (sign || (exp == 0x1F)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (uint32_t) (frac | 0x0400)<>10; +} diff --git a/src/cpu/softfloat/f2xm1.cc b/src/cpu/softfloat3e/f2xm1.cc similarity index 77% rename from src/cpu/softfloat/f2xm1.cc rename to src/cpu/softfloat3e/f2xm1.cc index ed4af1d12..16daec1d3 100644 --- a/src/cpu/softfloat/f2xm1.cc +++ b/src/cpu/softfloat3e/f2xm1.cc @@ -25,12 +25,15 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "specialize.h" + +#include "fpu_trans.h" +#include "softfloat-helpers.h" static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000)); static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000)); -static const float128 float128_ln2 = +static const float128_t float128_ln2 = packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6)); #ifdef BETTER_THAN_PENTIUM @@ -47,7 +50,7 @@ static const float128 float128_ln2 = #define EXP_ARR_SIZE 15 -static float128 exp_arr[EXP_ARR_SIZE] = +static float128_t exp_arr[EXP_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ @@ -66,10 +69,10 @@ static float128 exp_arr[EXP_ARR_SIZE] = PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ }; -extern float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status); +extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status); /* required -1 < x < 1 */ -static float128 poly_exp(float128 x, struct float_status_t *status) +static float128_t poly_exp(float128_t x, struct softfloat_status_t *status) { /* // 2 3 4 5 6 7 8 9 @@ -92,8 +95,8 @@ static float128 poly_exp(float128 x, struct float_status_t *status) // e - 1 ~ x * [ p(x) + x * q(x) ] // */ - float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status); - return float128_mul(t, x, status); + float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE, status); + return f128_mul(t, x, status); } // ================================================= @@ -114,49 +117,51 @@ static float128 poly_exp(float128 x, struct float_status_t *status) // e = 1 + --- + --- + --- + --- + --- + ... + --- + ... // 1! 2! 3! 4! 5! n! // - -floatx80 f2xm1(floatx80 a, struct float_status_t *status) +floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u zSig0, zSig1, zSig2; + static const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + uint64_t zSig0, zSig1, zSig2; + struct exp32_sig64 normExpSig; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaNOne(a, status); + if (aSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0, status); return (aSign) ? floatx80_negone : a; } - if (aExp == 0) { - if (aSig == 0) return a; - float_raise(status, float_flag_denormal | float_flag_inexact); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + if (! aExp) { + if (! aSig) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal | softfloat_flag_inexact); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; tiny_argument: mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --aExp; } - return - roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80, status); } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(status, softfloat_flag_inexact); if (aExp < 0x3FFF) { @@ -167,14 +172,14 @@ floatx80 f2xm1(floatx80 a, struct float_status_t *status) /* using float128 for approximation */ /* ******************************** */ - float128 x = floatx80_to_float128(a, status); - x = float128_mul(x, float128_ln2, status); + float128_t x = extF80_to_f128(a, status); + x = f128_mul(x, float128_ln2, status); x = poly_exp(x, status); - return float128_to_floatx80(x, status); + return f128_to_extF80(x, status); } else { - if (a.exp == 0xBFFF && ! (aSig<<1)) + if (a.signExp == 0xBFFF && ! (aSig<<1)) return floatx80_neghalf; return a; diff --git a/src/cpu/softfloat3e/f32_addsub.c b/src/cpu/softfloat3e/f32_addsub.c new file mode 100644 index 000000000..0b12d0e76 --- /dev/null +++ b/src/cpu/softfloat3e/f32_addsub.c @@ -0,0 +1,60 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +extern float32 softfloat_addMagsF32(uint32_t, uint32_t, struct softfloat_status_t *); +extern float32 softfloat_subMagsF32(uint32_t, uint32_t, struct softfloat_status_t *); + +float32 f32_add(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (signF32UI((uint32_t) a ^ (uint32_t) b)) { + return softfloat_subMagsF32(a, b, status); + } else { + return softfloat_addMagsF32(a, b, status); + } +} + +float32 f32_sub(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (signF32UI((uint32_t) a ^ (uint32_t) b)) { + return softfloat_addMagsF32(a, b, status); + } else { + return softfloat_subMagsF32(a, b, status); + } +} diff --git a/src/cpu/softfloat3e/f32_class.c b/src/cpu/softfloat3e/f32_class.c new file mode 100644 index 000000000..84c337d0e --- /dev/null +++ b/src/cpu/softfloat3e/f32_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f32_class(float32 a) +{ + bool signA; + int16_t expA; + uint32_t sigA; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & 0x00400000) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f32_compare.c b/src/cpu/softfloat3e/f32_compare.c new file mode 100644 index 000000000..6c8ecfaae --- /dev/null +++ b/src/cpu/softfloat3e/f32_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f32_compare(float32 a, float32 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f32_class(a); + bClass = f32_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & 0x80000000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & 0x80000000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint32_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF32UI(a); + signB = signF32UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f32_div.c b/src/cpu/softfloat3e/f32_div.c new file mode 100644 index 000000000..a9ccfcfd4 --- /dev/null +++ b/src/cpu/softfloat3e/f32_div.c @@ -0,0 +1,146 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#define SOFTFLOAT_FAST_DIV64TO32 + +float32 f32_div(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signZ; + struct exp16_sig32 normExpSig; + int16_t expZ; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + uint64_t sig64A; + uint32_t sigZ; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) goto propagateNaN; + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x7E; + sigA |= 0x00800000; + sigB |= 0x00800000; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + if (sigA < sigB) { + --expZ; + sig64A = (uint64_t) sigA<<31; + } else { + sig64A = (uint64_t) sigA<<30; + } + sigZ = sig64A / sigB; + if (! (sigZ & 0x3F)) sigZ |= ((uint64_t) sigB * sigZ != sig64A); +#endif + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF32UI(signZ, 0xFF, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF32UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f32_frc.c b/src/cpu/softfloat3e/f32_frc.c new file mode 100644 index 000000000..fc1b02460 --- /dev/null +++ b/src/cpu/softfloat3e/f32_frc.c @@ -0,0 +1,101 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of single-precision floating-point value `a', +| and returns the result as a single-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_frc(float32 a, struct softfloat_status_t *status) +{ + int roundingMode = softfloat_getRoundingMode(status); + + bool signA; + int16_t expA; + uint32_t sigA; + uint32_t lastBitMask; + uint32_t roundBitsMask; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + if (expA >= 0x96) { + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + } + + if (expA < 0x7F) { + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) + softfloat_raiseFlags(status, softfloat_flag_underflow); + + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signA, 0, 0); + } + } + return a; + } + + lastBitMask = 1 << (0x96 - expA); + roundBitsMask = lastBitMask - 1; + + sigA &= roundBitsMask; + sigA <<= 7; + expA--; + + if (! sigA) + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + + return softfloat_normRoundPackToF32(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f32_getExp.c b/src/cpu/softfloat3e/f32_getExp.c new file mode 100644 index 000000000..66b00ac7c --- /dev/null +++ b/src/cpu/softfloat3e/f32_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of single-precision floating-point value 'a', +| and returns the result as a single-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_getExp(float32 a, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + return packToF32UI(0, 0xFF, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF32UI(1, 0xFF, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f32((int32_t)(expA) - 0x7F, status); +} diff --git a/src/cpu/softfloat3e/f32_getMant.c b/src/cpu/softfloat3e/f32_getMant.c new file mode 100644 index 000000000..9dfa58a63 --- /dev/null +++ b/src/cpu/softfloat3e/f32_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of single-precision floating-point value 'a' and +| returns the result as a single-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_getMant(float32 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + } + return packToF32UI(~sign_ctrl & signA, 0x7F, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF32UI(~sign_ctrl & signA, 0x7F, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + } + + if (! expA) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= 0x7FFFFF; + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0x7F; + break; + case 0x1: // interval [1/2,2) + expA -= 0x7F; + expA = 0x7F - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0x7E; + break; + case 0x3: // interval [3/4,3/2) + expA = 0x7F - ((sigA >> 22) & 0x1); + break; + } + + return packToF32UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f32_minmax.c b/src/cpu/softfloat3e/f32_minmax.c new file mode 100644 index 000000000..e36c297ae --- /dev/null +++ b/src/cpu/softfloat3e/f32_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float32 f32_min(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f32_denormal_to_zero(a); + b = f32_denormal_to_zero(b); + } + + return (f32_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float32 f32_max(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f32_denormal_to_zero(a); + b = f32_denormal_to_zero(b); + } + + return (f32_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f32_mul.c b/src/cpu/softfloat3e/f32_mul.c new file mode 100644 index 000000000..db96e0db7 --- /dev/null +++ b/src/cpu/softfloat3e/f32_mul.c @@ -0,0 +1,137 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_mul(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signZ; + uint32_t magBits; + struct exp16_sig32 normExpSig; + int16_t expZ; + uint32_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA || ((expB == 0xFF) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x7F; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<8; + sigZ = softfloat_shortShiftRightJam64((uint64_t) sigA * sigB, 32); + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF32UI; + } else { + uiZ = packToF32UI(signZ, 0xFF, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF32UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f32_mulAdd.c b/src/cpu/softfloat3e/f32_mulAdd.c new file mode 100644 index 000000000..101b20f18 --- /dev/null +++ b/src/cpu/softfloat3e/f32_mulAdd.c @@ -0,0 +1,233 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float32 f32_mulAdd(float32 a, float32 b, float32 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signC; + int16_t expC; + uint32_t sigC; + bool signProd; + uint32_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig32 normExpSig; + int16_t expProd; + uint64_t sigProd; + bool signZ; + int16_t expZ; + uint32_t sigZ; + int16_t expDiff; + uint64_t sig64Z, sig64C; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(uiA); + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + signB = signF32UI(uiB); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF32UI(uiC); + sigC = fracF32UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0xFF) && sigA; + bool bisNaN = (expB == 0xFF) && sigB; + bool cisNaN = (expC == 0xFF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF32UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0xFF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0xFF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF32UI(signC, 0xFF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0x7E; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<7; + sigProd = (uint64_t) sigA * sigB; + if (sigProd < UINT64_C(0x2000000000000000)) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = softfloat_shortShiftRightJam64(sigProd, 31); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x00800000)<<6; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff); + } else { + expZ = expProd; + sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff); + sigZ = softfloat_shortShiftRightJam64(sig64Z, 32); + } + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64C = (uint64_t) sigC<<32; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig64Z = sigProd - sig64C; + if (! sig64Z) goto completeCancellation; + if (sig64Z & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig64Z = -sig64Z; + } + } else { + expZ = expProd; + sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff); + } + shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1; + expZ -= shiftDist; + shiftDist -= 32; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist); + } else { + sigZ = (uint32_t) sig64Z< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_range(float32 a, float32 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool aIsNaN, bIsNaN; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF32UI(a)) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + if (softfloat_isSigNaNF32UI(b)) { + return softfloat_propagateNaNF32UI(b, 0, status); + } + + aIsNaN = isNaNF32UI(a); + bIsNaN = isNaNF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF32UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF32UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float32 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~0x80000000; // clear the sign bit + tmp_b = tmp_b & ~0x80000000; + signA = 0; + } + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~0x80000000) | (a & 0x80000000); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~0x80000000; // zero out the sign bit + break; + case 3: + z = z | 0x80000000; // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f32_roundToInt.c b/src/cpu/softfloat3e/f32_roundToInt.c new file mode 100644 index 000000000..7791fbbf4 --- /dev/null +++ b/src/cpu/softfloat3e/f32_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_roundToInt(float32 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + int32_t frac; + uint32_t uiZ, lastBitMask, roundBitsMask; + bool sign; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + frac = fracF32UI(a); + sign = signF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x96 <= (exp + scale)) { + if ((exp == 0xFF) && frac) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF32UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0x7E) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF32UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0x7E) uiZ |= packToF32UI(0, 0x7F - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF32UI(1, 0x7F - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF32UI(0, 0x7F - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint32_t) 1<<(0x96 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF32UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f32_scalef.c b/src/cpu/softfloat3e/f32_scalef.c new file mode 100644 index 000000000..320baff30 --- /dev/null +++ b/src/cpu/softfloat3e/f32_scalef.c @@ -0,0 +1,155 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the single-precision floating +| point value `a' by multiplying it by 2 power of the single-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in single precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_scalef(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + int shiftCount; + int scale = 0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0xFF) { + if (sigB) return softfloat_propagateNaNF32UI(a, b, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) { + int aIsSignalingNaN = (sigA & 0x00400000) == 0; + if (aIsSignalingNaN || expB != 0xFF || sigB) + return softfloat_propagateNaNF32UI(a, b, status); + + return signB ? 0 : packToF32UI(0, 0xFF, 0); + } + + if (expB == 0xFF && signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (expB == 0xFF && ! signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + return packToF32UI(signA, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((expB | sigB) == 0) return a; + + if (expB == 0xFF) { + if (signB) return packToF32UI(signA, 0, 0); + return packToF32UI(signA, 0xFF, 0); + } + + if (expB >= 0x8E) { + // handle obvious overflow/underflow result + return softfloat_roundPackToF32(signA, signB ? -0x7F : 0xFF, sigA, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB <= 0x7E) { + if (! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + scale = -signB; + } + else { + shiftCount = expB - 0x9E; + sigB = (sigB | 0x800000)<<8; + scale = sigB>>(-shiftCount); + + if (signB) { + if ((uint32_t) (sigB<<(shiftCount & 31))) scale++; + scale = -scale; + } + + if (scale > 0x200) scale = 0x200; + if (scale < -0x200) scale = -0x200; + } + + if (expA != 0) { + sigA |= 0x00800000; + } else { + expA++; + } + + expA += scale - 1; + sigA <<= 7; + return softfloat_normRoundPackToF32(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f32_sqrt.c b/src/cpu/softfloat3e/f32_sqrt.c new file mode 100644 index 000000000..fc2ef8f76 --- /dev/null +++ b/src/cpu/softfloat3e/f32_sqrt.c @@ -0,0 +1,117 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_sqrt(float32 a, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + int16_t expZ; + uint32_t sigZ, shiftedSigZ; + uint32_t negRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF32UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x7F)>>1) + 0x7E; + expA &= 1; + sigA = (sigA | 0x00800000)<<8; + sigZ = + ((uint64_t) sigA * softfloat_approxRecipSqrt32_1(expA, sigA))>>32; + if (expA) sigZ >>= 1; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ += 2; + if ((sigZ & 0x3F) < 2) { + shiftedSigZ = sigZ>>2; + negRem = shiftedSigZ * shiftedSigZ; + sigZ &= ~3; + if (negRem & 0x80000000) { + sigZ |= 1; + } else { + if (negRem) --sigZ; + } + } + return softfloat_roundPackToF32(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; +} diff --git a/src/cpu/softfloat3e/f32_to_extF80.cc b/src/cpu/softfloat3e/f32_to_extF80.cc new file mode 100644 index 000000000..73b8bedfd --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f32_to_extF80(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3F80); + uiZ0 = (uint64_t) (frac | 0x00800000)<<40; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f32_to_f128.cc b/src/cpu/softfloat3e/f32_to_f128.cc new file mode 100644 index 000000000..6d3fafec2 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f128.cc @@ -0,0 +1,86 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f32_to_f128(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0); + uiZ.v0 = 0; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + uiZ.v64 = packToF128UI64(sign, 0, 0); + uiZ.v0 = 0; + return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ.v64 = packToF128UI64(sign, exp + 0x3F80, (uint64_t) frac<<25); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f32_to_f16.c b/src/cpu/softfloat3e/f32_to_f16.c new file mode 100644 index 000000000..9253a958a --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f16.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f32_to_f16(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + uint16_t uiZ, frac16; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF16UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac16 = frac>>9 | ((frac & 0x1FF) != 0); + if (! (exp | frac16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF16(sign, exp - 0x71, frac16 | 0x4000, status); +} diff --git a/src/cpu/softfloat3e/f32_to_f64.c b/src/cpu/softfloat3e/f32_to_f64.c new file mode 100644 index 000000000..28ebb61b6 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f64.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f32_to_f64(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + uint64_t uiZ; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF64UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp + 0x380, (uint64_t) frac<<29); +} diff --git a/src/cpu/softfloat3e/f32_to_i32.c b/src/cpu/softfloat3e/f32_to_i32.c new file mode 100644 index 000000000..2b3df52a3 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i32.c @@ -0,0 +1,78 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f32_to_i32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + uint64_t sig64; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0xFF) && sig) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<32; + shiftDist = 0xAA - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_i32_r_minMag.c b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c new file mode 100644 index 000000000..abe782d3b --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f32_to_i32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x9E - exp; + if (32 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (shiftDist <= 0) { + if (a == packToF32UI(1, 0x9E, 0)) return -0x7FFFFFFF - 1; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig | 0x00800000)<<8; + absZ = sig>>shiftDist; + if (exact && ((uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f32_to_i64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + int16_t shiftDist; + uint64_t sig64, extra; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + extra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundToI64(sign, sig64, extra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_i64_r_minMag.c b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c new file mode 100644 index 000000000..2ccabd09d --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f32_to_i64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint64_t sig64; + int64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (shiftDist <= 0) { + if (a == packToF32UI(1, 0xBE, 0)) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + absZ = sig64>>shiftDist; + shiftDist = 40 - shiftDist; + if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return sign ? -absZ : absZ; +} diff --git a/src/cpu/softfloat3e/f32_to_ui32.c b/src/cpu/softfloat3e/f32_to_ui32.c new file mode 100644 index 000000000..5a8d57414 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui32.c @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f32_to_ui32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + uint64_t sig64; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0xFF) && sig) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<32; + shiftDist = 0xAA - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c new file mode 100644 index 000000000..4b37708b0 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c @@ -0,0 +1,83 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f32_to_ui32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x9E - exp; + if (32 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig | 0x00800000)<<8; + z = sig>>shiftDist; + if (exact && (z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f32_to_ui64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + int16_t shiftDist; + uint64_t sig64, extra; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<40; + extra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundToUI64(sign, sig64, extra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c new file mode 100644 index 000000000..111c50e7f --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c @@ -0,0 +1,84 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f32_to_ui64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint64_t sig64, z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + z = sig64>>shiftDist; + shiftDist = 40 - shiftDist; + if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return z; +} diff --git a/src/cpu/softfloat3e/f64_addsub.c b/src/cpu/softfloat3e/f64_addsub.c new file mode 100644 index 000000000..6c5acb4f7 --- /dev/null +++ b/src/cpu/softfloat3e/f64_addsub.c @@ -0,0 +1,70 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +extern float64 softfloat_addMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float64 softfloat_subMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); + +float64 f64_add(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + bool signB; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA == signB) { + return softfloat_addMagsF64(a, b, signA, status); + } else { + return softfloat_subMagsF64(a, b, signA, status); + } +} + +float64 f64_sub(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + bool signB; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA == signB) { + return softfloat_subMagsF64(a, b, signA, status); + } else { + return softfloat_addMagsF64(a, b, signA, status); + } +} diff --git a/src/cpu/softfloat3e/f64_class.c b/src/cpu/softfloat3e/f64_class.c new file mode 100644 index 000000000..1d44a6351 --- /dev/null +++ b/src/cpu/softfloat3e/f64_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f64_class(float64 a) +{ + bool signA; + int16_t expA; + uint64_t sigA; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & UINT64_C(0x0008000000000000)) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f64_compare.c b/src/cpu/softfloat3e/f64_compare.c new file mode 100644 index 000000000..aed250768 --- /dev/null +++ b/src/cpu/softfloat3e/f64_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f64_compare(float64 a, float64 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f64_class(a); + bClass = f64_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & UINT64_C(0x8000000000000000); + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & UINT64_C(0x8000000000000000); + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint64_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f64_div.c b/src/cpu/softfloat3e/f64_div.c new file mode 100644 index 000000000..89f74f1b1 --- /dev/null +++ b/src/cpu/softfloat3e/f64_div.c @@ -0,0 +1,165 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_div(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signZ; + struct exp16_sig64 normExpSig; + int16_t expZ; + uint32_t recip32, sig32Z, doubleTerm; + uint64_t rem; + uint32_t q; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) goto propagateNaN; + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FE; + sigA |= UINT64_C(0x0010000000000000); + sigB |= UINT64_C(0x0010000000000000); + if (sigA < sigB) { + --expZ; + sigA <<= 11; + } else { + sigA <<= 10; + } + sigB <<= 11; + recip32 = softfloat_approxRecip32_1(sigB>>32) - 2; + sig32Z = ((uint32_t) (sigA>>32) * (uint64_t) recip32)>>32; + doubleTerm = sig32Z<<1; + rem = + ((sigA - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint64_t) doubleTerm * ((uint32_t) sigB>>4); + q = (((uint32_t) (rem>>32) * (uint64_t) recip32)>>32) + 4; + sigZ = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<4); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((sigZ & 0x1FF) < 4<<4) { + q &= ~7; + sigZ &= ~(uint64_t) 0x7F; + doubleTerm = q<<1; + rem = + ((rem - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint64_t) doubleTerm * ((uint32_t) sigB>>4); + if (rem & UINT64_C(0x8000000000000000)) { + sigZ -= 1<<7; + } else { + if (rem) sigZ |= 1; + } + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF64UI(signZ, 0x7FF, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF64UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f64_frc.c b/src/cpu/softfloat3e/f64_frc.c new file mode 100644 index 000000000..46c21ac4f --- /dev/null +++ b/src/cpu/softfloat3e/f64_frc.c @@ -0,0 +1,101 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of double-precision floating-point value `a', +| and returns the result as a double-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_frc(float64 a, struct softfloat_status_t *status) +{ + int roundingMode = softfloat_getRoundingMode(status); + + bool signA; + int16_t expA; + uint64_t sigA; + uint64_t lastBitMask; + uint64_t roundBitsMask; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + if (expA >= 0x433) { + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + } + + if (expA < 0x3FF) { + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) + softfloat_raiseFlags(status, softfloat_flag_underflow); + + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signA, 0, 0); + } + } + return a; + } + + lastBitMask = UINT64_C(1) << (0x433 - expA); + roundBitsMask = lastBitMask - 1; + + sigA &= roundBitsMask; + sigA <<= 10; + expA--; + + if (! sigA) + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + + return softfloat_normRoundPackToF64(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f64_getExp.c b/src/cpu/softfloat3e/f64_getExp.c new file mode 100644 index 000000000..b76cc996d --- /dev/null +++ b/src/cpu/softfloat3e/f64_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of double-precision floating-point value 'a', +| and returns the result as a double-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_getExp(float64 a, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + return packToF64UI(0, 0x7FF, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF64UI(1, 0x7FF, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f64((int32_t)(expA) - 0x3FF); +} diff --git a/src/cpu/softfloat3e/f64_getMant.c b/src/cpu/softfloat3e/f64_getMant.c new file mode 100644 index 000000000..84077e314 --- /dev/null +++ b/src/cpu/softfloat3e/f64_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of double-precision floating-point value 'a' and +| returns the result as a double-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_getMant(float64 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + } + return packToF64UI(~sign_ctrl & signA, 0x3FF, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF64UI(~sign_ctrl & signA, 0x3FF, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + } + + if (expA == 0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= UINT64_C(0xFFFFFFFFFFFFF); + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0x3FF; + break; + case 0x1: // interval [1/2,2) + expA -= 0x3FF; + expA = 0x3FF - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0x3FE; + break; + case 0x3: // interval [3/4,3/2) + expA = 0x3FF - ((sigA >> 51) & 0x1); + break; + } + + return packToF64UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f64_minmax.c b/src/cpu/softfloat3e/f64_minmax.c new file mode 100644 index 000000000..3c927410a --- /dev/null +++ b/src/cpu/softfloat3e/f64_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float64 f64_min(float64 a, float64 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f64_denormal_to_zero(a); + b = f64_denormal_to_zero(b); + } + + return (f64_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float64 f64_max(float64 a, float64 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f64_denormal_to_zero(a); + b = f64_denormal_to_zero(b); + } + + return (f64_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f64_mul.c b/src/cpu/softfloat3e/f64_mul.c new file mode 100644 index 000000000..c1e98f2b6 --- /dev/null +++ b/src/cpu/softfloat3e/f64_mul.c @@ -0,0 +1,139 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_mul(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signZ; + uint64_t magBits; + struct exp16_sig64 normExpSig; + int16_t expZ; + struct uint128 sig128Z; + uint64_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA || ((expB == 0x7FF) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FF; + sigA = (sigA | UINT64_C(0x0010000000000000))<<10; + sigB = (sigB | UINT64_C(0x0010000000000000))<<11; + sig128Z = softfloat_mul64To128(sigA, sigB); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF64UI; + } else { + uiZ = packToF64UI(signZ, 0x7FF, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF64UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f64_mulAdd.c b/src/cpu/softfloat3e/f64_mulAdd.c new file mode 100644 index 000000000..9623b4980 --- /dev/null +++ b/src/cpu/softfloat3e/f64_mulAdd.c @@ -0,0 +1,243 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float64 f64_mulAdd(float64 a, float64 b, float64 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signC; + int16_t expC; + uint64_t sigC; + bool signZ; + uint64_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig64 normExpSig; + int16_t expZ; + struct uint128 sig128Z; + uint64_t sigZ; + int16_t expDiff; + struct uint128 sig128C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(uiA); + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + signB = signF64UI(uiB); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + signC = signF64UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF64UI(uiC); + sigC = fracF64UI(uiC); + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x7FF) && sigA; + bool bisNaN = (expB == 0x7FF) && sigB; + bool cisNaN = (expC == 0x7FF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF64UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x7FF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x7FF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF64UI(signC, 0x7FF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C(0x0010000000000000))<<10; + sigB = (sigB | UINT64_C(0x0010000000000000))<<10; + sig128Z = softfloat_mul64To128(sigA, sigB); + if (sig128Z.v64 < UINT64_C(0x2000000000000000)) { + --expZ; + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); + } + if (! expC) { + if (! sigC) { + --expZ; + sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C(0x0010000000000000))<<9; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + sig128Z.v64 = softfloat_shiftRightJam64(sig128Z.v64, -expDiff); + } else { + sig128Z = softfloat_shortShiftRightJam128(sig128Z.v64, sig128Z.v0, 1); + } + } else if (expDiff) { + sig128C = softfloat_shiftRightJam128(sigC, 0, expDiff); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); + } else { + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + } + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + sig128Z = softfloat_sub128(sigC, 0, sig128Z.v64, sig128Z.v0); + } else if (! expDiff) { + sig128Z.v64 = sig128Z.v64 - sigC; + if (! (sig128Z.v64 | sig128Z.v0)) goto completeCancellation; + if (sig128Z.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig128Z = softfloat_sub128(0, 0, sig128Z.v64, sig128Z.v0); + } + } else { + sig128Z = softfloat_sub128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! sig128Z.v64) { + expZ -= 64; + sig128Z.v64 = sig128Z.v0; + sig128Z.v0 = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig128Z.v64) - 1; + expZ -= shiftDist; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig128Z.v64, -shiftDist); + } else { + sig128Z = softfloat_shortShiftLeft128(sig128Z.v64, sig128Z.v0, shiftDist); + sigZ = sig128Z.v64; + } + sigZ |= (sig128Z.v0 != 0); + } + roundPack: + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if (magBits) { + uiZ = packToF64UI(signZ, 0x7FF, 0); + if (signZ == signC || expC != 0x7FF) { + if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiZ; + } + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF64UI; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = packToF64UI(signC, expC, sigC); + if (!expC && sigC) { + /* Exact zero plus a denormal */ + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signC, 0, 0); + } + } + if (! (expC | sigC) && (signZ != signC)) { + completeCancellation: + uiZ = packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_range.c b/src/cpu/softfloat3e/f64_range.c new file mode 100644 index 000000000..6f01c84cc --- /dev/null +++ b/src/cpu/softfloat3e/f64_range.c @@ -0,0 +1,135 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_range(float64 a, float64 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool aIsNaN, bIsNaN; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF64UI(a)) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + if (softfloat_isSigNaNF64UI(b)) { + return softfloat_propagateNaNF64UI(b, 0, status); + } + + aIsNaN = isNaNF64UI(a); + bIsNaN = isNaNF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF64UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF64UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float64 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~UINT64_C(0x8000000000000000); // clear the sign bit + tmp_b = tmp_b & ~UINT64_C(0x8000000000000000); + signA = 0; + } + + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~UINT64_C(0x8000000000000000)) | (a & UINT64_C(0x8000000000000000)); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~UINT64_C(0x8000000000000000); // zero out the sign bit + break; + case 3: + z = z | UINT64_C(0x8000000000000000); // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f64_roundToInt.c b/src/cpu/softfloat3e/f64_roundToInt.c new file mode 100644 index 000000000..3c5f7fb8c --- /dev/null +++ b/src/cpu/softfloat3e/f64_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_roundToInt(float64 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + int64_t frac; + bool sign; + uint64_t uiZ, lastBitMask, roundBitsMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + frac = fracF64UI(a); + sign = signF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x433 <= (exp + scale)) { + if ((exp == 0x7FF) && frac) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF64UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0x3FE) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF64UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0x3FE) uiZ |= packToF64UI(0, 0x3FF - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF64UI(1, 0x3FF - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF64UI(0, 0x3FF - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint64_t) 1<<(0x433 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF64UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_scalef.c b/src/cpu/softfloat3e/f64_scalef.c new file mode 100644 index 000000000..7a552ccc3 --- /dev/null +++ b/src/cpu/softfloat3e/f64_scalef.c @@ -0,0 +1,156 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the double-precision floating +| point value `a' by multiplying it by 2 power of the double-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in double precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_scalef(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + int shiftCount; + int scale = 0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0x7FF) { + if (sigB) return softfloat_propagateNaNF64UI(a, b, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) { + int aIsSignalingNaN = (sigA & UINT64_C(0x0008000000000000)) == 0; + if (aIsSignalingNaN || expB != 0x7FF || sigB) + return softfloat_propagateNaNF64UI(a, b, status); + + return signB ? 0 : packToF64UI(0, 0x7FF, 0); + } + + if (expB == 0x7FF && signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (expB == 0x7FF && ! signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + return packToF64UI(signA, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((expB | sigB) == 0) return a; + + if (expB == 0x7FF) { + if (signB) return packToF64UI(signA, 0, 0); + return packToF64UI(signA, 0x7FF, 0); + } + + if (0x40F <= expB) { + // handle obvious overflow/underflow result + return softfloat_roundPackToF64(signA, signB ? -0x3FF : 0x7FF, sigA, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB < 0x3FF) { + if (expB == 0) + softfloat_raiseFlags(status, softfloat_flag_denormal); + scale = -signB; + } + else { + sigB |= UINT64_C(0x0010000000000000); + shiftCount = 0x433 - expB; + uint64_t prev_sigB = sigB; + sigB >>= shiftCount; + scale = (int32_t) sigB; + if (signB) { + if ((sigB< 0x1000) scale = 0x1000; + if (scale < -0x1000) scale = -0x1000; + } + + if (expA != 0) { + sigA |= UINT64_C(0x0010000000000000); + } else { + expA++; + } + + expA += scale - 1; + sigA <<= 10; + return softfloat_normRoundPackToF64(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f64_sqrt.c b/src/cpu/softfloat3e/f64_sqrt.c new file mode 100644 index 000000000..d3ea81af8 --- /dev/null +++ b/src/cpu/softfloat3e/f64_sqrt.c @@ -0,0 +1,130 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_sqrt(float64 a, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + int16_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + uint64_t rem; + uint32_t q; + uint64_t sigZ, shiftedSigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF64UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FF)>>1) + 0x3FE; + expA &= 1; + sigA |= UINT64_C(0x0010000000000000); + sig32A = sigA>>21; + recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if (expA) { + sigA <<= 8; + sig32Z >>= 1; + } else { + sigA <<= 9; + } + rem = sigA - (uint64_t) sig32Z * sig32Z; + q = ((uint32_t) (rem>>2) * (uint64_t) recipSqrt32)>>32; + sigZ = ((uint64_t) sig32Z<<32 | 1<<5) + ((uint64_t) q<<3); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((sigZ & 0x1FF) < 0x22) { + sigZ &= ~(uint64_t) 0x3F; + shiftedSigZ = sigZ>>6; + rem = (sigA<<52) - shiftedSigZ * shiftedSigZ; + if (rem & UINT64_C(0x8000000000000000)) { + --sigZ; + } else { + if (rem) sigZ |= 1; + } + } + return softfloat_roundPackToF64(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; +} diff --git a/src/cpu/softfloat3e/f64_to_extF80.cc b/src/cpu/softfloat3e/f64_to_extF80.cc new file mode 100644 index 000000000..88b27f9d3 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f64_to_extF80(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3C00); + uiZ0 = (frac | UINT64_C(0x0010000000000000))<<11; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f64_to_f128.cc b/src/cpu/softfloat3e/f64_to_f128.cc new file mode 100644 index 000000000..cfae72824 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f128.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f64_to_f128(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig64 normExpSig; + struct uint128 frac128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0); + uiZ.v0 = 0; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + uiZ.v64 = packToF128UI64(sign, 0, 0); + uiZ.v0 = 0; + return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac128 = softfloat_shortShiftLeft128(0, frac, 60); + uiZ.v64 = packToF128UI64(sign, exp + 0x3C00, frac128.v64); + uiZ.v0 = frac128.v0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_to_f16.c b/src/cpu/softfloat3e/f64_to_f16.c new file mode 100644 index 000000000..fe8dea057 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f16.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f64_to_f16(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + uint16_t uiZ, frac16; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF16UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac16 = softfloat_shortShiftRightJam64(frac, 38); + if (! (exp | frac16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF16(sign, exp - 0x3F1, frac16 | 0x4000, status); +} diff --git a/src/cpu/softfloat3e/f64_to_f32.c b/src/cpu/softfloat3e/f64_to_f32.c new file mode 100644 index 000000000..7ebbf428f --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f32.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f64_to_f32(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + uint32_t uiZ, frac32; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF32UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac32 = softfloat_shortShiftRightJam64(frac, 22); + if (! (exp | frac32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF32(sign, exp - 0x381, frac32 | 0x40000000, status); +} diff --git a/src/cpu/softfloat3e/f64_to_i32.c b/src/cpu/softfloat3e/f64_to_i32.c new file mode 100644 index 000000000..c296e0bd5 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i32.c @@ -0,0 +1,77 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f64_to_i32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FF) && sig) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x427 - exp; + if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToI32(sign, sig, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f64_to_i32_r_minMag.c b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c new file mode 100644 index 000000000..80e2d6bc3 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f64_to_i32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (shiftDist < 22) { + if (sign && (exp == 0x41E) && (sig < UINT64_C(0x0000000000200000))) { + if (exact && sig) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f64_to_i64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + } + return softfloat_roundToI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && fracF64UI(a) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; +} + diff --git a/src/cpu/softfloat3e/f64_to_i64_r_minMag.c b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c new file mode 100644 index 000000000..eb633eb22 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c @@ -0,0 +1,95 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f64_to_i64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + uint64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -10) { + if (a == packToF64UI(1, 0x43E, 0)) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig<<-shiftDist; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig>>shiftDist; + if (exact && (absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f64_to_ui32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FF) && sig) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x427 - exp; + if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToUI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c new file mode 100644 index 000000000..7610d7c37 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c @@ -0,0 +1,83 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f64_to_ui32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (sign || (shiftDist < 21)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + z = sig>>shiftDist; + if (exact && ((uint64_t) z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f64_to_ui64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + } + return softfloat_roundToUI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && fracF64UI(a) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c new file mode 100644 index 000000000..e7bda4c67 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f64_to_ui64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (sign) goto invalid; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + z = (sig | UINT64_C(0x0010000000000000))<<-shiftDist; + } else { + sig |= UINT64_C(0x0010000000000000); + z = sig>>shiftDist; + if (exact && (uint64_t) (sig<<(-shiftDist & 63))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FF) && sig ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat/fpatan.cc b/src/cpu/softfloat3e/fpatan.cc similarity index 59% rename from src/cpu/softfloat/fpatan.cc rename to src/cpu/softfloat3e/fpatan.cc index f33a3ff66..207dc320a 100644 --- a/src/cpu/softfloat/fpatan.cc +++ b/src/cpu/softfloat3e/fpatan.cc @@ -25,27 +25,31 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "softfloat.h" +#include "specialize.h" + +#include "fpu_trans.h" #include "fpu_constant.h" +#include "poly.h" #define FPATAN_ARR_SIZE 11 -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_sqrt3 = +static const float128_t float128_sqrt3 = packFloat128(BX_CONST64(0x3fffbb67ae8584ca), BX_CONST64(0xa73b25742d7078b8)); static const floatx80 floatx80_pi = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); -static const float128 float128_pi2 = +static const float128_t float128_pi2 = packFloat128(BX_CONST64(0x3fff921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi4 = +static const float128_t float128_pi4 = packFloat128(BX_CONST64(0x3ffe921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi6 = +static const float128_t float128_pi6 = packFloat128(BX_CONST64(0x3ffe0c152382d736), BX_CONST64(0x58465BB32E0F580F)); -static float128 atan_arr[FPATAN_ARR_SIZE] = +static float128_t atan_arr[FPATAN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ @@ -60,10 +64,10 @@ static float128 atan_arr[FPATAN_ARR_SIZE] = PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ }; -extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* |x| < 1/4 */ -static float128 poly_atan(float128 x1, struct float_status_t *status) +static float128_t poly_atan(float128_t x1, softfloat_status_t &status) { /* // 3 5 7 9 11 13 15 17 @@ -86,12 +90,11 @@ static float128 poly_atan(float128 x1, struct float_status_t *status) // atan(x) ~ x * [ p(x) + x * q(x) ] // */ - return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) atan_arr, FPATAN_ARR_SIZE, status); } // ================================================= -// FPATAN Compute y * log (x) -// 2 +// FPATAN Compute arctan(y/x) // ================================================= // @@ -134,125 +137,129 @@ static float128 poly_atan(float128 x1, struct float_status_t *status) // 3 5 7 9 2n+1 // -floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (aSign) { /* return 3PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status); - } - else { /* return PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } + if (aSign) /* return 3PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); + else /* return PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (bSig && (bExp == 0)) - float_raise(status, float_flag_denormal); + if (bSig && ! bExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); return_PI_or_ZERO: - if (aSign) { /* return PI */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } else { /* return 0 */ - return packFloatx80(bSign, 0, 0); - } + if (aSign) /* return PI */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); + else /* return 0 */ + return packToExtF80(bSign, 0, 0); } - if (bExp == 0) + if (! bExp) { - if (bSig == 0) { - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + if (! bSig) { + if (aSig && ! aExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); goto return_PI_or_ZERO; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) + if (! aExp) { - if (aSig == 0) /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + if (! aSig) /* return PI/2 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); /* |a| = |b| ==> return PI/4 */ - if (aSig == bSig && aExp == bExp) - return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + if (aSig == bSig && aExp == bExp) { + if (aSign) + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); + else + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); + } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status); - float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status); - float128 x; + float128_t a128 = softfloat_normRoundPackToF128(0, aExp-0x10, aSig, 0, &status); + float128_t b128 = softfloat_normRoundPackToF128(0, bExp-0x10, bSig, 0, &status); + float128_t x; int swap = 0, add_pi6 = 0, add_pi4 = 0; if (aExp > bExp || (aExp == bExp && aSig > bSig)) { - x = float128_div(b128, a128, status); + x = f128_div(b128, a128, &status); } else { - x = float128_div(a128, b128, status); + x = f128_div(a128, b128, &status); swap = 1; } - Bit32s xExp = extractFloat128Exp(x); + int32_t xExp = expF128UI64(x.v64); if (xExp <= FLOATX80_EXP_BIAS-40) goto approximation_completed; - if (x.hi >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 + if (x.v64 >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 { /* arctan(x) = arctan((x-1)/(x+1)) + pi/4 */ - float128 t1 = float128_sub(x, float128_one, status); - float128 t2 = float128_add(x, float128_one, status); - x = float128_div(t1, t2, status); + float128_t t1 = f128_sub(x, float128_one, &status); + float128_t t2 = f128_add(x, float128_one, &status); + x = f128_div(t1, t2, &status); add_pi4 = 1; } else @@ -263,26 +270,26 @@ return_PI_or_ZERO: /* arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 */ - float128 t1 = float128_mul(x, float128_sqrt3, status); - float128 t2 = float128_add(x, float128_sqrt3, status); - x = float128_sub(t1, float128_one, status); - x = float128_div(x, t2, status); + float128_t t1 = f128_mul(x, float128_sqrt3, &status); + float128_t t2 = f128_add(x, float128_sqrt3, &status); + x = f128_sub(t1, float128_one, &status); + x = f128_div(x, t2, &status); add_pi6 = 1; } } x = poly_atan(x, status); - if (add_pi6) x = float128_add(x, float128_pi6, status); - if (add_pi4) x = float128_add(x, float128_pi4, status); + if (add_pi6) x = f128_add(x, float128_pi6, &status); + if (add_pi4) x = f128_add(x, float128_pi4, &status); approximation_completed: - if (swap) x = float128_sub(float128_pi2, x, status); - floatx80 result = float128_to_floatx80(x, status); + if (swap) x = f128_sub(float128_pi2, x, &status); + floatx80 result = f128_to_extF80(x, &status); if (zSign) floatx80_chs(result); - int rSign = extractFloatx80Sign(result); + int rSign = extF80_sign(result); if (!bSign && rSign) - return floatx80_add(result, floatx80_pi, status); + return extF80_add(result, floatx80_pi, &status); if (bSign && !rSign) - return floatx80_sub(result, floatx80_pi, status); + return extF80_sub(result, floatx80_pi, &status); return result; } diff --git a/src/cpu/softfloat/fprem.cc b/src/cpu/softfloat3e/fprem.cc similarity index 53% rename from src/cpu/softfloat/fprem.cc rename to src/cpu/softfloat3e/fprem.cc index 26637c5c5..2252f1230 100644 --- a/src/cpu/softfloat/fprem.cc +++ b/src/cpu/softfloat3e/fprem.cc @@ -23,100 +23,109 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" #define USE_estimateDiv128To64 -#include "softfloat-macros.h" +#include "softfloat-helpers.h" + +#include "specialize.h" // for softfloat_propagateNaNExtF80UI /* executes single exponent reduction cycle */ -static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) +static uint64_t remainder_kernel(uint64_t aSig0, uint64_t bSig, int expDiff, uint64_t *zSig0, uint64_t *zSig1) { - Bit64u term0, term1; - Bit64u aSig1 = 0; - + uint128 term, z; + uint64_t aSig1 = 0; shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); - Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig); - mul64To128(bSig, q, &term0, &term1); - sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { + uint64_t q = estimateDiv128To64(aSig1, aSig0, bSig); + term = softfloat_mul64To128(bSig, q); + z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0); + while ((int64_t) z.v64 < 0) { --q; - add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); + z = softfloat_add128(z.v64, z.v0, 0, bSig); } + *zSig0 = z.v0; + *zSig1 = z.v64; return q; } -static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding_mode, struct float_status_t *status) +static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, int rounding_mode, struct softfloat_status_t *status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + static const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit32s aExp, bExp, zExp, expDiff; - Bit64u aSig0, aSig1, bSig; + int32_t aExp, bExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0, bSig; int aSign; + struct exp32_sig64 normExpSig; + uint128 term; + *q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - *r = propagateFloatx80NaN(a, b, status); + if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) { - *r = propagateFloatx80NaN(a, b, status); + if (bSig << 1) { + *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - if (aExp == 0 && aSig0) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; + if (! aExp && aSig0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } *r = a; return 0; } - if (bExp == 0) { - if (bSig == 0) { - float_raise(status, float_flag_invalid); + if (! bExp) { + if (! bSig) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { *r = a; return 0; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } - expDiff = aExp - bExp; - aSig1 = 0; - Bit32u overflow = 0; + expDiff = aExp - bExp; + int overflow = 0; if (expDiff >= 64) { int n = (expDiff & 0x1f) | 0x20; @@ -129,11 +138,10 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding if (expDiff < 0) { if (expDiff < -1) { - *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; + *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } @@ -147,26 +155,28 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding } } - if (rounding_mode == float_round_nearest_even) - { - Bit64u term0, term1; - shift128Right(bSig, 0, 1, &term0, &term1); + if (rounding_mode == softfloat_round_near_even) { + uint64_t term0, term1; + shortShift128Right(bSig, 0, 1, &term0, &term1); - if (! lt128(aSig0, aSig1, term0, term1)) - { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); - if ((eq && ((*q) & 1)) || lt) { - aSign = !aSign; - ++(*q); - } - if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); + if ((eq && ((*q) & 1)) || lt) { + aSign = !aSign; + ++(*q); + } + if (lt) { + term = softfloat_sub128(bSig, 0, aSig0, aSig1); + aSig0 = term.v64; + aSig1 = term.v0; + } } } } - *r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status); + *r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80, status); return overflow; } @@ -176,9 +186,9 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_nearest_even, status); + return do_fprem(a, b, r, q, softfloat_round_near_even, status); } /*---------------------------------------------------------------------------- @@ -190,7 +200,7 @@ int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, s | quotient of 'a' divided by 'b' to an integer. *----------------------------------------------------------------------------*/ -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_to_zero, status); + return do_fprem(a, b, r, q, softfloat_round_to_zero, status); } diff --git a/src/cpu/softfloat/fpu_constant.h b/src/cpu/softfloat3e/fpu_constant.h similarity index 98% rename from src/cpu/softfloat/fpu_constant.h rename to src/cpu/softfloat3e/fpu_constant.h index 7a7fc6f1a..d7d44ee3c 100644 --- a/src/cpu/softfloat/fpu_constant.h +++ b/src/cpu/softfloat3e/fpu_constant.h @@ -24,7 +24,7 @@ these four paragraphs for those parts of this code that are retained. #include "config.h" // Pentium CPU uses only 68-bit precision M_PI approximation -//#define BETTER_THAN_PENTIUM +// #define BETTER_THAN_PENTIUM /*============================================================================ * Written for Bochs (x86 achitecture simulator) by diff --git a/src/cpu/softfloat3e/fpu_trans.h b/src/cpu/softfloat3e/fpu_trans.h new file mode 100644 index 000000000..bd3d3cecb --- /dev/null +++ b/src/cpu/softfloat3e/fpu_trans.h @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003-2018 Stanislav Shwartsman +// Written by Stanislav Shwartsman [sshwarts at sourceforge net] +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +///////////////////////////////////////////////////////////////////////// + +#ifndef _FPU_TRANS_H_ +#define _FPU_TRANS_H_ + +#include "softfloat.h" +#include "softfloat-specialize.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ + +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status); +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status); + +floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status); +#ifdef __cplusplus +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status); +int fsin(floatx80 &a, softfloat_status_t &status); +int fcos(floatx80 &a, softfloat_status_t &status); +int ftan(floatx80 &a, softfloat_status_t &status); +#else +floatx80 fyl2x(floatx80 a, floatx80 b, struct softfloat_status_t *status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, struct softfloat_status_t *status); +floatx80 fpatan(floatx80 a, floatx80 b, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct softfloat_status_t *status); +int fsin(floatx80 *a, struct softfloat_status_t *status); +int fcos(floatx80 *a, struct softfloat_status_t *status); +int ftan(floatx80 *a, struct softfloat_status_t *status); +#endif + +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------------- +| Calculates the absolute value of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +static __inline floatx80 &floatx80_abs(floatx80 ®) +#else +static __inline floatx80 floatx80_abs(floatx80 reg) +#endif +{ + reg.signExp &= 0x7FFF; + return reg; +} + +/*----------------------------------------------------------------------------- +| Changes the sign of the extended double-precision floating-point value 'a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +static __inline floatx80 &floatx80_chs(floatx80 ®) +#else +static __inline floatx80 floatx80_chs(floatx80 reg) +#endif +{ + reg.signExp ^= 0x8000; + return reg; +} + +#ifdef __cplusplus +static __inline floatx80 FPU_round_const(const floatx80 &a, int adj) +#else +static __inline floatx80 FPU_round_const(const floatx80 a, int adj) +#endif +{ + floatx80 result = a; + result.signif += adj; + return result; +} + +#endif diff --git a/src/cpu/softfloat/fsincos.cc b/src/cpu/softfloat3e/fsincos.cc similarity index 68% rename from src/cpu/softfloat/fsincos.cc rename to src/cpu/softfloat3e/fsincos.cc index f5b33a823..1a2a018de 100644 --- a/src/cpu/softfloat/fsincos.cc +++ b/src/cpu/softfloat3e/fsincos.cc @@ -26,24 +26,29 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 #define USE_estimateDiv128To64 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "specialize.h" + +#include "fpu_trans.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" +#include "poly.h" + static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); /* reduce trigonometric function argument using 128-bit precision M_PI approximation */ -static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1) +static uint64_t argument_reduction_kernel(uint64_t aSig0, int Exp, uint64_t *zSig0, uint64_t *zSig1) { - Bit64u term0, term1, term2; - Bit64u aSig1 = 0; + uint64_t term0, term1, term2; + uint64_t aSig1 = 0; shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); - Bit64u q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); + uint64_t q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { + while ((int64_t)(*zSig1) < 0) { --q; add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); } @@ -51,35 +56,35 @@ static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bi return q; } -static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1) +static int reduce_trig_arg(int expDiff, int &zSign, uint64_t &aSig0, uint64_t &aSig1) { - Bit64u term0, term1, q = 0; + uint64_t term0, term1, q = 0; if (expDiff < 0) { - shift128Right(*aSig0, 0, 1, aSig0, aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } if (expDiff > 0) { - q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1); + q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1); } else { - if (FLOAT_PI_HI <= *aSig0) { - *aSig0 -= FLOAT_PI_HI; + if (FLOAT_PI_HI <= aSig0) { + aSig0 -= FLOAT_PI_HI; q = 1; } } - shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); - if (! lt128(*aSig0, *aSig1, term0, term1)) + shortShift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { - int lt = lt128(term0, term1, *aSig0, *aSig1); - int eq = eq128(*aSig0, *aSig1, term0, term1); + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); if ((eq && (q & 1)) || lt) { - *zSign = !(*zSign); + zSign = !zSign; ++q; } - if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1); + if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1); } return (int)(q & 3); @@ -88,7 +93,7 @@ static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1 #define SIN_ARR_SIZE 11 #define COS_ARR_SIZE 11 -static float128 sin_arr[SIN_ARR_SIZE] = +static float128_t sin_arr[SIN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ @@ -103,7 +108,7 @@ static float128 sin_arr[SIN_ARR_SIZE] = PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ }; -static float128 cos_arr[COS_ARR_SIZE] = +static float128_t cos_arr[COS_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ @@ -118,10 +123,8 @@ static float128 cos_arr[COS_ARR_SIZE] = PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ }; -extern float128 OddPoly (float128 x, float128 *arr, int n, struct float_status_t *status); - /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status) +static __inline float128_t poly_sin(float128_t x, softfloat_status_t &status) { // 3 5 7 9 11 13 15 // x x x x x x x @@ -143,13 +146,11 @@ BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status) // sin(x) ~ x * [ p(x) + x * q(x) ] // - return OddPoly(x, sin_arr, SIN_ARR_SIZE, status); + return OddPoly(x, (const float128_t*) sin_arr, SIN_ARR_SIZE, status); } -extern float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status); - /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status) +static __inline float128_t poly_cos(float128_t x, softfloat_status_t &status) { // 2 4 6 8 10 12 14 // x x x x x x x @@ -166,22 +167,22 @@ BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status) // cos(x) ~ [ p(x) + x * q(x) ] // - return EvenPoly(x, cos_arr, COS_ARR_SIZE, status); + return EvenPoly(x, (const float128_t*) cos_arr, COS_ARR_SIZE, status); } -BX_CPP_INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +static __inline void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = a; } -BX_CPP_INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +static __inline void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = floatx80_one; } -static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struct float_status_t *status) +static floatx80 sincos_approximation(int neg, float128_t r, uint64_t quotient, softfloat_status_t &status) { if (quotient & 0x1) { r = poly_cos(r, status); @@ -190,7 +191,7 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc r = poly_sin(r, status); } - floatx80 result = float128_to_floatx80(r, status); + floatx80 result = f128_to_extF80(r, &status); if (quotient & 0x2) neg = ! neg; @@ -220,59 +221,62 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc // sin(x+2pi) = sin(x) // -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status) +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; int aSign, zSign; int q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) { + if (extF80_isUnsupported(a)) { goto invalid; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) { - sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOne(a, status)); + if (aSig0 << 1) { + sincos_invalid(sin_a, cos_a, softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status)); return 0; } invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); sincos_invalid(sin_a, cos_a, floatx80_default_nan); return 0; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { sincos_tiny_argument(sin_a, cos_a, a); return 0; } - float_raise(status, float_flag_denormal); + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (sin_a) - float_raise(status, float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_underflow); sincos_tiny_argument(sin_a, cos_a, a); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -283,7 +287,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { @@ -294,7 +298,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t zExp = aExp; } else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ @@ -302,7 +306,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); if (aSign) q = -q; if (sin_a) *sin_a = sincos_approximation(zSign, r, q, status); @@ -311,14 +315,14 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t return 0; } -int fsin(floatx80 *a, struct float_status_t *status) +int fsin(floatx80 &a, softfloat_status_t &status) { - return fsincos(*a, a, 0, status); + return fsincos(a, &a, 0, status); } -int fcos(floatx80 *a, struct float_status_t *status) +int fcos(floatx80 &a, softfloat_status_t &status) { - return fsincos(*a, 0, a, status); + return fsincos(a, 0, &a, status); } // ================================================= @@ -348,51 +352,55 @@ int fcos(floatx80 *a, struct float_status_t *status) // cos(x) // -int ftan(floatx80 *a, struct float_status_t *status) +int ftan(floatx80 &a, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; int aSign, zSign; int q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(*a)) { + if (extF80_isUnsupported(a)) { goto invalid; } - aSig0 = extractFloatx80Frac(*a); - aExp = extractFloatx80Exp(*a); - aSign = extractFloatx80Sign(*a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) + if (aSig0 << 1) { - *a = propagateFloatx80NaNOne(*a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status); return 0; } invalid: - float_raise(status, float_flag_invalid); - *a = floatx80_default_nan; + softfloat_raiseFlags(&status, softfloat_flag_invalid); + a = floatx80_default_nan; return 0; } - if (aExp == 0) { - if (aSig0 == 0) return 0; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig0) return 0; + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact | float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_inexact | softfloat_flag_underflow); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -403,17 +411,17 @@ int ftan(floatx80 *a, struct float_status_t *status) if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { - *a = packFloatx80(aSign, aExp, aSig0); + a = packFloatx80(aSign, aExp, aSig0); return 0; } zExp = aExp; } else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ @@ -421,21 +429,21 @@ int ftan(floatx80 *a, struct float_status_t *status) /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); - float128 sin_r = poly_sin(r, status); - float128 cos_r = poly_cos(r, status); + float128_t sin_r = poly_sin(r, status); + float128_t cos_r = poly_cos(r, status); if (q & 0x1) { - r = float128_div(cos_r, sin_r, status); + r = f128_div(cos_r, sin_r, &status); zSign = ! zSign; } else { - r = float128_div(sin_r, cos_r, status); + r = f128_div(sin_r, cos_r, &status); } - *a = float128_to_floatx80(r, status); + a = f128_to_extF80(r, &status); if (zSign) - floatx80_chs(*a); + floatx80_chs(a); return 0; } diff --git a/src/cpu/softfloat/fyl2x.cc b/src/cpu/softfloat3e/fyl2x.cc similarity index 61% rename from src/cpu/softfloat/fyl2x.cc rename to src/cpu/softfloat3e/fyl2x.cc index 875f866a9..7c90e6207 100644 --- a/src/cpu/softfloat/fyl2x.cc +++ b/src/cpu/softfloat3e/fyl2x.cc @@ -24,29 +24,28 @@ these four paragraphs for those parts of this code that are retained. * ==========================================================================*/ #define FLOAT128 - -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "fpu_trans.h" +#include "specialize.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" +#include "poly.h" -static const floatx80 floatx80_one = - packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_two = +static const float128_t float128_two = packFloat128(BX_CONST64(0x4000000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_ln2inv2 = +static const float128_t float128_ln2inv2 = packFloat128(BX_CONST64(0x400071547652b82f), BX_CONST64(0xe1777d0ffda0d23a)); #define SQRT2_HALF_SIG BX_CONST64(0xb504f333f9de6484) -extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); - #define L2_ARR_SIZE 9 -static float128 ln_arr[L2_ARR_SIZE] = +static float128_t ln_arr[L2_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ @@ -59,7 +58,7 @@ static float128 ln_arr[L2_ARR_SIZE] = PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ }; -static float128 poly_ln(float128 x1, struct float_status_t *status) +static float128_t poly_ln(float128_t x1, softfloat_status_t &status) { /* // @@ -84,28 +83,28 @@ static float128 poly_ln(float128 x1, struct float_status_t *status) // 1-u // */ - return OddPoly(x1, ln_arr, L2_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) ln_arr, L2_ARR_SIZE, status); } /* required sqrt(2)/2 < x < sqrt(2) */ -static float128 poly_l2(float128 x, struct float_status_t *status) +static float128_t poly_l2(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p1 = float128_add(x, float128_one, status); - float128 x_m1 = float128_sub(x, float128_one, status); - x = float128_div(x_m1, x_p1, status); + float128_t x_p1 = f128_add(x, float128_one, &status); + float128_t x_m1 = f128_sub(x, float128_one, &status); + x = f128_div(x_m1, x_p1, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } -static float128 poly_l2p1(float128 x, struct float_status_t *status) +static float128_t poly_l2p1(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p2 = float128_add(x, float128_two, status); - x = float128_div(x, x_p2, status); + float128_t x_plus2 = f128_add(x, float128_two, &status); + x = f128_div(x, x_plus2, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } @@ -134,7 +133,7 @@ static float128 poly_l2p1(float128 x, struct float_status_t *status) // 1-u 3 5 7 2n+1 // -floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. @@ -142,71 +141,73 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = bSign ^ 1; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSign && (Bit64u)(aExp | aSig)) goto invalid; - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (bExp == 0x7FFF) { + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); + if (aSign && (uint64_t)(aExp | aSig)) goto invalid; + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); if (aExp < 0x3FFF) { return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; + if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid; return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { + if (! aExp) { + if (! aSig) { if ((bExp | bSig) == 0) goto invalid; - float_raise(status, float_flag_divbyzero); + softfloat_raiseFlags(&status, softfloat_flag_divbyzero); return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } if (aSign) goto invalid; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } if (aSign) goto invalid; - if (bExp == 0) { - if (bSig == 0) { + if (! bExp) { + if (! bSig) { if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); return packFloatx80(bSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) + if (aExp == 0x3FFF && ! (aSig<<1)) return packFloatx80(bSign, 0, 0); - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); int ExpDiff = aExp - 0x3FFF; aExp = 0; @@ -219,12 +220,15 @@ invalid: /* using float128 for approximation */ /* ******************************** */ - Bit64u zSig0, zSig1; - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128Four(0, aExp+0x3FFF, zSig0, zSig1); + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + + uint64_t zSig0, zSig1; + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); x = poly_l2(x, status); - x = float128_add(x, int64_to_float128((Bit64s) ExpDiff), status); - return floatx80_128_mul(b, x, status); + x = f128_add(x, i32_to_f128(ExpDiff), &status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } // ================================================= @@ -252,112 +256,117 @@ invalid: // 1-u 3 5 7 2n+1 // -floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status) { + int32_t aExp, bExp; + uint64_t aSig, bSig, zSig0, zSig1, zSig2; + int aSign, bSign; + /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit32s aExp, bExp; - Bit64u aSig, bSig, zSig0, zSig1, zSig2; - int aSign, bSign; - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); + + aSig = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); + bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) != 0 || ((bExp == 0x7FFF) && (bSig<<1) != 0)) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) { + if (bSig && ! bExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); return packFloatx80(zSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + if (! bExp) { + if (! bSig) return packFloatx80(zSign, 0, 0); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (aSign && aExp >= 0x3FFF) return a; if (aExp >= 0x3FFC) // big argument { - return fyl2x(floatx80_add(a, floatx80_one, status), b, status); + return fyl2x(extF80_add(a, floatx80_one, &status), b, status); } // handle tiny argument if (aExp < FLOATX80_EXP_BIAS-70) { // first order approximation, return (a*b)/ln(2) - Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; + int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; - mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } zExp = zExp + bExp - 0x3FFE; - mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } - return - roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80, &status); } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128Four(aSign, aExp, zSig0, zSig1); + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(aSign, aExp, zSig0, zSig1); x = poly_l2p1(x, status); - return floatx80_128_mul(b, x, status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } diff --git a/src/cpu/softfloat3e/i32_to_extF80.cc b/src/cpu/softfloat3e/i32_to_extF80.cc new file mode 100644 index 000000000..edd92ced0 --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_extF80.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t i32_to_extF80(int32_t a) +{ + uint16_t uiZ64; + uint32_t absA; + bool sign; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + absA = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA); + uiZ64 = packToExtF80UI64(sign, 0x401E - shiftDist); + absA <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = (uint64_t) absA<<32; + return z; +} diff --git a/src/cpu/softfloat3e/i32_to_f128.cc b/src/cpu/softfloat3e/i32_to_f128.cc new file mode 100644 index 000000000..1ae64e46b --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_f128.cc @@ -0,0 +1,59 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t i32_to_f128(int32_t a) +{ + uint64_t uiZ64; + bool sign; + uint32_t absA; + int8_t shiftDist; + float128_t z; + + uiZ64 = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) + 17; + uiZ64 = packToF128UI64(sign, 0x402E - shiftDist, (uint64_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 i32_to_f16(int32_t a, struct softfloat_status_t *status) +{ + bool sign; + uint32_t absA; + int8_t shiftDist; + uint16_t sig; + + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) - 21; + if (0 <= shiftDist) { + return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA<>(-shiftDist) | ((uint32_t) (absA<<(shiftDist & 31)) != 0) + : (uint16_t) absA< +#include +#include "internals.h" +#include "softfloat.h" + +float32 i32_to_f32(int32_t a, struct softfloat_status_t *status) +{ + bool sign; + uint32_t absA; + + sign = (a < 0); + if (! (a & 0x7FFFFFFF)) { + return sign ? packToF32UI(1, 0x9E, 0) : 0; + } + absA = sign ? -(uint32_t) a : (uint32_t) a; + return softfloat_normRoundPackToF32(sign, 0x9C, absA, status); +} diff --git a/src/cpu/softfloat3e/i32_to_f64.c b/src/cpu/softfloat3e/i32_to_f64.c new file mode 100644 index 000000000..7aaa4e1c2 --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_f64.c @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 i32_to_f64(int32_t a) +{ + bool sign; + uint32_t absA; + int8_t shiftDist; + + if (! a) { + return 0; + } else { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) + 21; + return packToF64UI(sign, 0x432 - shiftDist, (uint64_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t i64_to_extF80(int64_t a) +{ + uint16_t uiZ64; + uint64_t absA; + bool sign; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + absA = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA); + uiZ64 = packToExtF80UI64(sign, 0x403E - shiftDist); + absA <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = absA; + return z; +} diff --git a/src/cpu/softfloat3e/i64_to_f128.cc b/src/cpu/softfloat3e/i64_to_f128.cc new file mode 100644 index 000000000..4d80a9e7a --- /dev/null +++ b/src/cpu/softfloat3e/i64_to_f128.cc @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t i64_to_f128(int64_t a) +{ + uint64_t uiZ64, uiZ0; + bool sign; + uint64_t absA; + int8_t shiftDist; + struct uint128 zSig; + float128_t z; + + if (! a) { + uiZ64 = 0; + uiZ0 = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) + 49; + if (64 <= shiftDist) { + zSig.v64 = absA<<(shiftDist - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128(0, absA, shiftDist); + } + uiZ64 = packToF128UI64(sign, 0x406E - shiftDist, zSig.v64); + uiZ0 = zSig.v0; + } + z.v64 = uiZ64; + z.v0 = uiZ0; + return z; +} diff --git a/src/cpu/softfloat3e/i64_to_f16.c b/src/cpu/softfloat3e/i64_to_f16.c new file mode 100644 index 000000000..43873610a --- /dev/null +++ b/src/cpu/softfloat3e/i64_to_f16.c @@ -0,0 +1,61 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 i64_to_f16(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + int8_t shiftDist; + uint16_t sig; + + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) - 53; + if (0 <= shiftDist) { + return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 i64_to_f32(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + int8_t shiftDist; + uint32_t sig; + + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) - 40; + if (0 <= shiftDist) { + return a ? packToF32UI(sign, 0x95 - shiftDist, (uint32_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 i64_to_f64(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + + sign = (a < 0); + if (! (a & UINT64_C(0x7FFFFFFFFFFFFFFF))) { + return sign ? packToF64UI(1, 0x43E, 0) : 0; + } + absA = sign ? -(uint64_t) a : (uint64_t) a; + return softfloat_normRoundPackToF64(sign, 0x43C, absA, status); +} diff --git a/src/cpu/softfloat3e/internals.h b/src/cpu/softfloat3e/internals.h new file mode 100644 index 000000000..3b5d7aa4d --- /dev/null +++ b/src/cpu/softfloat3e/internals.h @@ -0,0 +1,150 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _INTERNALS_H_ +#define _INTERNALS_H_ + +#include +#include +//#include "primitives.h" +#include "softfloat_types.h" + +struct softfloat_status_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +uint32_t softfloat_roundToUI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); + +int32_t softfloat_roundToI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); +int64_t softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + + +#define signF16UI(a) ((bool) ((uint16_t) (a)>>15)) +#define expF16UI(a) ((int8_t) ((a)>>10) & 0x1F) +#define fracF16UI(a) ((a) & 0x03FF) +#define packToF16UI(sign, exp, sig) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig)) + +#define isNaNF16UI(a) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF)) + +struct exp8_sig16 { int8_t exp; uint16_t sig; }; +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t); + +float16 softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); +float16 softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF32UI(a) ((bool) ((uint32_t) (a)>>31)) +#define expF32UI(a) ((int16_t) ((a)>>23) & 0xFF) +#define fracF32UI(a) ((a) & 0x007FFFFF) +#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + +#define isNaNF32UI(a) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) + +struct exp16_sig32 { int16_t exp; uint32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t); + +float32 softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); +float32 softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF64UI(a) ((bool) ((uint64_t) (a)>>63)) +#define expF64UI(a) ((int16_t) ((a)>>52) & 0x7FF) +#define fracF64UI(a) ((a) & UINT64_C(0x000FFFFFFFFFFFFF)) +#define packToF64UI(sign, exp, sig) ((uint64_t) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<52) + (sig))) + +#define isNaNF64UI(a) (((~(a) & UINT64_C(0x7FF0000000000000)) == 0) && ((a) & UINT64_C(0x000FFFFFFFFFFFFF))) + +struct exp16_sig64 { int16_t exp; uint64_t sig; }; +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t); + +float64 softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); +float64 softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status); +extFloat80_t softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status); + +#define signExtF80UI64(a64) ((bool) ((uint16_t) (a64)>>15)) +#define expExtF80UI64(a64) ((a64) & 0x7FFF) +#define packToExtF80UI64(sign, exp) ((uint16_t) (sign)<<15 | (exp)) + +#define isNaNExtF80UI(a64, a0) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C(0x7FFFFFFFFFFFFFFF))) + +extFloat80_t packToExtF80(bool, uint16_t, uint64_t); +extFloat80_t packToExtF80_twoargs(uint16_t, uint64_t); +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +struct exp32_sig64 { int32_t exp; uint64_t sig; }; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t); + +extFloat80_t + softfloat_roundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *); +extFloat80_t + softfloat_normRoundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI64(a64) ((bool) ((uint64_t) (a64)>>63)) +#define expF128UI64(a64) ((int32_t) ((a64)>>48) & 0x7FFF) +#define fracF128UI64(a64) ((a64) & UINT64_C(0x0000FFFFFFFFFFFF)) +#define packToF128UI64(sign, exp, sig64) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<48) + (sig64)) + +#define isNaNF128UI(a64, a0) (((~(a64) & UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64) & UINT64_C(0x0000FFFFFFFFFFFF)))) + +struct exp32_sig128 { int32_t exp; struct uint128 sig; }; +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t, uint64_t); + +float128_t + softfloat_roundPackToF128(bool, int32_t, uint64_t, uint64_t, uint64_t, struct softfloat_status_t *); +float128_t + softfloat_normRoundPackToF128(bool, int32_t, uint64_t, uint64_t, struct softfloat_status_t *); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpu/softfloat3e/isNaN.cc b/src/cpu/softfloat3e/isNaN.cc new file mode 100644 index 000000000..8c0bd1912 --- /dev/null +++ b/src/cpu/softfloat3e/isNaN.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f16_isNaN(float16 a) +{ + return isNaNF16UI(a); +} + +bool f32_isNaN(float32 a) +{ + return isNaNF32UI(a); +} + +bool f64_isNaN(float64 a) +{ + return isNaNF64UI(a); +} + +bool extF80_isNaN(extFloat80_t a) +{ + return isNaNExtF80UI(a.signExp, a.signif); +} + +bool f128_isNaN(float128_t a) +{ + return isNaNF128UI(a.v64, a.v0); +} diff --git a/src/cpu/softfloat3e/isSignalingNaN.cc b/src/cpu/softfloat3e/isSignalingNaN.cc new file mode 100644 index 000000000..994ac3784 --- /dev/null +++ b/src/cpu/softfloat3e/isSignalingNaN.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f16_isSignalingNaN(float16 a) +{ + return softfloat_isSigNaNF16UI(a); +} + +bool f32_isSignalingNaN(float32 a) +{ + return softfloat_isSigNaNF32UI(a); +} + +bool f64_isSignalingNaN(float64 a) +{ + return softfloat_isSigNaNF64UI(a); +} + +bool extF80_isSignalingNaN(extFloat80_t a) +{ + return softfloat_isSigNaNExtF80UI(a.signExp, a.signif); +} + +bool f128_isSignalingNaN(float128_t a) +{ + return softfloat_isSigNaNF128UI(a.v64, a.v0); +} diff --git a/src/cpu/softfloat3e/opts-GCC.h b/src/cpu/softfloat3e/opts-GCC.h new file mode 100644 index 000000000..dd6c0ab64 --- /dev/null +++ b/src/cpu/softfloat3e/opts-GCC.h @@ -0,0 +1,110 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2017 The Regents of the University of California. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _OPTS_GCC_H_ +#define _OPTS_GCC_H_ + +#include +#include "primitiveTypes.h" + +#ifdef SOFTFLOAT_BUILTIN_CLZ + +static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a) + { return a ? __builtin_clz(a) - 16 : 16; } +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 + +static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a) + { return a ? __builtin_clz(a) : 32; } +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 + +static __inline uint8_t softfloat_countLeadingZeros64(uint64_t a) + { return a ? __builtin_clzll(a) : 64; } +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 + +#endif + +#ifdef SOFTFLOAT_INTRINSIC_INT128 + +static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * ((uint64_t) b<<32); + return uZ.s; +} +#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 + +static __inline struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * b; + return uZ.s; +} +#define softfloat_mul64To128 softfloat_mul64To128 + +static __inline +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = ((unsigned __int128) a64<<64 | a0) * b; + return uZ.s; +} +#define softfloat_mul128By32 softfloat_mul128By32 + +static __inline +void + softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr) +{ + unsigned __int128 z0, mid1, mid, z128; + z0 = (unsigned __int128) a0 * b0; + mid1 = (unsigned __int128) a64 * b0; + mid = mid1 + (unsigned __int128) a0 * b64; + z128 = (unsigned __int128) a64 * b64; + z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64; + mid <<= 64; + z0 += mid; + z128 += (z0 < mid); + zPtr[indexWord(4, 0)] = z0; + zPtr[indexWord(4, 1)] = z0>>64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z128>>64; +} +#define softfloat_mul128To256M softfloat_mul128To256M + +#endif + +#endif + +#endif diff --git a/src/cpu/softfloat/softfloat_poly.cc b/src/cpu/softfloat3e/poly.cc similarity index 84% rename from src/cpu/softfloat/softfloat_poly.cc rename to src/cpu/softfloat3e/poly.cc index 5c7079353..a89d7f03f 100644 --- a/src/cpu/softfloat/softfloat_poly.cc +++ b/src/cpu/softfloat3e/poly.cc @@ -23,10 +23,10 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#define FLOAT128 - #include + #include "softfloat.h" +#include "poly.h" // 2 3 4 n // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) @@ -39,13 +39,15 @@ these four paragraphs for those parts of this code that are retained. // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status) { - float128 r = arr[--n]; + float128_t r = arr[--n]; do { - r = float128_mul(r, x, status); - r = float128_add(r, arr[--n], status); + r = f128_mulAdd(r, x, arr[--n], 0, status); +// r = f128_mul(r, x, &status); +// r = f128_add(r, arr[--n], &status); + } while (n > 0); return r; @@ -63,9 +65,9 @@ float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *statu // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return EvalPoly(float128_mul(x, x, status), arr, n, status); + return EvalPoly(f128_mul(x, x, &status), arr, n, &status); } // 3 5 7 9 2n+1 @@ -83,7 +85,7 @@ float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *statu // f(x) ~ x * [ p(x) + x * q(x) ] // -float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return float128_mul(x, EvenPoly(x, arr, n, status), status); + return f128_mul(x, EvenPoly(x, arr, n, status), &status); } diff --git a/src/cpu/softfloat3e/poly.h b/src/cpu/softfloat3e/poly.h new file mode 100644 index 000000000..1d6c3170c --- /dev/null +++ b/src/cpu/softfloat3e/poly.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003-2018 Stanislav Shwartsman +// Written by Stanislav Shwartsman [sshwarts at sourceforge net] +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +///////////////////////////////////////////////////////////////////////// + +#ifndef _POLY_H_ +#define _POLY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); +float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); +#else +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status); +float128_t OddPoly(float128_t x, const float128_t *arr, int n, struct float_status_t *status); +#endif // __cplusplus + +#ifdef __cplusplus +} +#endif + +#endif // _POLY_H_ diff --git a/src/cpu/softfloat3e/primitiveTypes.h b/src/cpu/softfloat3e/primitiveTypes.h new file mode 100644 index 000000000..67751372f --- /dev/null +++ b/src/cpu/softfloat3e/primitiveTypes.h @@ -0,0 +1,54 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef primitiveTypes_h +#define primitiveTypes_h + +/*---------------------------------------------------------------------------- +| These macros are used to isolate the differences in word order between big- +| endian and little-endian platforms. +*----------------------------------------------------------------------------*/ +#define wordIncr 1 +#define indexWord(total, n) (n) +#define indexWordHi(total) ((total) - 1) +#define indexWordLo(total) 0 +#define indexMultiword(total, m, n) (n) +#define indexMultiwordHi(total, n) ((total) - (n)) +#define indexMultiwordLo(total, n) 0 +#define indexMultiwordHiBut(total, n) (n) +#define indexMultiwordLoBut(total, n) 0 +#define INIT_UINTM4(v3, v2, v1, v0) { v0, v1, v2, v3 } + +#endif diff --git a/src/cpu/softfloat3e/primitives.h b/src/cpu/softfloat3e/primitives.h new file mode 100644 index 000000000..993067996 --- /dev/null +++ b/src/cpu/softfloat3e/primitives.h @@ -0,0 +1,535 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _PRIMITIVES_H_ +#define _PRIMITIVES_H_ + +#include +#include +#include "softfloat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOFTFLOAT_FAST_DIV64TO32 + +#ifndef softfloat_shortShiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must be in +| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +static __inline +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint8_t dist) +{ + return a>>dist | ((a & (((uint64_t) 1<>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} +#endif + +#ifndef softfloat_shiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must not +| be zero. If any nonzero bits are shifted off, they are "jammed" into the +| least-significant bit of the shifted value by setting the least-significant +| bit to 1. This shifted-and-jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 64, the result will be either 0 or 1, depending on whether 'a' +| is zero or nonzero. +*----------------------------------------------------------------------------*/ +static __inline uint64_t softfloat_shiftRightJam64(uint64_t a, uint32_t dist) +{ + return (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +} +#endif + +/*---------------------------------------------------------------------------- +| A constant table that translates an 8-bit unsigned integer (the array index) +| into the number of leading 0 bits before the most-significant 1 of that +| integer. For integer zero (index 0), the corresponding table element is 8. +*----------------------------------------------------------------------------*/ +extern const uint_least8_t softfloat_countLeadingZeros8[256]; + +#ifndef softfloat_countLeadingZeros16 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 16 is returned. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a) +{ + uint8_t count = 8; + if (0x100 <= a) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; +} +#endif + +#ifndef softfloat_countLeadingZeros32 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a) +{ + uint8_t count = 0; + if (a < 0x10000) { + count = 16; + a <<= 16; + } + if (a < 0x1000000) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} +#endif + +#ifndef softfloat_countLeadingZeros64 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ +uint8_t softfloat_countLeadingZeros64(uint64_t a); +#endif + +extern const uint16_t softfloat_approxRecip_1k0s[16]; +extern const uint16_t softfloat_approxRecip_1k1s[16]; + +#ifndef softfloat_approxRecip32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the number represented by 'a', +| where 'a' is interpreted as an unsigned fixed-point number with one integer +| bit and 31 fraction bits. The 'a' input must be "normalized", meaning that +| its most-significant bit (bit 31) must be 1. Thus, if A is the value of +| the fixed-point interpretation of 'a', then 1 <= A < 2. The returned value +| is interpreted as a pure unsigned fraction, having no integer bits and 32 +| fraction bits. The approximation returned is never greater than the true +| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp +| (units in the last place). +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_DIV64TO32 +#define softfloat_approxRecip32_1(a) ((uint32_t) (UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t) (a))) +#endif +#endif + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[16]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[16]; + +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the square root of the number +| represented by 'a', where 'a' is interpreted as an unsigned fixed-point +| number either with one integer bit and 31 fraction bits or with two integer +| bits and 30 fraction bits. The format of 'a' is determined by 'oddExpA', +| which must be either 0 or 1. If 'oddExpA' is 1, 'a' is interpreted as +| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having +| two integer bits. The 'a' input must be "normalized", meaning that its +| most-significant bit (bit 31) must be 1. Thus, if A is the value of the +| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA' +| is 1, and 2 <= A < 4 when 'oddExpA' is 0. +| The returned value is interpreted as a pure unsigned fraction, having +| no integer bits and 32 fraction bits. The approximation returned is never +| greater than the true reciprocal 1/sqrt(A), and it differs from the true +| reciprocal by at most 2.06 ulp (units in the last place). The approximation +| returned is also always within the range 0.5 to 1; thus, the most- +| significant bit of the result is always set. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a); + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 == b64) && (a0 == b0); +} + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than or equal to the 128-bit unsigned integer formed by +| concatenating 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); +} + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 < b0)); +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the +| number of bits given in 'dist', which must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + z.v64 = a64<>(-dist & 63); + z.v0 = a0<>dist; + z.v0 = a64<<(-dist & 63) | a0>>dist; + return z; +} + +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam64Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +static __inline +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint8_t dist) +{ + struct uint64_extra z; + z.v = a>>dist; + z.extra = a<<(-dist & 63) | (extra != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must be in the range 1 to 63. If any +| nonzero bits are shifted off, they are "jammed" into the least-significant +| bit of the shifted value by setting the least-significant bit to 1. This +| shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + uint8_t negDist = -dist; + struct uint128 z; + z.v64 = a64>>dist; + z.v0 = + a64<<(negDist & 63) | a0>>dist + | ((uint64_t) (a0<<(negDist & 63)) != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam128Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint8_t dist) +{ + uint8_t negDist = -dist; + struct uint128_extra z; + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(negDist & 63) | a0>>dist; + z.extra = a0<<(negDist & 63) | (extra != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64 +| _plus_ the number of bits given in 'dist', which must not be zero. This +| shifted value is at most 64 nonzero bits and is returned in the 'v' field +| of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result +| contains a value formed as follows from the bits that were shifted off: The +| _last_ bit shifted off is the most-significant bit of the 'extra' field, and +| the other 63 bits of the 'extra' field are all zero if and only if _all_but_ +| _the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a' and 'extra' are considered to form +| an unsigned fixed-point number with binary point between 'a' and 'extra'. +| This fixed-point value is shifted right by the number of bits given in +| 'dist', and the integer part of this shifted value is returned in the 'v' +| field of the result. The fractional part of the shifted value is modified +| as described above and returned in the 'extra' field of the result.) +*----------------------------------------------------------------------------*/ +static __inline +struct uint64_extra + softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint32_t dist) +{ + struct uint64_extra z; + if (dist < 64) { + z.v = a>>dist; + z.extra = a<<(-dist & 63); + } else { + z.v = 0; + z.extra = (dist == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must not be zero. If any nonzero bits +| are shifted off, they are "jammed" into the least-significant bit of the +| shifted value by setting the least-significant bit to 1. This shifted-and- +| jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 128, the result will be either 0 or 1, depending on whether the +| original 128 bits are all zeros. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 + softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128 z; + + if (dist < 64) { + u8NegDist = -dist; + z.v64 = a64>>dist; + z.v0 = + a64<<(u8NegDist & 63) | a0>>dist + | ((uint64_t) (a0<<(u8NegDist & 63)) != 0); + } else { + z.v64 = 0; + z.v0 = + (dist < 127) + ? a64>>(dist & 63) + | (((a64 & (((uint64_t) 1<<(dist & 63)) - 1)) | a0) + != 0) + : ((a64 | a0) != 0); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right +| by 64 _plus_ the number of bits given in 'dist', which must not be zero. +| This shifted value is at most 128 nonzero bits and is returned in the 'v' +| field of the 'struct uint128_extra' result. The 64-bit 'extra' field of the +| result contains a value formed as follows from the bits that were shifted +| off: The _last_ bit shifted off is the most-significant bit of the 'extra' +| field, and the other 63 bits of the 'extra' field are all zero if and only +| if _all_but_the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a64', 'a0', and 'extra' are considered +| to form an unsigned fixed-point number with binary point between 'a0' and +| 'extra'. This fixed-point value is shifted right by the number of bits +| given in 'dist', and the integer part of this shifted value is returned +| in the 'v' field of the result. The fractional part of the shifted value +| is modified as described above and returned in the 'extra' field of the +| result.) +*----------------------------------------------------------------------------*/ +static __inline +struct uint128_extra + softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128_extra z; + + u8NegDist = -dist; + if (dist < 64) { + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist; + z.extra = a0<<(u8NegDist & 63); + } else { + z.v.v64 = 0; + if (dist == 64) { + z.v.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if (dist < 128) { + z.v.v0 = a64>>(dist & 63); + z.extra = a64<<(u8NegDist & 63); + } else { + z.v.v0 = 0; + z.extra = (dist == 128) ? a64 : (a64 != 0); + } + } + } + z.extra |= (extra != 0); + return z; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', which must not be zero. If any nonzero bits are +| shifted off, they are "jammed" into the least-significant bit of the shifted +| value by setting the least-significant bit to 1. This shifted-and-jammed +| value is stored at the location pointed to by 'zPtr'. Each of 'aPtr' and +| 'zPtr' points to an array of four 64-bit elements that concatenate in the +| platform's normal endian order to form a 256-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' +| is greater than 256, the stored result will be either 0 or 1, depending on +| whether the original 256 bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *zPtr); + +#ifndef softfloat_add128 +/*---------------------------------------------------------------------------- +| Returns the sum of the 128-bit integer formed by concatenating 'a64' and +| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. The +| addition is modulo 2^128, so any carry out is lost. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} +#endif + +#ifndef softfloat_add256M +/*---------------------------------------------------------------------------- +| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'. The addition +| is modulo 2^256, so any carry out is lost. The sum is stored at the +| location pointed to by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to +| an array of four 64-bit elements that concatenate in the platform's normal +| endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr); +#endif + +#ifndef softfloat_sub128 +/*---------------------------------------------------------------------------- +| Returns the difference of the 128-bit integer formed by concatenating 'a64' +| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. +| The subtraction is modulo 2^128, so any borrow out (carry out) is lost. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + z.v0 = a0 - b0; + z.v64 = a64 - b64; + z.v64 -= (a0 < b0); + return z; +} +#endif + +#ifndef softfloat_sub256M +/*---------------------------------------------------------------------------- +| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer +| pointed to by 'aPtr'. The addition is modulo 2^256, so any borrow out +| (carry out) is lost. The difference is stored at the location pointed to +| by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four +| 64-bit elements that concatenate in the platform's normal endian order to +| form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_sub256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr); +#endif + +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a', 'b', and 2^32. +*----------------------------------------------------------------------------*/ +static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + uint64_t mid; + struct uint128 z; + mid = (uint64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a' and 'b'. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b); + +/*---------------------------------------------------------------------------- +| Returns the product of the 128-bit integer formed by concatenating 'a64' and +| 'a0', multiplied by 'b'. The multiplication is modulo 2^128; any overflow +| bits are discarded. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + struct uint128 z; + uint64_t mid; + uint32_t carry; + z.v0 = a0 * b; + mid = (uint64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint32_t) (z.v0>>32) - (uint32_t) mid); + z.v64 = a64 * b + (uint32_t) ((mid + carry)>>32); + return z; +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and +| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and +| 'b0'. The 256-bit product is stored at the location pointed to by 'zPtr'. +| Argument 'zPtr' points to an array of four 64-bit elements that concatenate +| in the platform's normal endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr); +#ifdef __cplusplus +} +#endif + +#endif // _PRIMITIVES_H_ diff --git a/src/cpu/softfloat3e/s_add128.cc b/src/cpu/softfloat3e/s_add128.cc new file mode 100644 index 000000000..8efabb850 --- /dev/null +++ b/src/cpu/softfloat3e/s_add128.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_add128 + +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} + +#endif + diff --git a/src/cpu/softfloat3e/s_add256M.c b/src/cpu/softfloat3e/s_add256M.c new file mode 100644 index 000000000..32fdf122f --- /dev/null +++ b/src/cpu/softfloat3e/s_add256M.c @@ -0,0 +1,60 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_add256M + +void softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr) +{ + unsigned int index; + uint8_t carry; + uint64_t wordA, wordZ; + + index = indexWordLo(4); + carry = 0; + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + if (index == indexWordHi(4)) break; + if (wordZ != wordA) carry = (wordZ < wordA); + index += wordIncr; + } +} + +#endif + diff --git a/src/cpu/softfloat3e/s_addMagsExtF80.cc b/src/cpu/softfloat3e/s_addMagsExtF80.cc new file mode 100644 index 000000000..5cc969198 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsExtF80.cc @@ -0,0 +1,146 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + uint64_t sigA; + int32_t expB; + uint64_t sigB; + int32_t expDiff; + uint64_t sigZ, sigZExtra; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64(uiA64); + sigA = uiA0; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA << 1) || ((expB == 0x7FFF) && (sigB << 1))) + goto propagateNaN; + if (sigB && ! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80_twoargs(uiA64, uiA0); + } + if (expB == 0x7FFF) { + if (sigB << 1) goto propagateNaN; + if (sigA && ! expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (! expB && sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + expZ = expB; + sigZ = sigB; + sigZExtra = 0; + goto roundAndPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0) { + if (sigB == 0) { + expZ = expA; + sigZ = sigA; + sigZExtra = 0; + goto roundAndPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + sigZ = sigA + sigB; + sigZExtra = 0; + expZ = expA; + goto shiftRight1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expDiff < 0) { + expZ = expB; + sig64Extra = softfloat_shiftRightJam64Extra(sigA, 0, -expDiff); + sigA = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } else { + expZ = expA; + sig64Extra = softfloat_shiftRightJam64Extra(sigB, 0, expDiff); + sigB = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } + sigZ = sigA + sigB; + if (sigZ & UINT64_C(0x8000000000000000)) goto roundAndPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftRight1: + sig64Extra = softfloat_shortShiftRightJam64Extra(sigZ, sigZExtra, 1); + sigZ = sig64Extra.v | UINT64_C(0x8000000000000000); + sigZExtra = sig64Extra.extra; + ++expZ; + roundAndPack: + return softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); +} diff --git a/src/cpu/softfloat3e/s_addMagsF128.cc b/src/cpu/softfloat3e/s_addMagsF128.cc new file mode 100644 index 000000000..b831796cc --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF128.cc @@ -0,0 +1,138 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float128_t softfloat_addMagsF128(uint64_t uiA64, uint64_t uiA0, uint64_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + struct uint128 sigA; + int32_t expB; + struct uint128 sigB; + int32_t expDiff; + struct uint128 uiZ, sigZ; + int32_t expZ; + uint64_t sigZExtra; + struct uint128_extra sig128Extra; + + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + expDiff = expA - expB; + if (! expDiff) { + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + sigZ = softfloat_add128(sigA.v64, sigA.v0, sigB.v64, sigB.v0); + if (! expA) { + uiZ.v64 = packToF128UI64(signZ, 0, sigZ.v64); + uiZ.v0 = sigZ.v0; + return uiZ; + } + expZ = expA; + sigZ.v64 |= UINT64_C(0x0002000000000000); + sigZExtra = 0; + goto shiftRight1; + } + if (expDiff < 0) { + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + } + expZ = expB; + if (expA) { + sigA.v64 |= UINT64_C(0x0001000000000000); + } else { + ++expDiff; + sigZExtra = 0; + if (! expDiff) goto newlyAligned; + } + sig128Extra = + softfloat_shiftRightJam128Extra(sigA.v64, sigA.v0, 0, -expDiff); + sigA = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } else { + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + expZ = expA; + if (expB) { + sigB.v64 |= UINT64_C(0x0001000000000000); + } else { + --expDiff; + sigZExtra = 0; + if (! expDiff) goto newlyAligned; + } + sig128Extra = softfloat_shiftRightJam128Extra(sigB.v64, sigB.v0, 0, expDiff); + sigB = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + newlyAligned: + sigZ = + softfloat_add128( + sigA.v64 | UINT64_C(0x0001000000000000), + sigA.v0, + sigB.v64, + sigB.v0 + ); + --expZ; + if (sigZ.v64 < UINT64_C(0x0002000000000000)) goto roundAndPack; + ++expZ; + shiftRight1: + sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.v64, sigZ.v0, sigZExtra, 1); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + roundAndPack: + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_addMagsF16.c b/src/cpu/softfloat3e/s_addMagsF16.c new file mode 100644 index 000000000..022f254a8 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF16.c @@ -0,0 +1,192 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 softfloat_addMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + int8_t expB; + uint16_t sigB; + int8_t expDiff; + uint16_t uiZ; + bool signZ; + int8_t expZ; + uint16_t sigZ; + uint16_t sigX, sigY; + int8_t shiftDist; + uint32_t sig32Z; + int8_t roundingMode; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + signZ = signF16UI(uiA); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF16UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF16UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF16UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0x1F) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = 0x0800 + sigA + sigB; + if (! (sigZ & 1) && (expZ < 0x1E)) { + sigZ >>= 1; + goto pack; + } + sigZ <<= 3; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF16UI(signZ, 0x1F, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + if (expDiff <= -13) { + uiZ = packToF16UI(signZ, expB, sigB); + if (expA | sigA) goto addEpsilon; + return uiZ; + } + expZ = expB; + sigX = sigB | 0x0400; + sigY = sigA + (expA ? 0x0400 : sigA); + shiftDist = 19 + expDiff; + } else { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + uiZ = uiA; + if (expA == 0x1F) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiZ; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + if (13 <= expDiff) { + if (expB | sigB) goto addEpsilon; + return uiZ; + } + expZ = expA; + sigX = sigA | 0x0400; + sigY = sigB + (expB ? 0x0400 : sigB); + shiftDist = 19 - expDiff; + } + sig32Z = ((uint32_t) sigX<<19) + ((uint32_t) sigY<>16; + if (sig32Z & 0xFFFF) { + sigZ |= 1; + } else { + if (! (sigZ & 0xF) && (expZ < 0x1E)) { + sigZ >>= 4; + goto pack; + } + } + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(uiA, uiB, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + addEpsilon: + roundingMode = softfloat_getRoundingMode(status); + if (roundingMode != softfloat_round_near_even) { + if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + ++uiZ; + if ((uint16_t) (uiZ<<1) == 0xF800) { + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + } + } + } + softfloat_raiseFlags(status, softfloat_flag_inexact); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + pack: + return packToF16UI(signZ, expZ, sigZ); +} diff --git a/src/cpu/softfloat3e/s_addMagsF32.c b/src/cpu/softfloat3e/s_addMagsF32.c new file mode 100644 index 000000000..df902348a --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF32.c @@ -0,0 +1,147 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float32 softfloat_addMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + int16_t expB; + uint32_t sigB; + int16_t expDiff; + uint32_t uiZ; + bool signZ; + int16_t expZ; + uint32_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + signZ = signF32UI(uiA); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF32UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF32UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0xFF) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = 0x01000000 + sigA + sigB; + if (! (sigZ & 1) && (expZ < 0xFE)) { + return packToF32UI(signZ, expZ, sigZ>>1); + } + sigZ <<= 6; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + signZ = signF32UI(uiA); + sigA <<= 6; + sigB <<= 6; + if (expDiff < 0) { + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF32UI(signZ, 0xFF, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expB; + sigA += expA ? 0x20000000 : sigA; + sigA = softfloat_shiftRightJam32(sigA, -expDiff); + } else { + if (expA == 0xFF) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiA; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expA; + sigB += expB ? 0x20000000 : sigB; + sigB = softfloat_shiftRightJam32(sigB, expDiff); + } + sigZ = 0x20000000 + sigA + sigB; + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(uiA, uiB, status); +} diff --git a/src/cpu/softfloat3e/s_addMagsF64.c b/src/cpu/softfloat3e/s_addMagsF64.c new file mode 100644 index 000000000..a315860f6 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF64.c @@ -0,0 +1,149 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float64 softfloat_addMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + int16_t expB; + uint64_t sigB; + int16_t expDiff; + uint64_t uiZ; + int16_t expZ; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF64UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF64UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0x7FF) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = UINT64_C(0x0020000000000000) + sigA + sigB; + sigZ <<= 9; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigA <<= 9; + sigB <<= 9; + if (expDiff < 0) { + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF64UI(signZ, 0x7FF, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expB; + if (expA) { + sigA += UINT64_C(0x2000000000000000); + } else { + sigA <<= 1; + } + sigA = softfloat_shiftRightJam64(sigA, -expDiff); + } else { + if (expA == 0x7FF) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiA; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expA; + if (expB) { + sigB += UINT64_C(0x2000000000000000); + } else { + sigB <<= 1; + } + sigB = softfloat_shiftRightJam64(sigB, expDiff); + } + sigZ = UINT64_C(0x2000000000000000) + sigA + sigB; + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(uiA, uiB, status); +} diff --git a/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c new file mode 100644 index 000000000..776c146ef --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; + +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a) +{ + int index; + uint16_t eps, r0; + uint32_t ESqrR0; + uint32_t sigma0; + uint32_t r; + uint32_t sqrSigma0; + + index = (a>>27 & 0xE) + oddExpA; + eps = (uint16_t) (a>>12); + r0 = softfloat_approxRecipSqrt_1k0s[index] - ((softfloat_approxRecipSqrt_1k1s[index] * (uint32_t) eps) >>20); + ESqrR0 = (uint32_t) r0 * r0; + if (! oddExpA) ESqrR0 <<= 1; + sigma0 = ~(uint32_t) (((uint32_t) ESqrR0 * (uint64_t) a)>>23); + r = ((uint32_t) r0<<16) + ((r0 * (uint64_t) sigma0)>>25); + sqrSigma0 = ((uint64_t) sigma0 * sigma0)>>32; + r += ((uint32_t) ((r>>1) + (r>>3) - ((uint32_t) r0<<14)) * (uint64_t) sqrSigma0) >>48; + if (! (r & 0x80000000)) r = 0x80000000; + return r; +} + diff --git a/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c b/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c new file mode 100644 index 000000000..56965c541 --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint16_t softfloat_approxRecipSqrt_1k0s[16] = { + 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29, + 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1 +}; +const uint16_t softfloat_approxRecipSqrt_1k1s[16] = { + 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6, + 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD +}; diff --git a/src/cpu/softfloat3e/s_approxRecip_1Ks.c b/src/cpu/softfloat3e/s_approxRecip_1Ks.c new file mode 100644 index 000000000..aadcd235c --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecip_1Ks.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint16_t softfloat_approxRecip_1k0s[16] = { + 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201, + 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417 +}; +const uint16_t softfloat_approxRecip_1k1s[16] = { + 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA, + 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211 +}; diff --git a/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc b/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc new file mode 100644 index 000000000..7afca6270 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN *aPtr) +{ + struct uint128 uiZ; + + uiZ.v64 = (uint16_t) aPtr->sign<<15 | 0x7FFF; + uiZ.v0 = UINT64_C(0xC000000000000000) | aPtr->v64>>1; + return uiZ; +} + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_extF80UIToCommonNaN(uint16_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNExtF80UI(uiA64, uiA0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA64>>15; + zPtr->v64 = uiA0<<1; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF128UI.cc b/src/cpu/softfloat3e/s_commonNaNToF128UI.cc new file mode 100644 index 000000000..a0bb93dd3 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF128UI.cc @@ -0,0 +1,72 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN *aPtr) +{ + struct uint128 uiZ; + + uiZ = softfloat_shortShiftRight128(aPtr->v64, aPtr->v0, 16); + uiZ.v64 |= (uint64_t) aPtr->sign<<63 | UINT64_C(0x7FFF800000000000); + return uiZ; +} + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN(uint64_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + struct uint128 NaNSig; + + if (softfloat_isSigNaNF128UI(uiA64, uiA0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + NaNSig = softfloat_shortShiftLeft128(uiA64, uiA0, 16); + zPtr->sign = uiA64>>63; + zPtr->v64 = NaNSig.v64; + zPtr->v0 = NaNSig.v0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF16UI.c b/src/cpu/softfloat3e/s_commonNaNToF16UI.c new file mode 100644 index 000000000..20da6a04f --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF16UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_commonNaNToF16UI(const struct commonNaN *aPtr) +{ + return (uint16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f16UIToCommonNaN(uint16_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF16UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>15; + zPtr->v64 = (uint64_t) uiA<<54; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF32UI.c b/src/cpu/softfloat3e/s_commonNaNToF32UI.c new file mode 100644 index 000000000..866ebb8f8 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF32UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_commonNaNToF32UI(const struct commonNaN *aPtr) +{ + return (uint32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN(uint32_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF32UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint64_t) uiA<<41; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF64UI.c b/src/cpu/softfloat3e/s_commonNaNToF64UI.c new file mode 100644 index 000000000..8e73f68f4 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF64UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_commonNaNToF64UI(const struct commonNaN *aPtr) +{ + return (uint64_t) aPtr->sign<<63 | UINT64_C(0x7FF8000000000000) | aPtr->v64>>12; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN(uint64_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF64UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>63; + zPtr->v64 = uiA<<12; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_countLeadingZeros16.c b/src/cpu/softfloat3e/s_countLeadingZeros16.c new file mode 100644 index 000000000..ffbb9c943 --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros16.c @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros16 + +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros16(uint16_t a) +{ + uint8_t count; + + count = 8; + if (0x100 <= a) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros32.c b/src/cpu/softfloat3e/s_countLeadingZeros32.c new file mode 100644 index 000000000..3f594137f --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros32.c @@ -0,0 +1,61 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros32 + +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros32(uint32_t a) +{ + uint8_t count; + + count = 0; + if (a < 0x10000) { + count = 16; + a <<= 16; + } + if (a < 0x1000000) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros64.c b/src/cpu/softfloat3e/s_countLeadingZeros64.c new file mode 100644 index 000000000..c96c4ec8c --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros64.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros64 + +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros64(uint64_t a) +{ + uint8_t count; + uint32_t a32; + + count = 0; + a32 = a>>32; + if (! a32) { + count = 32; + a32 = a; + } + /*------------------------------------------------------------------------ + | From here, result is current count + count leading zeros of `a32'. + *------------------------------------------------------------------------*/ + if (a32 < 0x10000) { + count += 16; + a32 <<= 16; + } + if (a32 < 0x1000000) { + count += 8; + a32 <<= 8; + } + count += softfloat_countLeadingZeros8[a32>>24]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros8.c b/src/cpu/softfloat3e/s_countLeadingZeros8.c new file mode 100644 index 000000000..873ab81ef --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros8.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint_least8_t softfloat_countLeadingZeros8[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + diff --git a/src/cpu/softfloat3e/s_eq128.c b/src/cpu/softfloat3e/s_eq128.c new file mode 100644 index 000000000..45495dd92 --- /dev/null +++ b/src/cpu/softfloat3e/s_eq128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_eq128 + +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 == b64) && (a0 == b0); +} + +#endif diff --git a/src/cpu/softfloat3e/s_le128.c b/src/cpu/softfloat3e/s_le128.c new file mode 100644 index 000000000..d299b5e92 --- /dev/null +++ b/src/cpu/softfloat3e/s_le128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_le128 + +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); +} + +#endif diff --git a/src/cpu/softfloat3e/s_lt128.c b/src/cpu/softfloat3e/s_lt128.c new file mode 100644 index 000000000..225c23356 --- /dev/null +++ b/src/cpu/softfloat3e/s_lt128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_lt128 + +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 < b0)); +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul128By32.cc b/src/cpu/softfloat3e/s_mul128By32.cc new file mode 100644 index 000000000..920ad5733 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul128By32.cc @@ -0,0 +1,54 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_mul128By32 + +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + struct uint128 z; + uint64_t mid; + uint32_t carry; + + z.v0 = a0 * b; + mid = (uint64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint32_t) (z.v0>>32) - (uint32_t) mid); + z.v64 = a64 * b + (uint32_t) ((mid + carry)>>32); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul128To256M.cc b/src/cpu/softfloat3e/s_mul128To256M.cc new file mode 100644 index 000000000..04b25a575 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul128To256M.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#include "primitives.h" +#include "primitiveTypes.h" + +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr) +{ + struct uint128 p0, p64, p128; + uint64_t z64, z128, z192; + + p0 = softfloat_mul64To128(a0, b0); + zPtr[indexWord(4, 0)] = p0.v0; + p64 = softfloat_mul64To128(a64, b0); + z64 = p64.v0 + p0.v64; + z128 = p64.v64 + (z64 < p64.v0); + p128 = softfloat_mul64To128(a64, b64); + z128 += p128.v0; + z192 = p128.v64 + (z128 < p128.v0); + p64 = softfloat_mul64To128(a0, b64); + z64 += p64.v0; + zPtr[indexWord(4, 1)] = z64; + p64.v64 += (z64 < p64.v0); + z128 += p64.v64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z192 + (z128 < p64.v64); +} + diff --git a/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc b/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc new file mode 100644 index 000000000..90938ac79 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc @@ -0,0 +1,52 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_mul64ByShifted32To128 + +struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + uint64_t mid; + struct uint128 z; + + mid = (uint64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul64To128.cc b/src/cpu/softfloat3e/s_mul64To128.cc new file mode 100644 index 000000000..d1ab9296a --- /dev/null +++ b/src/cpu/softfloat3e/s_mul64To128.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" +#include "primitives.h" + +#ifndef softfloat_mul64To128 + +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) +{ + uint32_t a32, a0, b32, b0; + struct uint128 z; + uint64_t mid1, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z.v0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid = mid1 + (uint64_t) a0 * b32; + z.v64 = (uint64_t) a32 * b32; + z.v64 += (uint64_t) (mid < mid1)<<32 | mid>>32; + mid <<= 32; + z.v0 += mid; + z.v64 += (z.v0 < mid); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc b/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc new file mode 100644 index 000000000..753f76184 --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +extFloat80_t softfloat_normRoundPackToExtF80(bool sign, int32_t exp, + uint64_t sig, + uint64_t sigExtra, + uint8_t roundingPrecision, + struct softfloat_status_t *status) +{ + int8_t shiftDist; + struct uint128 sig128; + + if (! sig) { + exp -= 64; + sig = sigExtra; + sigExtra = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig); + exp -= shiftDist; + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig, sigExtra, shiftDist); + sig = sig128.v64; + sigExtra = sig128.v0; + } + return softfloat_roundPackToExtF80(sign, exp, sig, sigExtra, roundingPrecision, status); +} diff --git a/src/cpu/softfloat3e/s_normRoundPackToF128.cc b/src/cpu/softfloat3e/s_normRoundPackToF128.cc new file mode 100644 index 000000000..14db1ce9b --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToF128.cc @@ -0,0 +1,75 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +float128_t softfloat_normRoundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, struct softfloat_status_t *status) +{ + int8_t shiftDist; + struct uint128 sig128; + uint64_t sigExtra; + struct uint128_extra sig128Extra; + float128_t z; + + if (! sig64) { + exp -= 64; + sig64 = sig0; + sig0 = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig64) - 15; + exp -= shiftDist; + if (0 <= shiftDist) { + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + if ((uint32_t) exp < 0x7FFD) { + z.v64 = packToF128UI64(sign, sig64 | sig0 ? exp : 0, sig64); + z.v0 = sig0; + return z; + } + sigExtra = 0; + } else { + sig128Extra = softfloat_shortShiftRightJam128Extra(sig64, sig0, 0, -shiftDist); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + } + return softfloat_roundPackToF128(sign, exp, sig64, sig0, sigExtra, status); +} diff --git a/src/cpu/softfloat3e/s_normRoundPackToF16.c b/src/cpu/softfloat3e/s_normRoundPackToF16.c new file mode 100644 index 000000000..36ae237fa --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToF16.c @@ -0,0 +1,49 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +float16 softfloat_normRoundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros16(sig) - 1; + exp -= shiftDist; + if ((4 <= shiftDist) && ((unsigned int) exp < 0x1D)) { + return packToF16UI(sign, sig ? exp : 0, sig<<(shiftDist - 4)); + } else { + return softfloat_roundPackToF16(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +float32 softfloat_normRoundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros32(sig) - 1; + exp -= shiftDist; + if ((7 <= shiftDist) && ((unsigned int) exp < 0xFD)) { + return packToF32UI(sign, sig ? exp : 0, sig<<(shiftDist - 7)); + } else { + return softfloat_roundPackToF32(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +float64 softfloat_normRoundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros64(sig) - 1; + exp -= shiftDist; + if ((10 <= shiftDist) && ((unsigned int) exp < 0x7FD)) { + return packToF64UI(sign, sig ? exp : 0, sig<<(shiftDist - 10)); + } else { + return softfloat_roundPackToF64(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t sig) +{ + int8_t shiftDist; + struct exp32_sig64 z; + + shiftDist = softfloat_countLeadingZeros64(sig); + z.exp = -shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t sig64, uint64_t sig0) +{ + int8_t shiftDist; + struct exp32_sig128 z; + + if (! sig64) { + shiftDist = softfloat_countLeadingZeros64(sig0) - 15; + z.exp = -63 - shiftDist; + if (shiftDist < 0) { + z.sig.v64 = sig0>>-shiftDist; + z.sig.v0 = sig0<<(shiftDist & 63); + } else { + z.sig.v64 = sig0< +#include "internals.h" +#include "primitives.h" + +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t sig) +{ + int8_t shiftDist; + struct exp8_sig16 z; + + shiftDist = softfloat_countLeadingZeros16(sig) - 5; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t sig) +{ + int8_t shiftDist; + struct exp16_sig32 z; + + shiftDist = softfloat_countLeadingZeros32(sig) - 8; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t sig) +{ + int8_t shiftDist; + struct exp16_sig64 z; + + shiftDist = softfloat_countLeadingZeros64(sig) - 11; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "softfloat.h" + +extFloat80_t packToExtF80_twoargs(uint16_t signExp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = signExp; + z.signif = sig; + return z; +} + +extFloat80_t packToExtF80(bool sign, uint16_t exp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = packToExtF80UI64(sign, exp); + z.signif = sig; + return z; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc b/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc new file mode 100644 index 000000000..77d699bb0 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc @@ -0,0 +1,96 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +extFloat80_t +softfloat_propagateNaNExtF80UI(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, struct softfloat_status_t *status) +{ + bool isSigNaNA, isSigNaNB; + uint64_t uiNonsigA0, uiNonsigB0; + uint16_t uiMagA64, uiMagB64; + extFloat80_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNExtF80UI(uiA64, uiA0); + isSigNaNB = softfloat_isSigNaNExtF80UI(uiB64, uiB0); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA0 = uiA0 | UINT64_C(0xC000000000000000); + uiNonsigB0 = uiB0 | UINT64_C(0xC000000000000000); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (isSigNaNA | isSigNaNB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) { + if (isSigNaNB) goto returnLargerMag; + if (isNaNExtF80UI(uiB64, uiB0)) goto returnB; + goto returnA; + } else { + if (isNaNExtF80UI(uiA64, uiA0)) goto returnA; + goto returnB; + } + } + returnLargerMag: + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if (uiMagA64 < uiMagB64) goto returnB; + if (uiMagB64 < uiMagA64) goto returnA; + if (uiA0 < uiB0) goto returnB; + if (uiB0 < uiA0) goto returnA; + if (uiA64 < uiB64) goto returnA; + returnB: + z.signExp = uiB64; + z.signif = uiNonsigB0; + return z; + returnA: + z.signExp = uiA64; + z.signif = uiNonsigA0; + return z; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF128UI.cc b/src/cpu/softfloat3e/s_propagateNaNF128UI.cc new file mode 100644 index 000000000..83a7c2413 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF128UI.cc @@ -0,0 +1,78 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status +) +{ + bool isSigNaNA; + struct uint128 uiZ; + + isSigNaNA = softfloat_isSigNaNF128UI(uiA64, uiA0); + if (isSigNaNA || softfloat_isSigNaNF128UI(uiB64, uiB0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) goto returnNonsigA; + } + if (isNaNF128UI(uiA64, uiA0)) { + returnNonsigA: + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + } else { + uiZ.v64 = uiB64; + uiZ.v0 = uiB0; + } + uiZ.v64 |= UINT64_C(0x0000800000000000); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF16UI.c b/src/cpu/softfloat3e/s_propagateNaNF16UI.c new file mode 100644 index 000000000..0a92c57f0 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF16UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_propagateNaNF16UI(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF16UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF16UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | 0x0200; + } + return (isNaNF16UI(uiA) ? uiA : uiB) | 0x0200; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF32UI.c b/src/cpu/softfloat3e/s_propagateNaNF32UI.c new file mode 100644 index 000000000..d5db3d24e --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF32UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_propagateNaNF32UI(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF32UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF32UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | 0x00400000; + } + return (isNaNF32UI(uiA) ? uiA : uiB) | 0x00400000; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF64UI.c b/src/cpu/softfloat3e/s_propagateNaNF64UI.c new file mode 100644 index 000000000..3bb2ead86 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF64UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_propagateNaNF64UI(uint64_t uiA, uint64_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF64UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF64UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | UINT64_C(0x0008000000000000); + } + return (isNaNF64UI(uiA) ? uiA : uiB) | UINT64_C(0x0008000000000000); +} diff --git a/src/cpu/softfloat3e/s_roundPackToExtF80.cc b/src/cpu/softfloat3e/s_roundPackToExtF80.cc new file mode 100644 index 000000000..ec63283e1 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToExtF80.cc @@ -0,0 +1,224 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t + softfloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint64_t roundIncrement, roundMask, roundBits; + bool isTiny, doIncrement; + struct uint64_extra sig64Extra; + uint64_t sigExact; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + if (roundingPrecision == 80) goto precision80; + if (roundingPrecision == 64) { + roundIncrement = UINT64_C(0x0000000000000400); + roundMask = UINT64_C(0x00000000000007FF); + } else if (roundingPrecision == 32) { + roundIncrement = UINT64_C(0x0000008000000000); + roundMask = UINT64_C(0x000000FFFFFFFFFF); + } else { + goto precision80; + } + sig |= (sigExtra != 0); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? roundMask : 0; + } + roundBits = sig & roundMask; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) (exp - 1)) { + if (exp <= 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; + } + else { + sig = softfloat_shiftRightJam64(sig, 1 - exp); + roundBits = sig & roundMask; + sigExact = sig; + sig += roundIncrement; + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + return packToExtF80(sign, exp, sig); + } + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { + goto overflow; + } + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigExact = sig; + sig = (uint64_t) (sig + roundIncrement); + if (sig < roundIncrement) { + ++exp; + sig = UINT64_C(0x8000000000000000); + sigExact >>= 1; // must scale also, or else later tests will fail + } + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + precision80: + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) (exp - 1)) { + if (exp <= 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < 0) || ! doIncrement || (sig < UINT64_C(0xFFFFFFFFFFFFFFFF)); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; + } + else { + sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); + exp = 0; + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + if (doIncrement) { + sigExact = sig; + ++sig; + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); + } + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + roundMask = 0; + overflow: + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + if (roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + exp = 0x7FFF; + sig = UINT64_C(0x8000000000000000); + softfloat_setRoundingUp(status); + } else { + exp = 0x7FFE; + sig = ~roundMask; + } + return packToExtF80(sign, exp, sig); + } + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + if (doIncrement) { + sigExact = sig; + ++sig; + if (! sig) { + ++exp; + sig = UINT64_C(0x8000000000000000); + sigExact >>= 1; // must scale also, or else later tests will fail + } else { + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + } + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + else { + if (! sig) exp = 0; + } + return packToExtF80(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF128.cc b/src/cpu/softfloat3e/s_roundPackToF128.cc new file mode 100644 index 000000000..46741e5e9 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF128.cc @@ -0,0 +1,102 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +// trimmed for Bochs to support only 'softfloat_round_nearest_even' rounding mode +float128_t + softfloat_roundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, uint64_t sigExtra, struct softfloat_status_t *status) +{ + bool doIncrement, isTiny; + struct uint128_extra sig128Extra; + struct uint128 sig128; + float128_t z; + + sigExtra = 0; // artificially reduce precision to match hardware x86 which uses only 67-bit + sig0 &= UINT64_C(0xFFFFFFFF00000000); // do 80 bits for now + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || ! doIncrement || + softfloat_lt128(sig64, sig0, UINT64_C(0x0001FFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)); + sig128Extra = softfloat_shiftRightJam128Extra(sig64, sig0, sigExtra, -exp); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + exp = 0; + if (isTiny && sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + } else if ((0x7FFD < exp) || ((exp == 0x7FFD) + && softfloat_eq128(sig64, sig0, UINT64_C(0x0001FFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)) + && doIncrement) + ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + z.v64 = packToF128UI64(sign, 0x7FFF, 0); + z.v0 = 0; + return z; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + if (doIncrement) { + sig128 = softfloat_add128(sig64, sig0, 0, 1); + sig64 = sig128.v64; + sig0 = sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF))); + } else { + if (! (sig64 | sig0)) exp = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z.v64 = packToF128UI64(sign, exp, sig64); + z.v0 = sig0; + return z; +} diff --git a/src/cpu/softfloat3e/s_roundPackToF16.c b/src/cpu/softfloat3e/s_roundPackToF16.c new file mode 100644 index 000000000..c262d00b1 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF16.c @@ -0,0 +1,104 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 softfloat_roundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint8_t roundIncrement, roundBits; + bool isTiny; + uint16_t uiZ; + uint16_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x8; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0xF : 0; + } + roundBits = sig & 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x1D <= (unsigned int) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < 0x8000); + sig = softfloat_shiftRightJam32(sig, -exp); + exp = 0; + roundBits = sig & 0xF; + if (isTiny) { + if (! softfloat_isMaskedException(status, softfloat_flag_underflow) || roundBits) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF16UI(sign, 0, 0); + } + } + } else if ((0x1D < exp) || (0x8000 <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF16UI(sign, 0x1F, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>4; + sig &= ~(uint16_t) (! (roundBits ^ 8) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 4) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF16UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF32.c b/src/cpu/softfloat3e/s_roundPackToF32.c new file mode 100644 index 000000000..03a4e36a0 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF32.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 softfloat_roundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint8_t roundIncrement, roundBits; + bool isTiny; + uint32_t uiZ; + uint32_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x7F : 0; + } + roundBits = sig & 0x7F; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0xFD <= (unsigned int) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < 0x80000000); + if (isTiny && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 192; + } + else { + sig = softfloat_shiftRightJam32(sig, -exp); + exp = 0; + roundBits = sig & 0x7F; + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(sign, 0, 0); + } + if (roundBits) softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } else if ((0xFD < exp) || (0x80000000 <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF32UI(sign, 0xFF, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>7; + sig &= ~(uint32_t) (! (roundBits ^ 0x40) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 7) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF32UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF64.c b/src/cpu/softfloat3e/s_roundPackToF64.c new file mode 100644 index 000000000..713fd6940 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF64.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 softfloat_roundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint16_t roundIncrement, roundBits; + bool isTiny; + uint64_t uiZ; + uint64_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x200; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x3FF : 0; + } + roundBits = sig & 0x3FF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FD <= (uint16_t) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < UINT64_C(0x8000000000000000)); + if (isTiny && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 1536; + } + else { + sig = softfloat_shiftRightJam64(sig, -exp); + exp = 0; + roundBits = sig & 0x3FF; + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(sign, 0, 0); + } + if (roundBits) softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } else if ((0x7FD < exp) || (UINT64_C(0x8000000000000000) <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF64UI(sign, 0x7FF, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>10; + sig &= ~(uint64_t) (! (roundBits ^ 0x200) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 10) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundToI32.c b/src/cpu/softfloat3e/s_roundToI32.c new file mode 100644 index 000000000..a7a0b13d7 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToI32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t softfloat_roundToI32(bool sign, uint64_t sig, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t roundIncrement, roundBits; + uint32_t sig32; + union { uint32_t ui; int32_t i; } uZ; + int32_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundIncrement = 0x800; + if ((roundingMode != softfloat_round_near_maxMag) && (roundingMode != softfloat_round_near_even)) { + roundIncrement = 0; + if (sign ? (roundingMode == softfloat_round_min) : (roundingMode == softfloat_round_max)) { + roundIncrement = 0xFFF; + } + } + roundBits = sig & 0xFFF; + sig += roundIncrement; + if (sig & UINT64_C(0xFFFFF00000000000)) goto invalid; + sig32 = sig>>12; + if ((roundBits == 0x800) && (roundingMode == softfloat_round_near_even)) { + sig32 &= ~(uint32_t) 1; + } + uZ.ui = sign ? -sig32 : sig32; + z = uZ.i; + if (z && ((z < 0) ^ sign)) goto invalid; + if (roundBits) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (((uint64_t)sig32 << 12) > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? i32_fromNegOverflow : i32_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToI64.c b/src/cpu/softfloat3e/s_roundToI64.c new file mode 100644 index 000000000..72d421889 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToI64.c @@ -0,0 +1,77 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t + softfloat_roundToI64(bool sign, uint64_t sig, uint64_t sigExtra, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + union { uint64_t ui; int64_t i; } uZ; + int64_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even)) { + if (UINT64_C(0x8000000000000000) <= sigExtra) goto increment; + } else { + if (sigExtra + && (sign ? (roundingMode == softfloat_round_min) : (roundingMode == softfloat_round_max))) { + increment: + ++sig; + if (!sig) goto invalid; + if ((sigExtra == UINT64_C(0x8000000000000000)) && (roundingMode == softfloat_round_near_even)) { + sig &= ~(uint64_t) 1; + } + } + } + uZ.ui = sign ? -sig : sig; + z = uZ.i; + if (z && ((z < 0) ^ sign)) goto invalid; + if (sigExtra) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? i64_fromNegOverflow : i64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToUI32.c b/src/cpu/softfloat3e/s_roundToUI32.c new file mode 100644 index 000000000..d2956b0ac --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToUI32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t + softfloat_roundToUI32(bool sign, uint64_t sig, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t roundIncrement, roundBits; + uint32_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundIncrement = 0x800; + if ((roundingMode != softfloat_round_near_maxMag) && (roundingMode != softfloat_round_near_even)) { + roundIncrement = 0; + if (sign) { + if (!sig) return 0; + if (roundingMode == softfloat_round_min) goto invalid; + } else { + if (roundingMode == softfloat_round_max) roundIncrement = 0xFFF; + } + } + roundBits = sig & 0xFFF; + sig += roundIncrement; + if (sig & UINT64_C(0xFFFFF00000000000)) goto invalid; + z = sig>>12; + if ((roundBits == 0x800) && (roundingMode == softfloat_round_near_even)) { + z &= ~(uint32_t) 1; + } + if (sign && z) goto invalid; + if (roundBits) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (((uint64_t)z << 12) > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToUI64.c b/src/cpu/softfloat3e/s_roundToUI64.c new file mode 100644 index 000000000..75120a7fe --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToUI64.c @@ -0,0 +1,76 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t + softfloat_roundToUI64(bool sign, uint64_t sig, uint64_t sigExtra, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t absSigExact = sig; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even)) { + if (UINT64_C(0x8000000000000000) <= sigExtra) goto increment; + } else { + if (sign) { + if (!(sig | sigExtra)) return 0; + if (roundingMode == softfloat_round_min) goto invalid; + } else { + if ((roundingMode == softfloat_round_max) && sigExtra) { + increment: + ++sig; + if (!sig) goto invalid; + if ((sigExtra == UINT64_C(0x8000000000000000)) && (roundingMode == softfloat_round_near_even)) { + sig &= ~(uint64_t) 1; + } + } + } + } + if (sign && sig) goto invalid; + if (sigExtra) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > absSigExact) + softfloat_setRoundingUp(status); + } + return sig; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_shiftRightJam128.cc b/src/cpu/softfloat3e/s_shiftRightJam128.cc new file mode 100644 index 000000000..11fb26abf --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam128.cc @@ -0,0 +1,65 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam128 + +struct uint128 + softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128 z; + + if (dist < 64) { + u8NegDist = -dist; + z.v64 = a64>>dist; + z.v0 = + a64<<(u8NegDist & 63) | a0>>dist + | ((uint64_t) (a0<<(u8NegDist & 63)) != 0); + } else { + z.v64 = 0; + z.v0 = + (dist < 127) + ? a64>>(dist & 63) + | (((a64 & (((uint64_t) 1<<(dist & 63)) - 1)) | a0) + != 0) + : ((a64 | a0) != 0); + } + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc b/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc new file mode 100644 index 000000000..7f4b3fa82 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam128Extra + +struct uint128_extra + softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128_extra z; + + u8NegDist = -dist; + if (dist < 64) { + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist; + z.extra = a0<<(u8NegDist & 63); + } else { + z.v.v64 = 0; + if (dist == 64) { + z.v.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if (dist < 128) { + z.v.v0 = a64>>(dist & 63); + z.extra = a64<<(u8NegDist & 63); + } else { + z.v.v0 = 0; + z.extra = (dist == 128) ? a64 : (a64 != 0); + } + } + } + z.extra |= (extra != 0); + return z; + +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam256M.c b/src/cpu/softfloat3e/s_shiftRightJam256M.c new file mode 100644 index 000000000..654e01234 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam256M.c @@ -0,0 +1,113 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam256M + +static void softfloat_shortShiftRightJamM(uint8_t size_words, const uint64_t *aPtr, uint8_t dist, uint64_t *zPtr) +{ + uint8_t uNegDist; + unsigned int index, lastIndex; + uint64_t partWordZ, wordA; + + uNegDist = -dist; + index = indexWordLo(size_words); + lastIndex = indexWordHi(size_words); + wordA = aPtr[index]; + partWordZ = wordA>>dist; + if (partWordZ<>dist; + } + zPtr[index] = partWordZ; + +} + +void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *zPtr) +{ + uint64_t wordJam; + uint32_t wordDist; + uint64_t *ptr; + uint8_t i, innerDist; + + wordJam = 0; + wordDist = dist>>6; + if (wordDist) { + if (4 < wordDist) wordDist = 4; + ptr = (uint64_t *) (aPtr + indexMultiwordLo(4, wordDist)); + i = wordDist; + do { + wordJam = *ptr++; + if (wordJam) break; + --i; + } while (i); + ptr = zPtr; + } + if (wordDist < 4) { + aPtr += indexMultiwordHiBut(4, wordDist); + innerDist = dist & 63; + if (innerDist) { + softfloat_shortShiftRightJamM( + 4 - wordDist, + aPtr, + innerDist, + zPtr + indexMultiwordLoBut(4, wordDist) + ); + if (! wordDist) goto wordJam; + } else { + aPtr += indexWordLo(4 - wordDist); + ptr = zPtr + indexWordLo(4); + for (i = 4 - wordDist; i; --i) { + *ptr = *aPtr; + aPtr += wordIncr; + ptr += wordIncr; + } + } + ptr = zPtr + indexMultiwordHi(4, wordDist); + } + do { + *ptr++ = 0; + --wordDist; + } while (wordDist); + wordJam: + if (wordJam) zPtr[indexWordLo(4)] |= 1; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam32.c b/src/cpu/softfloat3e/s_shiftRightJam32.c new file mode 100644 index 000000000..638aa0294 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam32.c @@ -0,0 +1,45 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shiftRightJam32 + +uint32_t softfloat_shiftRightJam32(uint32_t a, uint16_t dist) +{ + return (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam64.c b/src/cpu/softfloat3e/s_shiftRightJam64.c new file mode 100644 index 000000000..03cf5e692 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam64.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shiftRightJam64 + +uint64_t softfloat_shiftRightJam64(uint64_t a, uint32_t dist) +{ + return (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +} + +#endif + diff --git a/src/cpu/softfloat3e/s_shiftRightJam64Extra.c b/src/cpu/softfloat3e/s_shiftRightJam64Extra.c new file mode 100644 index 000000000..a80bafb35 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam64Extra.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam64Extra + +struct uint64_extra + softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint32_t dist) +{ + struct uint64_extra z; + + if (dist < 64) { + z.v = a>>dist; + z.extra = a<<(-dist & 63); + } else { + z.v = 0; + z.extra = (dist == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shortShiftLeft128.cc b/src/cpu/softfloat3e/s_shortShiftLeft128.cc new file mode 100644 index 000000000..dc24172cd --- /dev/null +++ b/src/cpu/softfloat3e/s_shortShiftLeft128.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftLeft128 + +struct uint128 + softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + + z.v64 = a64<>(-dist & 63); + z.v0 = a0< +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftRight128 + +struct uint128 + softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + + z.v64 = a64>>dist; + z.v0 = a64<<(-dist & 63) | a0>>dist; + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shortShiftRightJam64.c b/src/cpu/softfloat3e/s_shortShiftRightJam64.c new file mode 100644 index 000000000..cfee2a679 --- /dev/null +++ b/src/cpu/softfloat3e/s_shortShiftRightJam64.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shortShiftRightJam64 + +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint8_t dist) +{ + return a>>dist | ((a & (((uint64_t) 1< +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftRightJam64Extra + +struct uint64_extra + softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint8_t dist) +{ + struct uint64_extra z; + + z.v = a>>dist; + z.extra = a<<(-dist & 63) | (extra != 0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_sub128.cc b/src/cpu/softfloat3e/s_sub128.cc new file mode 100644 index 000000000..d5d5f941b --- /dev/null +++ b/src/cpu/softfloat3e/s_sub128.cc @@ -0,0 +1,50 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_sub128 + +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + + z.v0 = a0 - b0; + z.v64 = a64 - b64 - (a0 < b0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_sub256M.c b/src/cpu/softfloat3e/s_sub256M.c new file mode 100644 index 000000000..8b2f6e2fd --- /dev/null +++ b/src/cpu/softfloat3e/s_sub256M.c @@ -0,0 +1,59 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_sub256M + +void softfloat_sub256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr) +{ + unsigned int index; + uint8_t borrow; + uint64_t wordA, wordB; + + index = indexWordLo(4); + borrow = 0; + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + zPtr[index] = wordA - wordB - borrow; + if (index == indexWordHi(4)) break; + borrow = borrow ? (wordA <= wordB) : (wordA < wordB); + index += wordIncr; + } +} + +#endif diff --git a/src/cpu/softfloat3e/s_subMagsExtF80.cc b/src/cpu/softfloat3e/s_subMagsExtF80.cc new file mode 100644 index 000000000..3a75cd768 --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsExtF80.cc @@ -0,0 +1,154 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + uint64_t sigA; + int32_t expB; + uint64_t sigB; + int32_t expDiff; + int32_t expZ; + uint64_t sigExtra; + struct uint128 sig128; + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64(uiA64); + sigA = uiA0; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA<<1)) goto propagateNaN; + if (expB == 0x7FFF) { + if ((sigB<<1)) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + if (sigB && ! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80_twoargs(uiA64, uiA0); + } + if (expB == 0x7FFF) { + if ((sigB<<1)) goto propagateNaN; + if (sigA && ! expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ ^ 1, 0x7FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (! expB) { + if (sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + return softfloat_roundPackToExtF80(signZ ^ 1, expB, sigB, 0, softfloat_extF80_roundingPrecision(status), status); + } + return packToExtF80((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + return softfloat_roundPackToExtF80(signZ ^ 1, expB, sigB, 0, softfloat_extF80_roundingPrecision(status), status); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) + return softfloat_roundPackToExtF80(signZ, expA, sigA, 0, softfloat_extF80_roundingPrecision(status), status); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (0 < expDiff) goto expABigger; + if (expDiff < 0) goto expBBigger; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA; + sigExtra = 0; + if (sigB < sigA) goto aBigger; + if (sigA < sigB) goto bBigger; + return packToExtF80((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expBBigger: + sig128 = softfloat_shiftRightJam128(sigA, 0, -expDiff); + sigA = sig128.v64; + sigExtra = sig128.v0; + expZ = expB; + bBigger: + signZ = ! signZ; + sig128 = softfloat_sub128(sigB, 0, sigA, sigExtra); + goto normRoundPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expABigger: + sig128 = softfloat_shiftRightJam128(sigB, 0, expDiff); + sigB = sig128.v64; + sigExtra = sig128.v0; + expZ = expA; + aBigger: + sig128 = softfloat_sub128(sigA, 0, sigB, sigExtra); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + normRoundPack: + return + softfloat_normRoundPackToExtF80( + signZ, expZ, sig128.v64, sig128.v0, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); +} diff --git a/src/cpu/softfloat3e/s_subMagsF128.cc b/src/cpu/softfloat3e/s_subMagsF128.cc new file mode 100644 index 000000000..f39e6c02d --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF128.cc @@ -0,0 +1,131 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + softfloat_subMagsF128( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + bool signZ, + struct softfloat_status_t *status +) +{ + int32_t expA; + struct uint128 sigA; + int32_t expB; + struct uint128 sigB, sigZ; + int32_t expDiff, expZ; + struct uint128 uiZ; + + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 4); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 4); + expDiff = expA - expB; + if (0 < expDiff) goto expABigger; + if (expDiff < 0) goto expBBigger; + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + expZ = expA; + if (! expZ) expZ = 1; + if (sigB.v64 < sigA.v64) goto aBigger; + if (sigA.v64 < sigB.v64) goto bBigger; + if (sigB.v0 < sigA.v0) goto aBigger; + if (sigA.v0 < sigB.v0) goto bBigger; + uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + uiZ.v0 = 0; + return uiZ; + expBBigger: + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = packToF128UI64(signZ ^ 1, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + } + if (expA) { + sigA.v64 |= UINT64_C(0x0010000000000000); + } else { + ++expDiff; + if (! expDiff) goto newlyAlignedBBigger; + } + sigA = softfloat_shiftRightJam128(sigA.v64, sigA.v0, -expDiff); + newlyAlignedBBigger: + expZ = expB; + sigB.v64 |= UINT64_C(0x0010000000000000); + bBigger: + signZ = ! signZ; + sigZ = softfloat_sub128(sigB.v64, sigB.v0, sigA.v64, sigA.v0); + goto normRoundPack; + expABigger: + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + if (expB) { + sigB.v64 |= UINT64_C(0x0010000000000000); + } else { + --expDiff; + if (! expDiff) goto newlyAlignedABigger; + } + sigB = softfloat_shiftRightJam128(sigB.v64, sigB.v0, expDiff); + newlyAlignedABigger: + expZ = expA; + sigA.v64 |= UINT64_C(0x0010000000000000); + aBigger: + sigZ = softfloat_sub128(sigA.v64, sigA.v0, sigB.v64, sigB.v0); + normRoundPack: + return softfloat_normRoundPackToF128(signZ, expZ - 5, sigZ.v64, sigZ.v0, status); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_subMagsF16.c b/src/cpu/softfloat3e/s_subMagsF16.c new file mode 100644 index 000000000..6241d0ee5 --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF16.c @@ -0,0 +1,190 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 softfloat_subMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + int8_t expB; + uint16_t sigB; + int8_t expDiff; + uint16_t uiZ; + int16_t sigDiff; + bool signZ; + int8_t shiftDist, expZ; + uint16_t sigZ, sigX, sigY; + uint32_t sig32Z; + int8_t roundingMode; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF16UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + signZ = signF16UI(uiA); + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros16(sigDiff) - 5; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + sigZ = sigDiff<>16; + if (sig32Z & 0xFFFF) { + sigZ |= 1; + } else { + if (! (sigZ & 0xF) && ((unsigned int) expZ < 0x1E)) { + sigZ >>= 4; + goto pack; + } + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(uiA, uiB, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + subEpsilon: + roundingMode = softfloat_getRoundingMode(status); + if (roundingMode != softfloat_round_near_even) { + if ((roundingMode == softfloat_round_minMag) + || (roundingMode == (signF16UI(uiZ) ? softfloat_round_max : softfloat_round_min))) { + --uiZ; + } + } + softfloat_raiseFlags(status, softfloat_flag_inexact); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + pack: + return packToF16UI(signZ, expZ, sigZ); +} diff --git a/src/cpu/softfloat3e/s_subMagsF32.c b/src/cpu/softfloat3e/s_subMagsF32.c new file mode 100644 index 000000000..115e2906c --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF32.c @@ -0,0 +1,151 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 softfloat_subMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + int16_t expB; + uint32_t sigB; + int16_t expDiff; + int32_t sigDiff; + bool signZ; + int8_t shiftDist; + int16_t expZ; + uint32_t sigX, sigY; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF32UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + signZ = signF32UI(uiA); + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros32(sigDiff) - 8; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + if (!expZ && sigDiff) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + return packToF32UI(signZ, expZ, sigDiff< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 softfloat_subMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + int16_t expB; + uint64_t sigB; + int16_t expDiff; + int64_t sigDiff; + int8_t shiftDist; + int16_t expZ; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros64(sigDiff) - 11; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + if (!expZ && sigDiff) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + return packToF64UI(signZ, expZ, sigDiff< + +#include "primitives.h" +#include "primitiveTypes.h" + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static __inline void mul128By64To192(uint64_t a64, uint64_t a0, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t zPtr[4]; + + softfloat_mul128To256M(a64, a0, 0, b, (uint64_t*) zPtr); + + assert(zPtr[indexWord(4, 3)] == 0); + + *z0Ptr = zPtr[indexWord(4, 2)]; + *z1Ptr = zPtr[indexWord(4, 1)]; + *z2Ptr = zPtr[indexWord(4, 0)]; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static __inline void shortShift128Left(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1<>((-count) & 63)); +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static __inline void shortShift128Right(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + uint64_t z0 = a0, z1 = a1; + int negCount = (-count) & 63; + + if (count != 0) { + z1 = (a0<>count); + z0 = a0>>count; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +#ifdef USE_estimateDiv128To64 +static uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) +{ + uint128 term, rem; + uint64_t b0, b1; + uint64_t z; + if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); + b0 = b>>32; + z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; + term = softfloat_mul64To128(b, z); + rem = softfloat_sub128(a0, a1, term.v64, term.v0); + while (((int64_t) rem.v64) < 0) { + z -= UINT64_C(0x100000000); + b1 = b<<32; + rem = softfloat_add128(rem.v64, rem.v0, b0, b1); + } + rem.v64 = (rem.v64<<32) | (rem.v0>>32); + z |= (b0<<32 <= rem.v64) ? 0xFFFFFFFF : rem.v64 / b0; + return z; +} +#endif + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static __inline void add192(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t b0, uint64_t b1, uint64_t b2, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t z0, z1, z2; + unsigned carry0, carry1; + + z2 = a2 + b2; + carry1 = (z2 < a2); + z1 = a1 + b1; + carry0 = (z1 < a1); + z0 = a0 + b0; + z1 += carry1; + z0 += (z1 < carry1); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static __inline void sub128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +#endif diff --git a/src/cpu/softfloat3e/softfloat-specialize.h b/src/cpu/softfloat3e/softfloat-specialize.h new file mode 100644 index 000000000..bc7dcd263 --- /dev/null +++ b/src/cpu/softfloat3e/softfloat-specialize.h @@ -0,0 +1,224 @@ +/*============================================================================ +This C source fragment 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. +=============================================================================*/ + +#ifndef _SOFTFLOAT_SPECIALIZE_H_ +#define _SOFTFLOAT_SPECIALIZE_H_ + +#include "config.h" +#include "softfloat.h" +#include "softfloat_types.h" + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +const int16_t int16_indefinite = (int16_t) 0x8000; +const int32_t int32_indefinite = (int32_t) 0x80000000; +const int64_t int64_indefinite = (int64_t) BX_CONST64(0x8000000000000000); + +const uint16_t uint16_indefinite = 0xffff; +const uint32_t uint32_indefinite = 0xffffffff; +const uint64_t uint64_indefinite = BX_CONST64(0xffffffffffffffff); + +/*---------------------------------------------------------------------------- +| Commonly used half-precision floating point constants +*----------------------------------------------------------------------------*/ +const float16 float16_negative_inf = 0xfc00; +const float16 float16_positive_inf = 0x7c00; +const float16 float16_negative_zero = 0x8000; +const float16 float16_positive_zero = 0x0000; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated half-precision NaN. +*----------------------------------------------------------------------------*/ +const float16 float16_default_nan = 0xFE00; + +#define FLOAT16_EXP_BIAS 0xF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float16 packFloat16(int zSign, int zExp, uint16_t zSig) +{ + return (((uint16_t) zSign)<<15) + (((uint16_t) zExp)<<10) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float32 float32_negative_inf = 0xff800000; +const float32 float32_positive_inf = 0x7f800000; +const float32 float32_negative_zero = 0x80000000; +const float32 float32_positive_zero = 0x00000000; +const float32 float32_negative_one = 0xbf800000; +const float32 float32_positive_one = 0x3f800000; +const float32 float32_max_float = 0x7f7fffff; +const float32 float32_min_float = 0xff7fffff; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +const float32 float32_default_nan = 0xffc00000; + +#define FLOAT32_EXP_BIAS 0x7F + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float32 packFloat32(int zSign, int16_t zExp, uint32_t zSig) +{ + return (((uint32_t) zSign)<<31) + (((uint32_t) zExp)<<23) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000); +const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000); +const float64 float64_negative_zero = BX_CONST64(0x8000000000000000); +const float64 float64_positive_zero = BX_CONST64(0x0000000000000000); +const float64 float64_negative_one = BX_CONST64(0xbff0000000000000); +const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000); +const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff); +const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); + +#define FLOAT64_EXP_BIAS 0x3FF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| double-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float64 packFloat64(int zSign, int16_t zExp, uint64_t zSig) +{ + return (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<52) + zSig; +} + +/*----------------------------------------------------------------------------- +| Commonly used extended double-precision floating-point constants. +*----------------------------------------------------------------------------*/ +extern const floatx80 Const_Z; +extern const floatx80 Const_1; +extern const floatx80 Const_L2T; +extern const floatx80 Const_L2E; +extern const floatx80 Const_PI; +extern const floatx80 Const_LG2; +extern const floatx80 Const_LN2; +extern const floatx80 Const_INF; +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_exp 0xFFFF +#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) + +#define FLOATX80_EXP_BIAS 0x3FFF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an +| extended double-precision floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +static __inline floatx80 packFloatx80(int zSign, int32_t zExp, uint64_t zSig) +{ + floatx80 z; + z.signif = zSig; + z.signExp = (zSign << 15) + zExp; + return z; +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', the exponent `zExp', and the significand formed +| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision +| floating-point value, returning the result. After being shifted into the +| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply +| added together to form the most significant 32 bits of the result. This +| means that any integer portion of `zSig0' will be added into the exponent. +| Since a properly normalized significand will have an integer portion equal +| to 1, the `zExp' input should be 1 less than the desired result exponent +| whenever `zSig0' and `zSig1' concatenated form a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float128_t packFloat128(int zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1) +{ + float128_t z; + z.v0 = zSig1; + z.v64 = (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<48) + zSig0; + return z; +} + +/*---------------------------------------------------------------------------- +| Packs two 64-bit precision integers into into the quadruple-precision +| floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +static __inline float128_t packFloat128(uint64_t zHi, uint64_t zLo) +{ + float128_t z; + z.v0 = zLo; + z.v64 = zHi; + return z; +} + +#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) + +#endif +#endif diff --git a/src/cpu/softfloat3e/softfloat.h b/src/cpu/softfloat3e/softfloat.h new file mode 100644 index 000000000..40253a2a9 --- /dev/null +++ b/src/cpu/softfloat3e/softfloat.h @@ -0,0 +1,702 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/*============================================================================ +| Note: If SoftFloat is made available as a general library for programs to +| use, it is strongly recommended that a platform-specific version of this +| header, "softfloat.h", be created that folds in "softfloat_types.h" and that +| eliminates all dependencies on compile-time macros. +*============================================================================*/ + +#ifndef _SOFTFLOAT_H_ +#define _SOFTFLOAT_H_ + +#include + +#include "softfloat_types.h" +#include "softfloat-extra.h" + +struct softfloat_status_t +{ + uint8_t softfloat_roundingMode; + int softfloat_exceptionFlags; + int softfloat_exceptionMasks; + int softfloat_suppressException; + + bool softfloat_denormals_are_zeros; + bool softfloat_flush_underflow_to_zero; + + /*---------------------------------------------------------------------------- + | Rounding precision for 80-bit extended double-precision floating-point. + | Valid values are 32, 64, and 80. + *----------------------------------------------------------------------------*/ + uint8_t extF80_roundingPrecision; +}; + +/*---------------------------------------------------------------------------- +| Software floating-point rounding mode. +*----------------------------------------------------------------------------*/ +enum { + softfloat_round_near_even = 0, + softfloat_round_min = 1, + softfloat_round_down = softfloat_round_min, + softfloat_round_max = 2, + softfloat_round_up = softfloat_round_max, + softfloat_round_minMag = 3, + softfloat_round_to_zero = softfloat_round_minMag, + softfloat_round_near_maxMag = 4 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point exception flags. +*----------------------------------------------------------------------------*/ +enum softfloat_exception_flag_t { + softfloat_flag_invalid = 0x01, + softfloat_flag_denormal = 0x02, + softfloat_flag_divbyzero = 0x04, + softfloat_flag_infinite = softfloat_flag_divbyzero, + softfloat_flag_overflow = 0x08, + softfloat_flag_underflow = 0x10, + softfloat_flag_inexact = 0x20 +}; + +static const unsigned softfloat_all_exceptions_mask = 0x3f; + +#define FLOATX80 + +#ifdef FLOATX80 +#define RAISE_SW_C1 0x0200 +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point ordering relations +*----------------------------------------------------------------------------*/ +enum { + softfloat_relation_less = -1, + softfloat_relation_equal = 0, + softfloat_relation_greater = 1, + softfloat_relation_unordered = 2 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point class. +*----------------------------------------------------------------------------*/ +typedef enum { + softfloat_zero, + softfloat_SNaN, + softfloat_QNaN, + softfloat_negative_inf, + softfloat_positive_inf, + softfloat_denormal, + softfloat_normalized +} softfloat_class_t; + +/*---------------------------------------------------------------------------- +| Options to indicate which negations to perform in f*_muladd() +| Using these differs from negating an input or output before calling +| the muladd function in that this means that a NaN doesn't have its +| sign bit inverted before it is propagated. +*----------------------------------------------------------------------------*/ +enum { + softfloat_mulAdd_subC = 1, + softfloat_muladd_negate_c = softfloat_mulAdd_subC, + softfloat_mulAdd_subProd = 2, + softfloat_muladd_negate_product = softfloat_mulAdd_subProd, + softfloat_muladd_negate_result = softfloat_muladd_negate_c | softfloat_muladd_negate_product +}; + +static __inline void softfloat_setFlags(struct softfloat_status_t *status, int flags) { + status->softfloat_exceptionFlags = flags; +} + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software floating-point exception flags. +*----------------------------------------------------------------------------*/ +static __inline void softfloat_raiseFlags(struct softfloat_status_t *status, int flags) { + status->softfloat_exceptionFlags |= flags; +} + +/*---------------------------------------------------------------------------- +| Check if exception is masked. +*----------------------------------------------------------------------------*/ +static __inline int softfloat_isMaskedException(const struct softfloat_status_t *status, int flags) { + return status->softfloat_exceptionMasks & flags; +} + +/*---------------------------------------------------------------------------- +| Suppress generation of these exceptions. +*----------------------------------------------------------------------------*/ +static __inline void softfloat_suppressException(struct softfloat_status_t *status, int flags) { + status->softfloat_suppressException |= flags; +} + +/*---------------------------------------------------------------------------- +| Obtain current rounding mode. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_getRoundingMode(const struct softfloat_status_t *status) { + return status->softfloat_roundingMode; +} + +/*---------------------------------------------------------------------------- +| Read denormals-are-zeroes flag. +*----------------------------------------------------------------------------*/ +static __inline bool softfloat_denormalsAreZeros(const struct softfloat_status_t *status) { + return status->softfloat_denormals_are_zeros; +} + +/*---------------------------------------------------------------------------- +| Read flush-underflow-to-zero flag. +*----------------------------------------------------------------------------*/ +static __inline bool softfloat_flushUnderflowToZero(const struct softfloat_status_t *status) { + return status->softfloat_flush_underflow_to_zero; +} + +/*---------------------------------------------------------------------------- +| Obtain current rounding precision for F80. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_extF80_roundingPrecision(const struct softfloat_status_t *status) { + return status->extF80_roundingPrecision; +} + +/*---------------------------------------------------------------------------- +| Returns raised IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +static __inline int softfloat_getExceptionFlags(const struct softfloat_status_t *status) { + return status->softfloat_exceptionFlags & ~status->softfloat_suppressException; +} + +/*---------------------------------------------------------------------------- +| Raise floating point precision lost up flag (floatx80 only). +*----------------------------------------------------------------------------*/ +#ifdef FLOATX80 +static __inline void softfloat_setRoundingUp(struct softfloat_status_t *status) { + status->softfloat_exceptionFlags |= RAISE_SW_C1; +} +#endif + +/*---------------------------------------------------------------------------- +| Integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float16 ui32_to_f16(uint32_t, struct softfloat_status_t *); +float32 ui32_to_f32(uint32_t, struct softfloat_status_t *); +float64 ui32_to_f64(uint32_t); +float16 ui64_to_f16(uint64_t, struct softfloat_status_t *); +float32 ui64_to_f32(uint64_t, struct softfloat_status_t *); +float64 ui64_to_f64(uint64_t, struct softfloat_status_t *); +float16 i32_to_f16(int32_t, struct softfloat_status_t *); +float32 i32_to_f32(int32_t, struct softfloat_status_t *); +float64 i32_to_f64(int32_t); +float16 i64_to_f16(int64_t, struct softfloat_status_t *); +float32 i64_to_f32(int64_t, struct softfloat_status_t *); +float64 i64_to_f64(int64_t, struct softfloat_status_t *); + +static __inline float16 i16_to_f16(int16_t a, struct softfloat_status_t *status) { + return i32_to_f16((int32_t)(a), status); +} + +static __inline float16 ui16_to_f16(uint16_t a, struct softfloat_status_t *status) { + return ui32_to_f16((uint32_t)(a), status); +} + +/*---------------------------------------------------------------------------- +| 16-bit (half-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f16_to_ui32(float16, uint8_t, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64(float16, uint8_t, bool, struct softfloat_status_t *); +int32_t f16_to_i32(float16, uint8_t, bool, struct softfloat_status_t *); +int64_t f16_to_i64(float16, uint8_t, bool, struct softfloat_status_t *); +uint32_t f16_to_ui32_r_minMag(float16, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64_r_minMag(float16, bool, struct softfloat_status_t *); +int32_t f16_to_i32_r_minMag(float16, bool, struct softfloat_status_t *); +int64_t f16_to_i64_r_minMag(float16, bool, struct softfloat_status_t *); +float32 f16_to_f32(float16, struct softfloat_status_t *); +float64 f16_to_f64(float16, struct softfloat_status_t *); +float16 f16_roundToInt(float16, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float16 f16_add(float16, float16, struct softfloat_status_t *); +float16 f16_sub(float16, float16, struct softfloat_status_t *); +float16 f16_mul(float16, float16, struct softfloat_status_t *); +float16 f16_mulAdd(float16, float16, float16, uint8_t op, struct softfloat_status_t *); +float16 f16_div(float16, float16, struct softfloat_status_t *); +float16 f16_min(float16, float16, struct softfloat_status_t *); +float16 f16_max(float16, float16, struct softfloat_status_t *); +float16 f16_getExp(float16, struct softfloat_status_t *); +float16 f16_getMant(float16, struct softfloat_status_t *, int, int); +float16 f16_range(float16, float16, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +int f16_compare(float16, float16, bool, struct softfloat_status_t *); +float16 f16_sqrt(float16, struct softfloat_status_t *); +softfloat_class_t f16_class(float16); + +#ifdef __cplusplus +extern "C" { +#endif +bool f16_isSignalingNaN(float16); +bool f16_isNaN(float16); +#ifdef __cplusplus +} +#endif + +bool f16_sign(float16); +int8_t f16_exp(float16); +uint16_t f16_fraction(float16); +float16 f16_denormal_to_zero(float16); + +static __inline int f16_compare_normal(float16 a, float16 b, struct softfloat_status_t *status) { + return f16_compare(a, b, 0, status); +} + +static __inline int f16_compare_quiet(float16 a, float16 b, struct softfloat_status_t *status) { + return f16_compare(a, b, 1, status); +} + +static __inline float16 f16_roundToInt_normal(float16 a, uint8_t scale, struct softfloat_status_t *status) { + return f16_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float16 f16_roundToInt_noscale(float16 a, struct softfloat_status_t *status) { + return f16_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int64_t f16_to_i64_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_i64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int32_t f16_to_i32_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_i32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int16_t f16_to_i16(float16 a, struct softfloat_status_t *status) +{ + int32_t val_32 = f16_to_i32_normal(a, status); + int16_t val_16 = (int16_t) val_32; + if ((int32_t)(val_16) != val_32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return val_16; +} + +static __inline int64_t f16_to_i64_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_i64_r_minMag(a, true, status); +} +static __inline int32_t f16_to_i32_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_i32_r_minMag(a, true, status); +} + +static __inline int16_t f16_to_i16_round_to_zero(float16 a, struct softfloat_status_t *status) +{ + int32_t val_32 = f16_to_i32_round_to_zero(a, status); + int16_t val_16 = (int16_t) val_32; + if ((int32_t)(val_16) != val_32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return val_16; +} + +static __inline uint64_t f16_to_ui64_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint32_t f16_to_ui32_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint16_t f16_to_ui16(float16 a, struct softfloat_status_t *status) +{ + uint32_t val_32 = f16_to_ui32_normal(a, status); + if (val_32 > 0xFFFF) { + softfloat_setFlags(status, softfloat_flag_invalid); + return 0xFFFF; + } + return (uint16_t) val_32; +} + +static __inline uint64_t f16_to_ui64_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_ui64_r_minMag(a, true, status); +} +static __inline uint32_t f16_to_ui32_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_ui32_r_minMag(a, true, status); +} + +static __inline uint16_t f16_to_ui16_round_to_zero(float16 a, struct softfloat_status_t *status) +{ + uint32_t val_32 = f16_to_ui32_round_to_zero(a, status); + if (val_32 > 0xFFFF) { + softfloat_setFlags(status, softfloat_flag_invalid); + return 0xFFFF; + } + return (uint16_t) val_32; +} + +static __inline float16 f16_fmadd(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, 0, status); +} +static __inline float16 f16_fmsub(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float16 f16_fnmadd(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float16 f16_fnmsub(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +/*---------------------------------------------------------------------------- +| 32-bit (single-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f32_to_ui32(float32, uint8_t, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64(float32, uint8_t, bool, struct softfloat_status_t *); +int32_t f32_to_i32(float32, uint8_t, bool, struct softfloat_status_t *); +int64_t f32_to_i64(float32, uint8_t, bool, struct softfloat_status_t *); +uint32_t f32_to_ui32_r_minMag(float32, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64_r_minMag(float32, bool, struct softfloat_status_t *); +int32_t f32_to_i32_r_minMag(float32, bool, struct softfloat_status_t *); +int64_t f32_to_i64_r_minMag(float32, bool, struct softfloat_status_t *); +float16 f32_to_f16(float32, struct softfloat_status_t *); +float64 f32_to_f64(float32, struct softfloat_status_t *); +float32 f32_roundToInt(float32, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float32 f32_add(float32, float32, struct softfloat_status_t *); +float32 f32_sub(float32, float32, struct softfloat_status_t *); +float32 f32_mul(float32, float32, struct softfloat_status_t *); +float32 f32_mulAdd(float32, float32, float32, uint8_t op, struct softfloat_status_t *); +float32 f32_div(float32, float32, struct softfloat_status_t *); +float32 f32_min(float32, float32, struct softfloat_status_t *); +float32 f32_max(float32, float32, struct softfloat_status_t *); +float32 f32_scalef(float32, float32, struct softfloat_status_t *); +float32 f32_getExp(float32, struct softfloat_status_t *); +float32 f32_getMant(float32, struct softfloat_status_t *, int, int); +float32 f32_range(float32, float32, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +float32 f32_frc(float32, struct softfloat_status_t *); +int f32_compare(float32, float32, bool, struct softfloat_status_t *); +float32 f32_sqrt(float32, struct softfloat_status_t *); +softfloat_class_t f32_class(float32); + +#ifdef __cplusplus +extern "C" { +#endif +bool f32_isSignalingNaN(float32); +bool f32_isNaN(float32); +#ifdef __cplusplus +} +#endif + +bool f32_sign(float32); +int16_t f32_exp(float32); +uint32_t f32_fraction(float32); +float32 f32_denormal_to_zero(float32); + +static __inline int f32_compare_normal(float32 a, float32 b, struct softfloat_status_t *status) { + return f32_compare(a, b, 0, status); +} + +static __inline int f32_compare_quiet(float32 a, float32 b, struct softfloat_status_t *status) { + return f32_compare(a, b, 1, status); +} + +static __inline float32 f32_roundToInt_normal(float32 a, uint8_t scale, struct softfloat_status_t *status) { + return f32_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float32 f32_roundToInt_noscale(float32 a, struct softfloat_status_t *status) { + return f32_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f32_to_i32_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_i32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int64_t f32_to_i64_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_i64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f32_to_i32_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_i32_r_minMag(a, true, status); +} +static __inline int64_t f32_to_i64_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_i64_r_minMag(a, true, status); +} + +static __inline uint32_t f32_to_ui32_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint64_t f32_to_ui64_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint32_t f32_to_ui32_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_ui32_r_minMag(a, true, status); +} +static __inline uint64_t f32_to_ui64_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_ui64_r_minMag(a, true, status); +} + +static __inline float32 f32_fmadd(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, 0, status); +} +static __inline float32 f32_fmsub(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float32 f32_fnmadd(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float32 f32_fnmsub(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +/*---------------------------------------------------------------------------- +| 64-bit (double-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f64_to_ui32(float64, uint8_t, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64(float64, uint8_t, bool, struct softfloat_status_t *); +int32_t f64_to_i32(float64, uint8_t, bool, struct softfloat_status_t *); +int64_t f64_to_i64(float64, uint8_t, bool, struct softfloat_status_t *); +uint32_t f64_to_ui32_r_minMag(float64, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64_r_minMag(float64, bool, struct softfloat_status_t *); +int32_t f64_to_i32_r_minMag(float64, bool, struct softfloat_status_t *); +int64_t f64_to_i64_r_minMag(float64, bool, struct softfloat_status_t *); +float16 f64_to_f16(float64, struct softfloat_status_t *); +float32 f64_to_f32(float64, struct softfloat_status_t *); +float64 f64_roundToInt(float64, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float64 f64_add(float64, float64, struct softfloat_status_t *); +float64 f64_sub(float64, float64, struct softfloat_status_t *); +float64 f64_mul(float64, float64, struct softfloat_status_t *); +float64 f64_mulAdd(float64, float64, float64, uint8_t op, struct softfloat_status_t *); +float64 f64_div(float64, float64, struct softfloat_status_t *); +float64 f64_min(float64, float64, struct softfloat_status_t *); +float64 f64_max(float64, float64, struct softfloat_status_t *); +float64 f64_scalef(float64, float64, struct softfloat_status_t *); +float64 f64_getExp(float64, struct softfloat_status_t *); +float64 f64_getMant(float64, struct softfloat_status_t *, int, int); +float64 f64_range(float64, float64, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +float64 f64_frc(float64, struct softfloat_status_t *); +int f64_compare(float64, float64, bool, struct softfloat_status_t *); +float64 f64_sqrt(float64, struct softfloat_status_t *); +softfloat_class_t f64_class(float64); + +#ifdef __cplusplus +extern "C" { +#endif +bool f64_isSignalingNaN(float64); +bool f64_isNaN(float64); +#ifdef __cplusplus +} +#endif + +bool f64_sign(float64); +int16_t f64_exp(float64); +uint64_t f64_fraction(float64); +float64 f64_denormal_to_zero(float64); + +static __inline int f64_compare_normal(float64 a, float64 b, struct softfloat_status_t *status) { + return f64_compare(a, b, 0, status); +} + +static __inline int f64_compare_quiet(float64 a, float64 b, struct softfloat_status_t *status) { + return f64_compare(a, b, 1, status); +} + +static __inline float64 f64_roundToInt_normal(float64 a, uint8_t scale, struct softfloat_status_t *status) { + return f64_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float64 f64_roundToInt_noscale(float64 a, struct softfloat_status_t *status) { + return f64_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f64_to_i32_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_i32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int64_t f64_to_i64_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_i64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f64_to_i32_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_i32_r_minMag(a, true, status); +} +static __inline int64_t f64_to_i64_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_i64_r_minMag(a, true, status); +} + +static __inline uint32_t f64_to_ui32_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint64_t f64_to_ui64_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint32_t f64_to_ui32_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_ui32_r_minMag(a, true, status); +} +static __inline uint64_t f64_to_ui64_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_ui64_r_minMag(a, true, status); +} + +static __inline float64 f64_fmadd(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, 0, status); +} +static __inline float64 f64_fmsub(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float64 f64_fnmadd(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float64 f64_fnmsub(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| 80-bit extended double-precision floating-point operations. +*----------------------------------------------------------------------------*/ +extFloat80_t f16_to_extF80(float16, struct softfloat_status_t *); +extFloat80_t f32_to_extF80(float32, struct softfloat_status_t *); +extFloat80_t f64_to_extF80(float64, struct softfloat_status_t *); +extFloat80_t i32_to_extF80(int32_t); +extFloat80_t i64_to_extF80(int64_t); +extFloat80_t ui32_to_extF80(uint32_t); +extFloat80_t ui64_to_extF80(uint64_t); + +uint32_t extF80_to_ui32(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t extF80_to_ui64(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +int32_t extF80_to_i32(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +int64_t extF80_to_i64(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +uint32_t extF80_to_ui32_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +uint64_t extF80_to_ui64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +int32_t extF80_to_i32_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +int64_t extF80_to_i64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +float16 extF80_to_f16(extFloat80_t, struct softfloat_status_t *); +float32 extF80_to_f32(extFloat80_t, struct softfloat_status_t *); +float64 extF80_to_f64(extFloat80_t, struct softfloat_status_t *); +float128_t extF80_to_f128(extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_roundToInt(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +extFloat80_t extF80_add(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_sub(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_mul(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_div(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_rem(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_scale(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_sqrt(extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_extract(extFloat80_t *, struct softfloat_status_t *); +int extF80_compare(extFloat80_t, extFloat80_t, int, struct softfloat_status_t *); +softfloat_class_t extF80_class(extFloat80_t); + +static __inline int extF80_compare_normal(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) { + return extF80_compare(a, b, 0, status); +} + +static __inline int extF80_compare_quiet(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) { + return extF80_compare(a, b, 1, status); +} + +static __inline extFloat80_t extF80_roundToInt_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_roundToInt(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int64_t extF80_to_i64_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int32_t extF80_to_i32_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int16_t extF80_to_i16(extFloat80_t a, struct softfloat_status_t *status) +{ + int32_t v32 = extF80_to_i32_normal(a, status); + int16_t v16 = (int16_t) v32; + + if ((int32_t)(v16) != v32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return v16; +} + +static __inline int64_t extF80_to_i64_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i64_r_minMag(a, true, status); +} +static __inline int32_t extF80_to_i32_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i32_r_minMag(a, true, status); +} + +static __inline int16_t extF80_to_i16_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) +{ + int32_t v32 = extF80_to_i32_round_to_zero(a, status); + int16_t v16 = (int16_t) v32; + + if ((int32_t)(v16) != v32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return v16; +} + +bool extF80_isUnsupported(extFloat80_t); +bool extF80_isSignalingNaN(extFloat80_t); +bool extF80_isNaN(extFloat80_t); + +bool extF80_sign(extFloat80_t); +int16_t extF80_exp(extFloat80_t); +uint64_t extF80_fraction(extFloat80_t); + +/*---------------------------------------------------------------------------- +| 128-bit (quadruple-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +float128_t f32_to_f128(float32, struct softfloat_status_t *); +float128_t f64_to_f128(float64, struct softfloat_status_t *); +float128_t i32_to_f128(int32_t); +float128_t i64_to_f128(int64_t); +float128_t ui32_to_f128(uint32_t); +float128_t ui64_to_f128(uint64_t); + +uint32_t f128_to_ui32(float128_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t f128_to_ui64(float128_t, uint8_t, bool, struct softfloat_status_t *); +int32_t f128_to_i32(float128_t, uint8_t, bool, struct softfloat_status_t *); +int64_t f128_to_i64(float128_t, uint8_t, bool, struct softfloat_status_t *); +uint32_t f128_to_ui32_r_minMag(float128_t, bool, struct softfloat_status_t *); +uint64_t f128_to_ui64_r_minMag(float128_t, bool, struct softfloat_status_t *); +int32_t f128_to_i32_r_minMag(float128_t, bool, struct softfloat_status_t *); +int64_t f128_to_i64_r_minMag(float128_t, bool, struct softfloat_status_t *); +float32 f128_to_f32(float128_t, struct softfloat_status_t *); +float64 f128_to_f64(float128_t, struct softfloat_status_t *); +extFloat80_t f128_to_extF80(float128_t, struct softfloat_status_t *); +float128_t f128_roundToInt(float128_t, uint8_t, bool, struct softfloat_status_t *); +float128_t f128_add(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_sub(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_mul(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_mulAdd(float128_t, float128_t, float128_t, uint8_t op, struct softfloat_status_t *); +float128_t f128_div(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_sqrt(float128_t, struct softfloat_status_t *); +bool f128_isSignalingNaN(float128_t); +bool f128_isNaN(float128_t); +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/cpu/softfloat3e/softfloat_types.h b/src/cpu/softfloat3e/softfloat_types.h new file mode 100644 index 000000000..001f8e0c6 --- /dev/null +++ b/src/cpu/softfloat3e/softfloat_types.h @@ -0,0 +1,87 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _SOFTFLOAT_TYPES_H_ +#define _SOFTFLOAT_TYPES_H_ + +#include + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef uint16_t float16, bfloat16; +typedef uint32_t float32; +typedef uint64_t float64; + +struct uint128 { uint64_t v0, v64; }; +struct uint64_extra { uint64_t extra, v; }; +struct uint128_extra { uint64_t extra; struct uint128 v; }; + +/*---------------------------------------------------------------------------- +| Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point +| arguments and results to/from functions. These types must be exactly +| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. +*----------------------------------------------------------------------------*/ +typedef struct f16_t { uint16_t v; } float16_t; +typedef struct f32_t { uint32_t v; } float32_t; +typedef struct f64_t { uint64_t v; } float64_t; +typedef struct uint128 float128_t; + +/*---------------------------------------------------------------------------- +| The format of an 80-bit extended floating-point number in memory. This +| structure must contain a 16-bit field named 'signExp' and a 64-bit field +| named 'signif'. +*----------------------------------------------------------------------------*/ + +struct extFloat80M { + uint64_t signif; + uint16_t signExp; +}; + +/*---------------------------------------------------------------------------- +| The type used to pass 80-bit extended floating-point arguments and +| results to/from functions. This type must have size identical to +| 'struct extFloat80M'. Type 'extFloat80_t' can be defined as an alias for +| 'struct extFloat80M'. Alternatively, if a platform has "native" support +| for IEEE-Standard 80-bit extended floating-point, it may be possible, +| if desired, to define 'extFloat80_t' as an alias for the native type +| (presumably either 'long double' or a nonstandard compiler-intrinsic type). +| In that case, the 'signif' and 'signExp' fields of 'struct extFloat80M' +| must align exactly with the locations in memory of the sign, exponent, and +| significand of the native type. +*----------------------------------------------------------------------------*/ +typedef struct extFloat80M extFloat80_t, floatx80; + +#endif diff --git a/src/cpu/softfloat3e/specialize.h b/src/cpu/softfloat3e/specialize.h new file mode 100644 index 000000000..90d4a2caa --- /dev/null +++ b/src/cpu/softfloat3e/specialize.h @@ -0,0 +1,280 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _SPECIALIZE_H_ +#define _SPECIALIZE_H_ + +#include +#include +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 32-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui32_fromPosOverflow 0xFFFFFFFF +#define ui32_fromNegOverflow 0xFFFFFFFF +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 64-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) + +/*---------------------------------------------------------------------------- +| "Common NaN" structure, used to transfer NaN representations from one format +| to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; + uint64_t v0, v64; +}; + + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 16-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF16UI 0xFE00 + +/*---------------------------------------------------------------------------- +| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a +| 16-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF16UI(uiA) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f16UIToCommonNaN(uint16_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_commonNaNToF16UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint16_t + softfloat_propagateNaNF16UI(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI(uiA) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN(uint32_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_commonNaNToF32UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint32_t + softfloat_propagateNaNF32UI(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) + +/*---------------------------------------------------------------------------- +| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a +| 64-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF64UI(uiA) ((((uiA) & UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA) & UINT64_C(0x0007FFFFFFFFFFFF))) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN(uint64_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_commonNaNToF64UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint64_t + softfloat_propagateNaNF64UI(uint64_t uiA, uint64_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 80-bit extended floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNExtF80UI64 0xFFFF +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) + +/*---------------------------------------------------------------------------- +| Returns true when the 80-bit unsigned integer formed from concatenating +| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended +| floating-point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C(0x4000000000000000)) && ((uiA0) & UINT64_C(0x3FFFFFFFFFFFFFFF))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_extF80UIToCommonNaN(uint16_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +extFloat80_t + softfloat_propagateNaNExtF80UI( + uint16_t uiA64, + uint64_t uiA0, + uint16_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) + +/*---------------------------------------------------------------------------- +| Returns true when the 128-bit unsigned integer formed from concatenating +| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating- +| point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF128UI(uiA64, uiA0) ((((uiA64) & UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64) & UINT64_C(0x00007FFFFFFFFFFF)))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f128UIToCommonNaN(uint64_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN *); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status +); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpu/softfloat3e/ui32_to_extF80.cc b/src/cpu/softfloat3e/ui32_to_extF80.cc new file mode 100644 index 000000000..80c6d86b0 --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_extF80.cc @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t ui32_to_extF80(uint32_t a) +{ + uint16_t uiZ64; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros32(a); + uiZ64 = 0x401E - shiftDist; + a <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = (uint64_t) a<<32; + return z; +} diff --git a/src/cpu/softfloat3e/ui32_to_f128.cc b/src/cpu/softfloat3e/ui32_to_f128.cc new file mode 100644 index 000000000..6ef8214a8 --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_f128.cc @@ -0,0 +1,55 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t ui32_to_f128(uint32_t a) +{ + uint64_t uiZ64; + int8_t shiftDist; + float128_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros32(a) + 17; + uiZ64 = packToF128UI64(0, 0x402E - shiftDist, (uint64_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 ui32_to_f16(uint32_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint16_t sig; + + shiftDist = softfloat_countLeadingZeros32(a) - 21; + if (0 <= shiftDist) { + return a ? packToF16UI(0, 0x18 - shiftDist, (uint16_t) a<>(-shiftDist) | ((uint32_t) (a<<(shiftDist & 31)) != 0) + : (uint16_t) a< +#include "internals.h" +#include "softfloat.h" + +float32 ui32_to_f32(uint32_t a, struct softfloat_status_t *status) +{ + if (! a) { + return 0; + } + if (a & 0x80000000) { + return softfloat_roundPackToF32(0, 0x9D, a>>1 | (a & 1), status); + } else { + return softfloat_normRoundPackToF32(0, 0x9C, a, status); + } +} diff --git a/src/cpu/softfloat3e/ui32_to_f64.c b/src/cpu/softfloat3e/ui32_to_f64.c new file mode 100644 index 000000000..524d64eed --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_f64.c @@ -0,0 +1,49 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 ui32_to_f64(uint32_t a) +{ + if (! a) { + return 0; + } else { + int8_t shiftDist = softfloat_countLeadingZeros32(a) + 21; + return packToF64UI(0, 0x432 - shiftDist, (uint64_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t ui64_to_extF80(uint64_t a) +{ + uint16_t uiZ64; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros64(a); + uiZ64 = 0x403E - shiftDist; + a <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = a; + return z; +} diff --git a/src/cpu/softfloat3e/ui64_to_f128.cc b/src/cpu/softfloat3e/ui64_to_f128.cc new file mode 100644 index 000000000..91be29f37 --- /dev/null +++ b/src/cpu/softfloat3e/ui64_to_f128.cc @@ -0,0 +1,65 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t ui64_to_f128(uint64_t a) +{ + uint64_t uiZ64, uiZ0; + int8_t shiftDist; + struct uint128 zSig; + float128_t z; + + if (! a) { + uiZ64 = 0; + uiZ0 = 0; + } else { + shiftDist = softfloat_countLeadingZeros64(a) + 49; + if (64 <= shiftDist) { + zSig.v64 = a<<(shiftDist - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128(0, a, shiftDist); + } + uiZ64 = packToF128UI64(0, 0x406E - shiftDist, zSig.v64); + uiZ0 = zSig.v0; + } + z.v64 = uiZ64; + z.v0 = uiZ0; + return z; +} diff --git a/src/cpu/softfloat3e/ui64_to_f16.c b/src/cpu/softfloat3e/ui64_to_f16.c new file mode 100644 index 000000000..f2339e905 --- /dev/null +++ b/src/cpu/softfloat3e/ui64_to_f16.c @@ -0,0 +1,55 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 ui64_to_f16(uint64_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint16_t sig; + + shiftDist = softfloat_countLeadingZeros64(a) - 53; + if (0 <= shiftDist) { + return a ? packToF16UI(0, 0x18 - shiftDist, (uint16_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 ui64_to_f32(uint64_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint32_t sig; + + shiftDist = softfloat_countLeadingZeros64(a) - 40; + if (0 <= shiftDist) { + return a ? packToF32UI(0, 0x95 - shiftDist, (uint32_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 ui64_to_f64(uint64_t a, struct softfloat_status_t *status) +{ + if (! a) { + return 0; + } + if (a & UINT64_C(0x8000000000000000)) { + return softfloat_roundPackToF64(0, 0x43D, softfloat_shortShiftRightJam64(a, 1), status); + } else { + return softfloat_normRoundPackToF64(0, 0x43C, a, status); + } +} diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 6fb9b7a22..86f54ee3b 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -434,9 +434,9 @@ extern const OpFn ops_2386_REPE[1024]; extern const OpFn ops_2386_REPNE[1024]; extern const OpFn ops_2386_3DNOW[256]; -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ #endif /*_X86_OPS_H*/ diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 849e24e3d..9ea04b447 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -4,6 +4,7 @@ static int opESCAPE_d8_a16(uint32_t fetchdat) { + //pclog("D8 A16: fetchdat=%02x.\n", (fetchdat >> 3) & 0x1f); return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int @@ -15,6 +16,7 @@ opESCAPE_d8_a32(uint32_t fetchdat) static int opESCAPE_d9_a16(uint32_t fetchdat) { + //pclog("D9 A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); } static int @@ -26,6 +28,7 @@ opESCAPE_d9_a32(uint32_t fetchdat) static int opESCAPE_da_a16(uint32_t fetchdat) { + //pclog("DA A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); } static int @@ -37,6 +40,7 @@ opESCAPE_da_a32(uint32_t fetchdat) static int opESCAPE_db_a16(uint32_t fetchdat) { + //pclog("DB A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); } static int @@ -48,6 +52,7 @@ opESCAPE_db_a32(uint32_t fetchdat) static int opESCAPE_dc_a16(uint32_t fetchdat) { + //pclog("DC A16: fetchdat=%02x.\n", (fetchdat >> 3) & 0x1f); return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int @@ -59,6 +64,7 @@ opESCAPE_dc_a32(uint32_t fetchdat) static int opESCAPE_dd_a16(uint32_t fetchdat) { + //pclog("DD A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); } static int @@ -70,6 +76,7 @@ opESCAPE_dd_a32(uint32_t fetchdat) static int opESCAPE_de_a16(uint32_t fetchdat) { + //pclog("DE A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); } static int @@ -81,6 +88,7 @@ opESCAPE_de_a32(uint32_t fetchdat) static int opESCAPE_df_a16(uint32_t fetchdat) { + //pclog("DF A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); } static int diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index ab9d02d25..5e5dc3c7c 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -100,8 +100,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) /* load i387 register file */ for (index = 0; index < 8; index++) { - reg.fraction = readmemq(easeg, cpu_state.eaaddr + (index * 16) + 32); - reg.exp = readmemw(easeg, cpu_state.eaaddr + (index * 16) + 40); + reg.signif = readmemq(easeg, cpu_state.eaaddr + (index * 16) + 32); + reg.signExp = readmemw(easeg, cpu_state.eaaddr + (index * 16) + 40); // update tag only if it is not empty FPU_save_regi_tag(reg, IS_TAG_EMPTY(index) ? X87_TAG_EMPTY : FPU_tagof(reg), index); @@ -159,8 +159,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) for (index = 0; index < 8; index++) { const floatx80 fp = FPU_read_regi(index); - writememq(easeg, cpu_state.eaaddr + (index * 16) + 32, fp.fraction); - writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.exp); + writememq(easeg, cpu_state.eaaddr + (index * 16) + 32, fp.signif); + writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp); } CLOCK_CYCLES((cr0 & 1) ? 56 : 67); diff --git a/src/cpu/x86_ops_mmx.c b/src/cpu/x86_ops_mmx.c index f26c903f9..55fc987c2 100644 --- a/src/cpu/x86_ops_mmx.c +++ b/src/cpu/x86_ops_mmx.c @@ -33,7 +33,7 @@ uint16_t *MMEP[8]; static uint16_t MME[8]; -#define MMX_GETREGP(r) fpu_softfloat ? ((MMX_REG *) &fpu_state.st_space[r].fraction) : &(cpu_state.MM[r]) +#define MMX_GETREGP(r) fpu_softfloat ? ((MMX_REG *) &fpu_state.st_space[r].signif) : &(cpu_state.MM[r]) void mmx_init(void) { @@ -41,8 +41,8 @@ mmx_init(void) for (uint8_t i = 0; i < 8; i++) { if (fpu_softfloat) { - MMP[i] = (MMX_REG *) &fpu_state.st_space[i].fraction; - MMEP[i] = (uint16_t *) &fpu_state.st_space[i].exp; + MMP[i] = (MMX_REG *) &fpu_state.st_space[i].signif; + MMEP[i] = (uint16_t *) &fpu_state.st_space[i].signExp; } else { MMP[i] = &(cpu_state.MM[i]); MMEP[i] = &(MME[i]); diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 1f7643453..980431f15 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -16,7 +16,9 @@ #include "x86seg_common.h" #include "x87.h" #include "386_common.h" -#include "softfloat/softfloat-specialize.h" +#include "softfloat3e/config.h" +#include "softfloat3e/fpu_trans.h" +#include "softfloat3e/specialize.h" uint32_t x87_pc_off; uint32_t x87_op_off; @@ -106,24 +108,24 @@ x87_settag(uint16_t new_tag) } #endif -static floatx80 -FPU_handle_NaN32_Func(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, struct float_status_t *status) +static extFloat80_t +FPU_handle_NaN32_Func(extFloat80_t a, int aIsNaN, float32 b32, int bIsNaN, struct softfloat_status_t *status) { - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsSignalingNaN = float32_is_signaling_nan(b32); + int aIsSignalingNaN = extF80_isSignalingNaN(a); + int bIsSignalingNaN = f32_isSignalingNaN(b32); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaNOne(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, status); if (aIsNaN & !bIsNaN) return a; // float32 is NaN so conversion will propagate SNaN to QNaN and raise // appropriate exception flags - floatx80 b = float32_to_floatx80(b32, status); + extFloat80_t b = f32_to_extF80(b32, status); if (aIsSignalingNaN) { if (bIsSignalingNaN) @@ -133,29 +135,33 @@ FPU_handle_NaN32_Func(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, struct fl if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) + if (a.signif < b.signif) return b; - if (b.fraction < a.fraction) + if (b.signif < a.signif) return a; - return (a.exp < b.exp) ? a : b; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } int -FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status) +FPU_handle_NaN32(extFloat80_t a, float32 b, extFloat80_t *r, struct softfloat_status_t *status) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return 1; } - int aIsNaN = floatx80_is_nan(a); - int bIsNaN = float32_is_nan(b); + int aIsNaN = extF80_isNaN(a); + int bIsNaN = f32_isNaN(b); if (aIsNaN | bIsNaN) { *r = FPU_handle_NaN32_Func(a, aIsNaN, b, bIsNaN, status); return 1; @@ -163,24 +169,24 @@ FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *stat return 0; } -static floatx80 -FPU_handle_NaN64_Func(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, struct float_status_t *status) +static extFloat80_t +FPU_handle_NaN64_Func(extFloat80_t a, int aIsNaN, float64 b64, int bIsNaN, struct softfloat_status_t *status) { - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsSignalingNaN = float64_is_signaling_nan(b64); + int aIsSignalingNaN = extF80_isSignalingNaN(a); + int bIsSignalingNaN = f64_isSignalingNaN(b64); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaNOne(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, status); if (aIsNaN & !bIsNaN) return a; // float64 is NaN so conversion will propagate SNaN to QNaN and raise // appropriate exception flags - floatx80 b = float64_to_floatx80(b64, status); + extFloat80_t b = f64_to_extF80(b64, status); if (aIsSignalingNaN) { if (bIsSignalingNaN) @@ -190,29 +196,33 @@ FPU_handle_NaN64_Func(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, struct fl if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) + if (a.signif < b.signif) return b; - if (b.fraction < a.fraction) + if (b.signif < a.signif) return a; - return (a.exp < b.exp) ? a : b; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } int -FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status) +FPU_handle_NaN64(extFloat80_t a, float64 b, extFloat80_t *r, struct softfloat_status_t *status) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const extFloat80_t floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return 1; } - int aIsNaN = floatx80_is_nan(a); - int bIsNaN = float64_is_nan(b); + int aIsNaN = extF80_isNaN(a); + int bIsNaN = f64_isNaN(b); if (aIsNaN | bIsNaN) { *r = FPU_handle_NaN64_Func(a, aIsNaN, b, bIsNaN, status); return 1; @@ -220,37 +230,36 @@ FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *stat return 0; } -struct float_status_t +struct softfloat_status_t i387cw_to_softfloat_status_word(uint16_t control_word) { - struct float_status_t status; + struct softfloat_status_t status; int precision = control_word & FPU_CW_PC; switch (precision) { case FPU_PR_32_BITS: - status.float_rounding_precision = 32; + status.extF80_roundingPrecision = 32; break; case FPU_PR_64_BITS: - status.float_rounding_precision = 64; + status.extF80_roundingPrecision = 64; break; case FPU_PR_80_BITS: - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; break; default: /* With the precision control bits set to 01 "(reserved)", a real CPU behaves as if the precision control bits were set to 11 "80 bits" */ - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; break; } - status.float_exception_flags = 0; // clear exceptions before execution - status.float_nan_handling_mode = float_first_operand_nan; - status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10; - status.flush_underflow_to_zero = 0; - status.float_suppress_exception = 0; - status.float_exception_masks = control_word & FPU_CW_Exceptions_Mask; - status.denormals_are_zeros = 0; + status.softfloat_exceptionFlags = 0; // clear exceptions before execution + status.softfloat_roundingMode = (control_word & FPU_CW_RC) >> 10; + status.softfloat_flush_underflow_to_zero = 0; + status.softfloat_suppressException = 0; + status.softfloat_exceptionMasks = control_word & FPU_CW_Exceptions_Mask; + status.softfloat_denormals_are_zeros = 0; return status; } @@ -258,17 +267,20 @@ int FPU_status_word_flags_fpu_compare(int float_relation) { switch (float_relation) { - case float_relation_unordered: - return (C0 | C2 | C3); + case softfloat_relation_unordered: + return (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); - case float_relation_greater: + case softfloat_relation_greater: return 0; - case float_relation_less: - return C0; + case softfloat_relation_less: + return FPU_SW_C0; - case float_relation_equal: - return C3; + case softfloat_relation_equal: + return FPU_SW_C3; + + default: + break; } return (-1); // should never get here @@ -278,18 +290,18 @@ void FPU_write_eflags_fpu_compare(int float_relation) { switch (float_relation) { - case float_relation_unordered: + case softfloat_relation_unordered: cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); break; - case float_relation_greater: + case softfloat_relation_greater: break; - case float_relation_less: + case softfloat_relation_less: cpu_state.flags |= C_FLAG; break; - case float_relation_equal: + case softfloat_relation_equal: cpu_state.flags |= Z_FLAG; break; @@ -324,10 +336,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) // FPU_EX_Invalid cannot come with any other exception but x87 stack fault fpu_state.swd |= exceptions; if (exceptions & FPU_SW_Stack_Fault) { - if (!(exceptions & C1)) { + if (!(exceptions & FPU_SW_C1)) { /* This bit distinguishes over- from underflow for a stack fault, and roundup from round-down for precision loss. */ - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; } } return unmasked; @@ -359,10 +371,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) fpu_state.swd |= exceptions; if (exceptions & FPU_EX_Precision) { - if (!(exceptions & C1)) { + if (!(exceptions & FPU_SW_C1)) { /* This bit distinguishes over- from underflow for a stack fault, and roundup from round-down for precision loss. */ - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; } } @@ -380,7 +392,7 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) if (!store) unmasked &= ~(FPU_EX_Underflow | FPU_EX_Overflow); else { - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; if (!(status & FPU_EX_Precision)) fpu_state.swd &= ~FPU_EX_Precision; } @@ -391,7 +403,11 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) void FPU_stack_overflow(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); /* The masked response */ if (is_IA_masked()) { @@ -404,7 +420,11 @@ FPU_stack_overflow(uint32_t fetchdat) void FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); /* The masked response */ if (is_IA_masked()) { @@ -420,11 +440,11 @@ FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack) * rather than a kernel (ported by Kevin Lawton) * ------------------------------------------------------------ */ int -FPU_tagof(const floatx80 reg) +FPU_tagof(const extFloat80_t reg) { - int32_t exp = floatx80_exp(reg); + int32_t exp = extF80_exp(reg); if (exp == 0) { - if (!floatx80_fraction(reg)) + if (!extF80_fraction(reg)) return X87_TAG_ZERO; /* The number is a de-normal or pseudodenormal. */ @@ -436,7 +456,7 @@ FPU_tagof(const floatx80 reg) return X87_TAG_INVALID; } - if (!(reg.fraction & BX_CONST64(0x8000000000000000))) { + if (!(reg.signif & BX_CONST64(0x8000000000000000))) { /* Unsupported data type. */ /* Valid numbers have the ms bit set to 1. */ return X87_TAG_INVALID; @@ -516,12 +536,10 @@ unpack_FPU_TW(uint16_t tag_byte) */ for (int index = 7; index >= 0; index--, twd <<= 2, tag_byte <<= 1) { - if (tag_byte & 0x80) { - const floatx80 *fpu_reg = &fpu_state.st_space[index & 7]; - twd |= FPU_tagof(*fpu_reg); - } else { + if (tag_byte & 0x80) + twd |= FPU_tagof(fpu_state.st_space[index & 7]); + else twd |= X87_TAG_EMPTY; - } } return (twd >> 2); diff --git a/src/cpu/x87.h b/src/cpu/x87.h index f4e24f1ca..197e18bfe 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -60,89 +60,80 @@ void x87_settag(uint16_t new_tag); void codegen_set_rounding_mode(int mode); /* Status Word */ -#define FPU_SW_Backward (0x8000) /* backward compatibility */ -#define FPU_SW_C3 (0x4000) /* condition bit 3 */ -#define FPU_SW_Top (0x3800) /* top of stack */ -#define FPU_SW_C2 (0x0400) /* condition bit 2 */ -#define FPU_SW_C1 (0x0200) /* condition bit 1 */ -#define FPU_SW_C0 (0x0100) /* condition bit 0 */ -#define FPU_SW_Summary (0x0080) /* exception summary */ -#define FPU_SW_Stack_Fault (0x0040) /* stack fault */ -#define FPU_SW_Precision (0x0020) /* loss of precision */ -#define FPU_SW_Underflow (0x0010) /* underflow */ -#define FPU_SW_Overflow (0x0008) /* overflow */ -#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ -#define FPU_SW_Denormal_Op (0x0002) /* denormalized operand */ -#define FPU_SW_Invalid (0x0001) /* invalid operation */ +#define FPU_SW_Backward (0x8000) /* backward compatibility */ +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_Top (0x3800) /* top of stack */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ +#define FPU_SW_Summary (0x0080) /* exception summary */ +#define FPU_SW_Stack_Fault (0x0040) /* stack fault */ +#define FPU_SW_Precision (0x0020) /* loss of precision */ +#define FPU_SW_Underflow (0x0010) /* underflow */ +#define FPU_SW_Overflow (0x0008) /* overflow */ +#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ +#define FPU_SW_Denormal_Op (0x0002) /* denormalized operand */ +#define FPU_SW_Invalid (0x0001) /* invalid operation */ -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) +#define FPU_SW_CC (FPU_SW_C0|FPU_SW_C1|FPU_SW_C2|FPU_SW_C3) -#define FPU_SW_CC (C0 | C1 | C2 | C3) - -#define FPU_SW_Exceptions_Mask (0x027f) /* status word exceptions bit mask */ +#define FPU_SW_Exceptions_Mask (0x027f) /* status word exceptions bit mask */ /* Exception flags: */ -#define FPU_EX_Precision (0x0020) /* loss of precision */ -#define FPU_EX_Underflow (0x0010) /* underflow */ -#define FPU_EX_Overflow (0x0008) /* overflow */ -#define FPU_EX_Zero_Div (0x0004) /* divide by zero */ -#define FPU_EX_Denormal (0x0002) /* denormalized operand */ -#define FPU_EX_Invalid (0x0001) /* invalid operation */ +#define FPU_EX_Precision (0x0020) /* loss of precision */ +#define FPU_EX_Underflow (0x0010) /* underflow */ +#define FPU_EX_Overflow (0x0008) /* overflow */ +#define FPU_EX_Zero_Div (0x0004) /* divide by zero */ +#define FPU_EX_Denormal (0x0002) /* denormalized operand */ +#define FPU_EX_Invalid (0x0001) /* invalid operation */ /* Special exceptions: */ -#define FPU_EX_Stack_Overflow (0x0041 | C1) /* stack overflow */ -#define FPU_EX_Stack_Underflow (0x0041) /* stack underflow */ +#define FPU_EX_Stack_Overflow (0x0041|FPU_SW_C1) /* stack overflow */ +#define FPU_EX_Stack_Underflow (0x0041) /* stack underflow */ /* precision control */ -#define FPU_EX_Precision_Lost_Up (EX_Precision | C1) -#define FPU_EX_Precision_Lost_Dn (EX_Precision) +#define FPU_EX_Precision_Lost_Up (EX_Precision | SW_C1) +#define FPU_EX_Precision_Lost_Dn (EX_Precision) -#define setcc(cc) \ - fpu_state.swd = (fpu_state.swd & ~(FPU_SW_CC)) | ((cc) &FPU_SW_CC) +#define setcc(cc) \ + fpu_state.swd = (fpu_state.swd & ~(FPU_SW_CC)) | ((cc) & FPU_SW_CC) -#define clear_C1() \ - { \ - fpu_state.swd &= ~C1; \ - } -#define clear_C2() \ - { \ - fpu_state.swd &= ~C2; \ - } +#define clear_C1() { fpu_state.swd &= ~FPU_SW_C1; } +#define clear_C2() { fpu_state.swd &= ~FPU_SW_C2; } /* ************ */ /* Control Word */ /* ************ */ -#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ +#define FPU_CW_Reserved_Bits (0xe0c0) /* reserved bits */ -#define FPU_CW_RC (0x0C00) /* rounding control */ -#define FPU_CW_PC (0x0300) /* precision control */ +#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ -#define FPU_RC_RND (0x0000) /* rounding control */ -#define FPU_RC_DOWN (0x0400) -#define FPU_RC_UP (0x0800) -#define FPU_RC_CHOP (0x0C00) +#define FPU_CW_RC (0x0C00) /* rounding control */ +#define FPU_CW_PC (0x0300) /* precision control */ -#define FPU_CW_Precision (0x0020) /* loss of precision mask */ -#define FPU_CW_Underflow (0x0010) /* underflow mask */ -#define FPU_CW_Overflow (0x0008) /* overflow mask */ -#define FPU_CW_Zero_Div (0x0004) /* divide by zero mask */ -#define FPU_CW_Denormal (0x0002) /* denormalized operand mask */ -#define FPU_CW_Invalid (0x0001) /* invalid operation mask */ +#define FPU_RC_RND (0x0000) /* rounding control */ +#define FPU_RC_DOWN (0x0400) +#define FPU_RC_UP (0x0800) +#define FPU_RC_CHOP (0x0C00) -#define FPU_CW_Exceptions_Mask (0x003f) /* all masks */ +#define FPU_CW_Precision (0x0020) /* loss of precision mask */ +#define FPU_CW_Underflow (0x0010) /* underflow mask */ +#define FPU_CW_Overflow (0x0008) /* overflow mask */ +#define FPU_CW_Zero_Div (0x0004) /* divide by zero mask */ +#define FPU_CW_Denormal (0x0002) /* denormalized operand mask */ +#define FPU_CW_Invalid (0x0001) /* invalid operation mask */ + +#define FPU_CW_Exceptions_Mask (0x003f) /* all masks */ /* Precision control bits affect only the following: ADD, SUB(R), MUL, DIV(R), and SQRT */ -#define FPU_PR_32_BITS (0x000) -#define FPU_PR_RESERVED_BITS (0x100) -#define FPU_PR_64_BITS (0x200) -#define FPU_PR_80_BITS (0x300) +#define FPU_PR_32_BITS (0x000) +#define FPU_PR_RESERVED_BITS (0x100) +#define FPU_PR_64_BITS (0x200) +#define FPU_PR_80_BITS (0x300) -#include "softfloat/softfloatx80.h" +#include "softfloat3e/softfloat.h" static __inline int is_IA_masked(void) @@ -150,15 +141,15 @@ is_IA_masked(void) return (fpu_state.cwd & FPU_CW_Invalid); } -struct float_status_t i387cw_to_softfloat_status_word(uint16_t control_word); +struct softfloat_status_t i387cw_to_softfloat_status_word(uint16_t control_word); uint16_t FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store); int FPU_status_word_flags_fpu_compare(int float_relation); void FPU_write_eflags_fpu_compare(int float_relation); void FPU_stack_overflow(uint32_t fetchdat); void FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack); -int FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status); -int FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status); -int FPU_tagof(const floatx80 reg); +int FPU_handle_NaN32(extFloat80_t a, float32 b, extFloat80_t *r, struct softfloat_status_t *status); +int FPU_handle_NaN64(extFloat80_t a, float64 b, extFloat80_t *r, struct softfloat_status_t *status); +int FPU_tagof(const extFloat80_t reg); uint8_t pack_FPU_TW(uint16_t twd); uint16_t unpack_FPU_TW(uint16_t tag_byte); @@ -207,11 +198,11 @@ FPU_push(void) static __inline void FPU_pop(void) { - fpu_state.tag |= 3 << (fpu_state.tos * 2); + fpu_state.tag |= (3 << (fpu_state.tos * 2)); fpu_state.tos = (fpu_state.tos + 1) & 7; } -static __inline floatx80 +static __inline extFloat80_t FPU_read_regi(int stnr) { return fpu_state.st_space[(stnr + fpu_state.tos) & 7]; @@ -221,14 +212,14 @@ FPU_read_regi(int stnr) // instructions like FNSAVE, and they update tag word to its // real value anyway static __inline void -FPU_save_regi(floatx80 reg, int stnr) +FPU_save_regi(extFloat80_t reg, int stnr) { fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; FPU_settagi_valid(stnr); } static __inline void -FPU_save_regi_tag(floatx80 reg, int tag, int stnr) +FPU_save_regi_tag(extFloat80_t reg, int tag, int stnr) { fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; FPU_settagi(tag, stnr); @@ -237,6 +228,7 @@ FPU_save_regi_tag(floatx80 reg, int tag, int stnr) #define FPU_check_pending_exceptions() \ do { \ if (fpu_state.swd & FPU_SW_Summary) { \ + pclog("SW Summary.\n"); \ if (cr0 & 0x20) { \ x86_int(16); \ return 1; \ diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index aef9289e7..6be9d7648 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -40,17 +40,17 @@ static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARD #define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)] -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ #define X87_TAG_VALID 0 #define X87_TAG_ZERO 1 #define X87_TAG_INVALID 2 #define X87_TAG_EMPTY 3 -#define STATUS_ZERODIVIDE 4 +#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ typedef union { double d; @@ -76,8 +76,8 @@ typedef union { # define x87_div(dst, src1, src2) \ do { \ if (((double) src2) == 0.0) { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + cpu_state.npxs |= FPU_SW_Zero_Div; \ + if (cpu_state.npxc & FPU_SW_Zero_Div) \ dst = src1 / (double) src2; \ else { \ fpu_log("FPU : divide by zero\n"); \ @@ -94,8 +94,8 @@ typedef union { # define x87_div(dst, src1, src2) \ do { \ if (((double) src2) == 0.0) { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + cpu_state.npxs |= FPU_SW_Zero_Div; \ + if (cpu_state.npxc & FPU_SW_Zero_Div) \ dst = src1 / (double) src2; \ else { \ fpu_log("FPU : divide by zero\n"); \ @@ -107,12 +107,6 @@ typedef union { } while (0) #endif -static __inline void -x87_checkexceptions(void) -{ - // -} - static __inline void x87_push(double i) { @@ -366,7 +360,7 @@ x87_compare(double a, double b) /* Hack to make CHKCOP happy. */ if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8)) - return C3; + return FPU_SW_C3; if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) eb = ea; @@ -399,7 +393,7 @@ x87_compare(double a, double b) } # endif - return result & (C0 | C2 | C3); + return result & (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ @@ -410,9 +404,9 @@ x87_compare(double a, double b) eb = ea; if (ea == eb) - result |= C3; + result |= FPU_SW_C3; else if (ea < eb) - result |= C0; + result |= FPU_SW_C0; return result; #endif @@ -452,16 +446,16 @@ x87_ucompare(double a, double b) } # endif - return result & (C0 | C2 | C3); + return result & (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ uint32_t result = 0; if (a == b) - result |= C3; + result |= FPU_SW_C3; else if (a < b) - result |= C0; + result |= FPU_SW_C0; return result; #endif @@ -503,7 +497,8 @@ typedef union { # define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64 #endif -#include "softfloat/softfloat-specialize.h" +#include "softfloat3e/softfloat-specialize.h" +#include "softfloat3e/fpu_trans.h" #include "x87_ops_sf_arith.h" #include "x87_ops_sf_compare.h" @@ -1093,10 +1088,10 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = { const OpFn OP_TABLE(sf_fpu_d8_a16)[32] = { // clang-format off - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, + /*0x00*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x08*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x10*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x18*/ sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, // clang-format on }; @@ -1191,41 +1186,41 @@ const OpFn OP_TABLE(sf_fpu_287_d9_a32)[256] = { const OpFn OP_TABLE(sf_fpu_d9_a16)[256] = { // clang-format off - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + /*0x00*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x18*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x20*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x28*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x30*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x38*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + /*0x40*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x58*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x60*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x68*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x70*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x78*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + /*0x80*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x98*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0xa0*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0xa8*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0xb0*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0xb8*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ - sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, - sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, - sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, - sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + /*0xc0*/ sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + /*0xe0*/ sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + /*0xf0*/ sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + /*0xf8*/ sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, // clang-format on }; @@ -1593,41 +1588,41 @@ const OpFn OP_TABLE(sf_fpu_287_db_a32)[256] = { const OpFn OP_TABLE(sf_fpu_db_a16)[256] = { // clang-format off - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + /*0x00*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x18*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0x20*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x28*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0x30*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x38*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + /*0x40*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x58*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0x60*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x68*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0x70*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x78*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + /*0x80*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x98*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0xa0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xa8*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0xb0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb8*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xc0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xc8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe0*/ sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; @@ -1870,41 +1865,41 @@ const OpFn OP_TABLE(sf_fpu_287_dd_a32)[256] = { const OpFn OP_TABLE(sf_fpu_dd_a16)[256] = { // clang-format off - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + /*0x00*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x18*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x20*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x28*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x30*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x38*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + /*0x40*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x58*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x60*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x68*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x70*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x78*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + /*0x80*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x98*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0xa0*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0xa8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb0*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0xb8*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, - sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xc0*/ sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + /*0xe8*/ sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; @@ -2030,41 +2025,41 @@ const OpFn OP_TABLE(sf_fpu_287_de_a32)[256] = { const OpFn OP_TABLE(sf_fpu_de_a16)[256] = { // clang-format off - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + /*0x00*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x08*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x10*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x18*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0x20*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0x28*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0x30*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0x38*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + /*0x40*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x48*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x50*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x58*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0x60*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0x68*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0x70*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0x78*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + /*0x80*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x88*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x90*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x98*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0xa0*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0xa8*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0xb0*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0xb8*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, - sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, - sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, - ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, - sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, - sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, - sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + /*0xc0*/ sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + /*0xc8*/ sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + /*0xd0*/ sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, + /*0xd8*/ ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe0*/ sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + /*0xe8*/ sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + /*0xf0*/ sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + /*0xf8*/ sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, // clang-format on }; @@ -2190,41 +2185,41 @@ const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { // clang-format off - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + /*0x00*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x18*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0x20*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0x28*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0x30*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0x38*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + /*0x40*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x58*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0x60*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0x68*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0x70*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0x78*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + /*0x80*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x98*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0xa0*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0xa8*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0xb0*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0xb8*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xc0*/ sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; diff --git a/src/cpu/x87_ops_arith.h b/src/cpu/x87_ops_arith.h index 808a15051..31c26231b 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/cpu/x87_ops_arith.h @@ -27,7 +27,7 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ @@ -42,7 +42,7 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ x87_pop(); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ @@ -128,24 +128,24 @@ // clang-format off opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32) #ifndef FPU_8087 - opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) +opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) #endif opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64) #ifndef FPU_8087 - opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) +opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) #endif opFPU(iw, uint16_t, 16, t, geteaw, (double) (int16_t) t, _i16) #ifndef FPU_8087 - opFPU(iw, uint16_t, 32, t, geteaw, (double) (int16_t) t, _i16) +opFPU(iw, uint16_t, 32, t, geteaw, (double) (int16_t) t, _i16) #endif opFPU(il, uint32_t, 16, t, geteal, (double) (int32_t) t, _i32) #ifndef FPU_8087 - opFPU(il, uint32_t, 32, t, geteal, (double) (int32_t) t, _i32) +opFPU(il, uint32_t, 32, t, geteal, (double) (int32_t) t, _i32) #endif - // clang-format on +// clang-format on - static int opFADD(uint32_t fetchdat) +static int opFADD(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; @@ -184,11 +184,11 @@ opFCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (ST(0) == ST(fetchdat & 7)) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else if (ST(0) < ST(fetchdat & 7)) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); return 0; @@ -199,7 +199,7 @@ opFCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); x87_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -213,11 +213,11 @@ opFCOMPP(uint32_t fetchdat) uint64_t *p, *q; FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); p = (uint64_t *) &ST(0); q = (uint64_t *) &ST(1); if ((*p == ((uint64_t) 1 << 63) && *q == 0) && (fpu_type >= FPU_287XL)) - cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/ + cpu_state.npxs |= FPU_SW_C0; /*Nasty hack to fix 80387 detection*/ else cpu_state.npxs |= x87_compare(ST(0), ST(1)); @@ -233,7 +233,7 @@ opFUCOMPP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); x87_pop(); x87_pop(); @@ -458,7 +458,7 @@ opFUCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); @@ -470,7 +470,7 @@ opFUCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); x87_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -478,7 +478,7 @@ opFUCOMP(uint32_t fetchdat) return 0; } -# ifndef OPS_286_386 +#ifndef OPS_286_386 static int opFUCOMI(uint32_t fetchdat) { diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index d854f83db..d40d70140 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -536,11 +536,11 @@ opFTST(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (ST(0) == 0.0) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else if (ST(0) < 0.0) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; @@ -551,20 +551,20 @@ opFXAM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); #ifdef USE_NEW_DYNAREC if (cpu_state.tag[cpu_state.TOP & 7] == TAG_EMPTY) - cpu_state.npxs |= (C0 | C3); + cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3); #else if (cpu_state.tag[cpu_state.TOP & 7] == 3) - cpu_state.npxs |= (C0 | C3); + cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3); #endif else if (ST(0) == 0.0) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else - cpu_state.npxs |= C2; + cpu_state.npxs |= FPU_SW_C2; if (ST(0) < 0.0) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi)); return 0; @@ -694,7 +694,7 @@ opFPTAN(uint32_t fetchdat) ST(0) = tan(ST(0)); FP_TAG_VALID; x87_push(1.0); - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi)); return 0; @@ -752,13 +752,13 @@ opFPREM(uint32_t fetchdat) temp64 = (int64_t) (ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double) temp64); FP_TAG_VALID; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); if (temp64 & 4) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; if (temp64 & 2) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; if (temp64 & 1) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi)); return 0; @@ -773,13 +773,13 @@ opFPREM1(uint32_t fetchdat) temp64 = (int64_t) (ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double) temp64); FP_TAG_VALID; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); if (temp64 & 4) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; if (temp64 & 2) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; if (temp64 & 1) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi)); return 0; @@ -808,7 +808,7 @@ opFSINCOS(uint32_t fetchdat) ST(0) = sin(td); FP_TAG_VALID; x87_push(cos(td)); - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi)); return 0; @@ -853,7 +853,7 @@ opFSIN(uint32_t fetchdat) cpu_state.pc++; ST(0) = sin(ST(0)); FP_TAG_VALID; - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); return 0; @@ -866,7 +866,7 @@ opFCOS(uint32_t fetchdat) cpu_state.pc++; ST(0) = cos(ST(0)); FP_TAG_VALID; - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); return 0; diff --git a/src/cpu/x87_ops_sf.h b/src/cpu/x87_ops_sf.h index 137919fa9..ea3715c41 100644 --- a/src/cpu/x87_ops_sf.h +++ b/src/cpu/x87_ops_sf.h @@ -240,6 +240,7 @@ sf_FLDCW_a16(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); tempw = geteaw(); @@ -265,6 +266,7 @@ sf_FLDCW_a32(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); tempw = geteaw(); @@ -375,12 +377,13 @@ sf_FRSTOR_a16(uint32_t fetchdat) int offset; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); offset = fpu_load_environment(); for (int n = 0; n < 8; n++) { - tmp.fraction = readmemq(easeg, offset + (n * 10)); - tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + tmp.signif = readmemq(easeg, offset + (n * 10)); + tmp.signExp = readmemw(easeg, offset + (n * 10) + 8); FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); @@ -395,12 +398,13 @@ sf_FRSTOR_a32(uint32_t fetchdat) int offset; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); offset = fpu_load_environment(); for (int n = 0; n < 8; n++) { - tmp.fraction = readmemq(easeg, offset + (n * 10)); - tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + tmp.signif = readmemq(easeg, offset + (n * 10)); + tmp.signExp = readmemw(easeg, offset + (n * 10) + 8); FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); @@ -422,8 +426,8 @@ sf_FNSAVE_a16(uint32_t fetchdat) /* save all registers in stack order. */ for (int m = 0; m < 8; m++) { stn = FPU_read_regi(m); - writememq(easeg, offset + (m * 10), stn.fraction); - writememw(easeg, offset + (m * 10) + 8, stn.exp); + writememq(easeg, offset + (m * 10), stn.signif); + writememw(easeg, offset + (m * 10) + 8, stn.signExp); } #ifdef FPU_8087 @@ -458,8 +462,8 @@ sf_FNSAVE_a32(uint32_t fetchdat) /* save all registers in stack order. */ for (int m = 0; m < 8; m++) { stn = FPU_read_regi(m); - writememq(easeg, offset + (m * 10), stn.fraction); - writememw(easeg, offset + (m * 10) + 8, stn.exp); + writememq(easeg, offset + (m * 10), stn.signif); + writememw(easeg, offset + (m * 10) + 8, stn.signExp); } # ifdef FPU_8087 @@ -524,6 +528,7 @@ sf_FLDENV_a16(uint32_t fetchdat) int tag; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); fpu_load_environment(); @@ -546,6 +551,7 @@ sf_FLDENV_a32(uint32_t fetchdat) int tag; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); fpu_load_environment(); @@ -600,6 +606,8 @@ static int sf_FNOP(uint32_t fetchdat) { FP_ENTER(); + pclog("FNOP.\n"); + FPU_check_pending_exceptions(); cpu_state.pc++; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index 5144062bb..edbd64dcf 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -1,8 +1,8 @@ #define sf_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ static int sf_FADD##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -19,9 +19,9 @@ status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_add(a, use_var, &status); \ + result = extF80_add(a, use_var, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -31,8 +31,8 @@ next_ins: } \ static int sf_FDIV##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -49,9 +49,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_div(a, use_var, &status); \ + result = extF80_div(a, use_var, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -61,8 +61,8 @@ next_ins: } \ static int sf_FDIVR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -79,9 +79,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_div(use_var, a, &status); \ + result = extF80_div(use_var, a, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -91,8 +91,8 @@ next_ins: } \ static int sf_FMUL##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -109,9 +109,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_mul(a, use_var, &status); \ + result = extF80_mul(a, use_var, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -121,8 +121,8 @@ next_ins: } \ static int sf_FSUB##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -139,9 +139,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_sub(a, use_var, &status); \ + result = extF80_sub(a, use_var, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -151,8 +151,8 @@ next_ins: } \ static int sf_FSUBR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -169,9 +169,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_sub(use_var, a, &status); \ + result = extF80_sub(use_var, a, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -181,31 +181,31 @@ next_ins: } // clang-format off -sf_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +sf_FPU(s, float32, 16, temp, geteal(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) #ifndef FPU_8087 -sf_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +sf_FPU(s, float32, 32, temp, geteal(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) #endif -sf_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +sf_FPU(d, float64, 16, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) #ifndef FPU_8087 -sf_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +sf_FPU(d, float64, 32, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) #endif -sf_FPU(iw, uint16_t, 16, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +sf_FPU(iw, uint16_t, 16, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16) #ifndef FPU_8087 -sf_FPU(iw, uint16_t, 32, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +sf_FPU(iw, uint16_t, 32, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16) #endif -sf_FPU(il, uint32_t, 16, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +sf_FPU(il, uint32_t, 16, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32) #ifndef FPU_8087 -sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +sf_FPU(il, uint32_t, 32, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32) #endif - // clang-format on +// clang-format on - static int sf_FADD_st0_stj(uint32_t fetchdat) +static int sf_FADD_st0_stj(uint32_t fetchdat) { floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -218,9 +218,9 @@ sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -234,7 +234,7 @@ sf_FADD_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -247,9 +247,9 @@ sf_FADD_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -264,7 +264,7 @@ sf_FADDP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -277,9 +277,9 @@ sf_FADDP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -296,9 +296,10 @@ sf_FDIV_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -308,9 +309,9 @@ sf_FDIV_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -325,9 +326,10 @@ sf_FDIV_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -337,9 +339,9 @@ sf_FDIV_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -353,9 +355,10 @@ sf_FDIVP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -365,9 +368,9 @@ sf_FDIVP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -384,9 +387,10 @@ sf_FDIVR_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -396,9 +400,9 @@ sf_FDIVR_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -412,9 +416,10 @@ sf_FDIVR_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -424,9 +429,9 @@ sf_FDIVR_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -440,9 +445,10 @@ sf_FDIVRP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -452,9 +458,9 @@ sf_FDIVRP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -471,9 +477,10 @@ sf_FMUL_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -483,9 +490,9 @@ sf_FMUL_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -500,9 +507,10 @@ sf_FMUL_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -512,9 +520,9 @@ sf_FMUL_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -529,9 +537,10 @@ sf_FMULP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -541,9 +550,9 @@ sf_FMULP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -560,9 +569,10 @@ sf_FSUB_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -572,9 +582,9 @@ sf_FSUB_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -589,9 +599,10 @@ sf_FSUB_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -601,9 +612,9 @@ sf_FSUB_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -618,9 +629,10 @@ sf_FSUBP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -630,9 +642,9 @@ sf_FSUBP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -649,9 +661,10 @@ sf_FSUBR_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -661,9 +674,9 @@ sf_FSUBR_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -678,9 +691,10 @@ sf_FSUBR_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -690,9 +704,9 @@ sf_FSUBR_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -707,9 +721,10 @@ sf_FSUBRP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -719,9 +734,9 @@ sf_FSUBRP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -736,9 +751,10 @@ static int sf_FSQRT(uint32_t fetchdat) { floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -746,9 +762,9 @@ sf_FSQRT(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_sqrt(FPU_read_regi(0), &status); + result = extF80_sqrt(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -762,9 +778,10 @@ static int sf_FRNDINT(uint32_t fetchdat) { floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -772,9 +789,9 @@ sf_FRNDINT(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_round_to_int(FPU_read_regi(0), &status); + result = extF80_roundToInt_normal(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index 6b4c1cb62..c4a38b375 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -1,11 +1,12 @@ #define cmp_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ static int sf_FCOM##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a; \ - int rc; \ - struct float_status_t status; \ - optype temp; \ + floatx80 a; \ + int rc; \ + struct softfloat_status_t status; \ + optype temp; \ FP_ENTER(); \ + FPU_check_pending_exceptions(); \ fetch_ea_##a_size(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = rw; \ @@ -14,19 +15,19 @@ clear_C1(); \ if (IS_TAG_EMPTY(0)) { \ FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ - setcc(C0 | C2 | C3); \ + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ goto next_ins; \ } \ status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (is_nan) { \ - rc = float_relation_unordered; \ - float_raise(&status, float_flag_invalid); \ + rc = softfloat_relation_unordered; \ + softfloat_raiseFlags(&status, softfloat_flag_invalid); \ } else { \ - rc = floatx80_compare_two(a, use_var, &status); \ + rc = extF80_compare_normal(a, use_var, &status); \ } \ setcc(FPU_status_word_flags_fpu_compare(rc)); \ - FPU_exception(fetchdat, status.float_exception_flags, 0); \ + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); \ \ next_ins: \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ @@ -35,11 +36,12 @@ next_ins: } \ static int sf_FCOMP##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a; \ - int rc; \ - struct float_status_t status; \ - optype temp; \ + floatx80 a; \ + int rc; \ + struct softfloat_status_t status; \ + optype temp; \ FP_ENTER(); \ + FPU_check_pending_exceptions(); \ fetch_ea_##a_size(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = rw; \ @@ -48,7 +50,7 @@ next_ins: clear_C1(); \ if (IS_TAG_EMPTY(0)) { \ FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ - setcc(C0 | C2 | C3); \ + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ if (is_IA_masked()) \ FPU_pop(); \ \ @@ -57,13 +59,13 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (is_nan) { \ - rc = float_relation_unordered; \ - float_raise(&status, float_flag_invalid); \ + rc = softfloat_relation_unordered; \ + softfloat_raiseFlags(&status, softfloat_flag_invalid); \ } else { \ - rc = floatx80_compare_two(a, use_var, &status); \ + rc = extF80_compare_normal(a, use_var, &status); \ } \ setcc(FPU_status_word_flags_fpu_compare(rc)); \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_pop(); \ \ next_ins: \ @@ -73,46 +75,48 @@ next_ins: } // clang-format off -cmp_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +cmp_FPU(s, float32, 16, temp, geteal(), f32_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f32_isNaN(temp), _32) #ifndef FPU_8087 -cmp_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +cmp_FPU(s, float32, 32, temp, geteal(), f32_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f32_isNaN(temp), _32) #endif -cmp_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +cmp_FPU(d, float64, 16, temp, geteaq(), f64_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f64_isNaN(temp), _64) #ifndef FPU_8087 -cmp_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +cmp_FPU(d, float64, 32, temp, geteaq(), f64_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f64_isNaN(temp), _64) #endif -cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), i32_to_extF80((int32_t)temp), 0, _i16) #ifndef FPU_8087 -cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), i32_to_extF80((int32_t)temp), 0, _i16) #endif -cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), i32_to_extF80(temp), 0, _i32) #ifndef FPU_8087 -cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), i32_to_extF80(temp), 0, _i32) #endif - // clang-format on +// clang-format on - static int sf_FCOM_sti(uint32_t fetchdat) +static int +sf_FCOM_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -123,17 +127,18 @@ next_ins: static int sf_FCOMP_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); } @@ -142,9 +147,9 @@ sf_FCOMP_sti(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); } @@ -157,17 +162,18 @@ next_ins: static int sf_FCOMPP(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); FPU_pop(); @@ -177,9 +183,9 @@ sf_FCOMPP(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(1); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_pop(); } @@ -194,17 +200,18 @@ next_ins: static int sf_FUCOMPP(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); FPU_pop(); @@ -214,9 +221,9 @@ sf_FUCOMPP(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(1); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_pop(); } @@ -227,16 +234,17 @@ next_ins: return 0; } -# ifndef OPS_286_386 +#ifndef OPS_286_386 static int sf_FCOMI_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -248,9 +256,9 @@ sf_FCOMI_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); FPU_write_eflags_fpu_compare(rc); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -260,12 +268,13 @@ next_ins: static int sf_FCOMIP_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -280,9 +289,9 @@ sf_FCOMIP_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); FPU_write_eflags_fpu_compare(rc); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); } @@ -291,30 +300,31 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); return 0; } -# endif +#endif static int sf_FUCOM_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -325,17 +335,18 @@ next_ins: static int sf_FUCOMP_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) FPU_pop(); @@ -344,9 +355,9 @@ sf_FUCOMP_sti(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_pop(); next_ins: @@ -359,12 +370,13 @@ next_ins: static int sf_FUCOMI_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -376,9 +388,9 @@ sf_FUCOMI_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); FPU_write_eflags_fpu_compare(rc); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -388,12 +400,13 @@ next_ins: static int sf_FUCOMIP_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -408,9 +421,9 @@ sf_FUCOMIP_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); FPU_write_eflags_fpu_compare(rc); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_pop(); next_ins: @@ -418,26 +431,28 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); return 0; } -# endif +#endif #endif static int sf_FTST(uint32_t fetchdat) { - int rc; - struct float_status_t status; + const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - rc = floatx80_compare_two(FPU_read_regi(0), Const_Z, &status); + rc = extF80_compare_normal(FPU_read_regi(0), Const_Z, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); @@ -447,45 +462,45 @@ sf_FTST(uint32_t fetchdat) static int sf_FXAM(uint32_t fetchdat) { - floatx80 reg; - int sign; - float_class_t aClass; + floatx80 reg; + int sign; + softfloat_class_t aClass; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; reg = FPU_read_regi(0); - sign = floatx80_sign(reg); + sign = extF80_sign(reg); /* * Examine the contents of the ST(0) register and sets the condition * code flags C0, C2 and C3 in the FPU status word to indicate the * class of value or number in the register. */ if (IS_TAG_EMPTY(0)) { - setcc(C3 | C1 | C0); + setcc(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C3); } else { - aClass = floatx80_class(reg); + aClass = extF80_class(reg); switch (aClass) { - case float_zero: - setcc(C3 | C1); + case softfloat_zero: + setcc(FPU_SW_C1 | FPU_SW_C3); break; - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: // unsupported handled as NaNs - if (floatx80_is_unsupported(reg)) { - setcc(C1); - } else { - setcc(C1 | C0); - } + if (extF80_isUnsupported(reg)) + setcc(FPU_SW_C1); + else + setcc(FPU_SW_C0 | FPU_SW_C1); break; - case float_negative_inf: - case float_positive_inf: - setcc(C2 | C1 | C0); + case softfloat_negative_inf: + case softfloat_positive_inf: + setcc(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2); break; - case float_denormal: - setcc(C3 | C2 | C1); + case softfloat_denormal: + setcc(FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); break; - case float_normalized: - setcc(C2 | C1); + case softfloat_normalized: + setcc(FPU_SW_C1 | FPU_SW_C2); break; } } diff --git a/src/cpu/x87_ops_sf_const.h b/src/cpu/x87_ops_sf_const.h index 0808cbae8..19cc401f5 100644 --- a/src/cpu/x87_ops_sf_const.h +++ b/src/cpu/x87_ops_sf_const.h @@ -3,18 +3,11 @@ */ #define DOWN_OR_CHOP() (fpu_state.cwd & FPU_CW_RC & FPU_RC_DOWN) -static __inline floatx80 -FPU_round_const(const floatx80 a, int adj) -{ - floatx80 result = a; - result.fraction += adj; - return result; -} - static int sf_FLDL2T(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -32,6 +25,7 @@ static int sf_FLDL2E(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -49,6 +43,7 @@ static int sf_FLDPI(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -66,6 +61,7 @@ static int sf_FLDEG2(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -83,6 +79,7 @@ static int sf_FLDLN2(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -100,6 +97,7 @@ static int sf_FLD1(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -117,6 +115,7 @@ static int sf_FLDZ(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) diff --git a/src/cpu/x87_ops_sf_load_store.h b/src/cpu/x87_ops_sf_load_store.h index 228d9fc06..69249016e 100644 --- a/src/cpu/x87_ops_sf_load_store.h +++ b/src/cpu/x87_ops_sf_load_store.h @@ -38,10 +38,10 @@ sf_FILDiw_a16(uint32_t fetchdat) if (cpu_state.abrt) return 1; clear_C1(); - if (!IS_TAG_EMPTY(-1)) { + if (!IS_TAG_EMPTY(-1)) FPU_stack_overflow(fetchdat); - } else { - result = int32_to_floatx80(temp); + else { + result = i32_to_extF80(temp); FPU_push(); FPU_save_regi(result, 0); } @@ -67,7 +67,7 @@ sf_FILDiw_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(temp); + result = i32_to_extF80(temp); FPU_push(); FPU_save_regi(result, 0); } @@ -94,7 +94,7 @@ sf_FILDil_a16(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(templ); + result = i32_to_extF80(templ); FPU_push(); FPU_save_regi(result, 0); } @@ -120,7 +120,7 @@ sf_FILDil_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(templ); + result = i32_to_extF80(templ); FPU_push(); FPU_save_regi(result, 0); } @@ -147,7 +147,7 @@ sf_FILDiq_a16(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int64_to_floatx80(temp64); + result = i64_to_extF80(temp64); FPU_push(); FPU_save_regi(result, 0); } @@ -173,7 +173,7 @@ sf_FILDiq_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int64_to_floatx80(temp64); + result = i64_to_extF80(temp64); FPU_push(); FPU_save_regi(result, 0); } @@ -187,40 +187,36 @@ static int sf_FBLD_PACKED_BCD_a16(uint32_t fetchdat) { floatx80 result; - uint16_t load_reg_hi = 0xffff; - uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); - int64_t load_val = 0ULL; - uint64_t power; - int sign; + uint16_t load_reg_hi; + uint64_t load_reg_lo; + int64_t val64 = 0; + int64_t scale = 1; FP_ENTER(); FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_hi = readmemw(easeg, (cpu_state.eaaddr + 8) & 0xffff); load_reg_lo = readmemq(easeg, cpu_state.eaaddr); - load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - sign = (load_reg_hi & 0x8000) != 0; - load_val = 0ULL; - power = 1; - for (int i = 0; i < 16; i++) { - load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + for (int n = 0; n < 16; n++) { + val64 += ((load_reg_lo & 0x0f) * scale); load_reg_lo >>= 4; - power *= 10; + scale *= 10; } - for (int i = 0; i < 2; i++) { - load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; - load_reg_hi >>= 4; - power *= 10; - } - if (sign) - load_val = -load_val; - result = int64_to_floatx80(load_val); + val64 += ((load_reg_hi & 0x0f) * scale); + val64 += (((load_reg_hi >> 4) & 0x0f) * scale * 10); + + result = (floatx80) i64_to_extF80(val64); + + if (load_reg_hi & 0x8000) + floatx80_chs(result); + FPU_push(); FPU_save_regi(result, 0); } @@ -233,40 +229,36 @@ static int sf_FBLD_PACKED_BCD_a32(uint32_t fetchdat) { floatx80 result; - uint16_t load_reg_hi = 0xffff; - uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); - int64_t load_val = 0ULL; - uint64_t power; - int sign; + uint16_t load_reg_hi; + uint64_t load_reg_lo; + int64_t val64 = 0; + int64_t scale = 1; FP_ENTER(); FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_hi = readmemw(easeg, (cpu_state.eaaddr + 8) & 0xffff); load_reg_lo = readmemq(easeg, cpu_state.eaaddr); - load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - sign = (load_reg_hi & 0x8000) != 0; - load_val = 0ULL; - power = 1; - for (int i = 0; i < 16; i++) { - load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + for (int n = 0; n < 16; n++) { + val64 += ((load_reg_lo & 0x0f) * scale); load_reg_lo >>= 4; - power *= 10; + scale *= 10; } - for (int i = 0; i < 2; i++) { - load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; - load_reg_hi >>= 4; - power *= 10; - } - if (sign) - load_val = -load_val; - result = int64_to_floatx80(load_val); + val64 += ((load_reg_hi & 0x0f) * scale); + val64 += (((load_reg_hi >> 4) & 0x0f) * scale * 10); + + result = (floatx80) i64_to_extF80(val64); + + if (load_reg_hi & 0x8000) + floatx80_chs(result); + FPU_push(); FPU_save_regi(result, 0); } @@ -279,10 +271,10 @@ sf_FBLD_PACKED_BCD_a32(uint32_t fetchdat) static int sf_FLDs_a16(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float32 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -297,8 +289,8 @@ sf_FLDs_a16(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float32_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f32_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -313,10 +305,10 @@ next_ins: static int sf_FLDs_a32(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float32 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -331,8 +323,8 @@ sf_FLDs_a32(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float32_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f32_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -348,10 +340,10 @@ next_ins: static int sf_FLDd_a16(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float64 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -366,8 +358,8 @@ sf_FLDd_a16(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float64_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f64_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -382,10 +374,10 @@ next_ins: static int sf_FLDd_a32(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float64 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -400,8 +392,8 @@ sf_FLDd_a32(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float64_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f64_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -423,10 +415,11 @@ sf_FLDe_a16(uint32_t fetchdat) FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); - result.fraction = readmemq(easeg, cpu_state.eaaddr); - result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + result.signif = readmemq(easeg, cpu_state.eaaddr); + result.signExp = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; + clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); @@ -448,10 +441,11 @@ sf_FLDe_a32(uint32_t fetchdat) FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); - result.fraction = readmemq(easeg, cpu_state.eaaddr); - result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + result.signif = readmemq(easeg, cpu_state.eaaddr); + result.signExp = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; + clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); @@ -484,9 +478,8 @@ sf_FLD_sti(uint32_t fetchdat) FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); if (!is_IA_masked()) goto next_ins; - } else { + } else sti_reg = FPU_read_regi(fetchdat & 7); - } FPU_push(); FPU_save_regi(sti_reg, 0); @@ -500,9 +493,9 @@ next_ins: static int sf_FISTiw_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -516,8 +509,8 @@ sf_FISTiw_a16(uint32_t fetchdat) } } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -535,9 +528,9 @@ next_ins: static int sf_FISTiw_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -550,8 +543,8 @@ sf_FISTiw_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -569,9 +562,9 @@ next_ins: static int sf_FISTPiw_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -584,8 +577,8 @@ sf_FISTPiw_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -606,9 +599,9 @@ next_ins: static int sf_FISTPiw_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -621,8 +614,8 @@ sf_FISTPiw_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -643,9 +636,9 @@ next_ins: static int sf_FISTil_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -658,8 +651,8 @@ sf_FISTil_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -677,9 +670,9 @@ next_ins: static int sf_FISTil_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -692,8 +685,8 @@ sf_FISTil_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -711,9 +704,9 @@ next_ins: static int sf_FISTPil_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -726,8 +719,8 @@ sf_FISTPil_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -748,9 +741,9 @@ next_ins: static int sf_FISTPil_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -763,8 +756,8 @@ sf_FISTPil_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -785,9 +778,9 @@ next_ins: static int sf_FISTPiq_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int64_t save_reg = int64_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -800,8 +793,8 @@ sf_FISTPiq_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i64_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -822,9 +815,9 @@ next_ins: static int sf_FISTPiq_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int64_t save_reg = int64_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -837,8 +830,8 @@ sf_FISTPiq_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i64_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case origial FPU_SW must be kept @@ -859,13 +852,13 @@ next_ins: static int sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - uint16_t save_reg_hi = 0xffff; - uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); - floatx80 reg; - int64_t save_val; - int sign; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; FP_ENTER(); FPU_check_pending_exceptions(); @@ -879,15 +872,15 @@ sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); reg = FPU_read_regi(0); - save_val = floatx80_to_int64(reg, &status); - sign = (reg.exp & 0x8000) != 0; + save_val = extF80_to_i64_normal(reg, &status); + sign = extF80_sign(reg); if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) - status.float_exception_flags = float_flag_invalid; // throw away other flags + softfloat_setFlags(&status, softfloat_flag_invalid); // throw away other flags - if (!(status.float_exception_flags & float_flag_invalid)) { + if (!(status.softfloat_exceptionFlags & softfloat_flag_invalid)) { save_reg_hi = sign ? 0x8000 : 0; save_reg_lo = 0; for (int i = 0; i < 16; i++) { @@ -899,7 +892,7 @@ sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) save_reg_hi += (uint16_t) (save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -923,13 +916,13 @@ next_ins: static int sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - uint16_t save_reg_hi = 0xffff; - uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); - floatx80 reg; - int64_t save_val; - int sign; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; FP_ENTER(); FPU_check_pending_exceptions(); @@ -943,15 +936,15 @@ sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); reg = FPU_read_regi(0); - save_val = floatx80_to_int64(reg, &status); - sign = (reg.exp & 0x8000) != 0; + save_val = extF80_to_i64_normal(reg, &status); + sign = extF80_sign(reg); if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) - status.float_exception_flags = float_flag_invalid; // throw away other flags + softfloat_setFlags(&status, softfloat_flag_invalid); // throw away other flags - if (!(status.float_exception_flags & float_flag_invalid)) { + if (!(status.softfloat_exceptionFlags & softfloat_flag_invalid)) { save_reg_hi = sign ? 0x8000 : 0; save_reg_lo = 0; for (int i = 0; i < 16; i++) { @@ -963,7 +956,7 @@ sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) save_reg_hi += (uint16_t) (save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -988,9 +981,9 @@ next_ins: static int sf_FSTs_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1003,8 +996,8 @@ sf_FSTs_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1022,9 +1015,9 @@ next_ins: static int sf_FSTs_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1037,8 +1030,8 @@ sf_FSTs_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1056,9 +1049,9 @@ next_ins: static int sf_FSTPs_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1071,17 +1064,17 @@ sf_FSTPs_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } // store to the memory might generate an exception, in this case original FPU_SW must be kept swap_values16u(sw, fpu_state.swd); seteal(save_reg); - if (cpu_state.abrt) { + if (cpu_state.abrt) return 1; - } + fpu_state.swd = sw; FPU_pop(); @@ -1094,9 +1087,9 @@ next_ins: static int sf_FSTPs_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1109,8 +1102,8 @@ sf_FSTPs_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1118,6 +1111,7 @@ sf_FSTPs_a32(uint32_t fetchdat) seteal(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1131,9 +1125,9 @@ next_ins: static int sf_FSTd_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1146,8 +1140,8 @@ sf_FSTd_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1165,9 +1159,9 @@ next_ins: static int sf_FSTd_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1180,8 +1174,8 @@ sf_FSTd_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1199,9 +1193,9 @@ next_ins: static int sf_FSTPd_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1215,8 +1209,8 @@ sf_FSTPd_a16(uint32_t fetchdat) } } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1225,6 +1219,7 @@ sf_FSTPd_a16(uint32_t fetchdat) seteaq(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1237,9 +1232,9 @@ next_ins: static int sf_FSTPd_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1252,8 +1247,8 @@ sf_FSTPd_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1261,6 +1256,7 @@ sf_FSTPd_a32(uint32_t fetchdat) seteaq(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1293,8 +1289,8 @@ sf_FSTPe_a16(uint32_t fetchdat) } else { save_reg = FPU_read_regi(0); } - writememq(easeg, cpu_state.eaaddr, save_reg.fraction); - writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + writememq(easeg, cpu_state.eaaddr, save_reg.signif); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.signExp); FPU_pop(); next_ins: @@ -1324,8 +1320,8 @@ sf_FSTPe_a32(uint32_t fetchdat) } else { save_reg = FPU_read_regi(0); } - writememq(easeg, cpu_state.eaaddr, save_reg.fraction); - writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + writememq(easeg, cpu_state.eaaddr, save_reg.signif); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.signExp); FPU_pop(); next_ins: @@ -1365,7 +1361,7 @@ sf_FSTP_sti(uint32_t fetchdat) cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { - FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + FPU_pop(); } else { st0_reg = FPU_read_regi(0); FPU_save_regi(st0_reg, fetchdat & 7); diff --git a/src/cpu/x87_ops_sf_misc.h b/src/cpu/x87_ops_sf_misc.h index 85f42e6d5..0aab2ec08 100644 --- a/src/cpu/x87_ops_sf_misc.h +++ b/src/cpu/x87_ops_sf_misc.h @@ -129,6 +129,7 @@ sf_FFREEP_sti(uint32_t fetchdat) FPU_settagi(X87_TAG_EMPTY, fetchdat & 7); if (cpu_state.abrt) return 1; + FPU_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); diff --git a/src/cpu/x87_ops_sf_trans.h b/src/cpu/x87_ops_sf_trans.h index 5a99abb4c..d5aec0110 100644 --- a/src/cpu/x87_ops_sf_trans.h +++ b/src/cpu/x87_ops_sf_trans.h @@ -1,10 +1,11 @@ static int sf_F2XM1(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -13,7 +14,7 @@ sf_F2XM1(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = f2xm1(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -25,10 +26,11 @@ next_ins: static int sf_FYL2X(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -37,7 +39,7 @@ sf_FYL2X(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fyl2x(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_save_regi(result, 0); } @@ -51,11 +53,12 @@ next_ins: static int sf_FPTAN(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - floatx80 y; - struct float_status_t status; + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -76,12 +79,12 @@ sf_FPTAN(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (ftan(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (floatx80_is_nan(y)) { - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (extF80_isNaN(y)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(y, 0); FPU_push(); FPU_save_regi(y, 0); @@ -89,7 +92,7 @@ sf_FPTAN(uint32_t fetchdat) goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(y, 0); FPU_push(); FPU_save_regi(Const_1, 0); @@ -104,12 +107,13 @@ next_ins: static int sf_FPATAN(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_stack_underflow(fetchdat, 1, 1); @@ -119,7 +123,7 @@ sf_FPATAN(uint32_t fetchdat) b = FPU_read_regi(1); status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fpatan(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_save_regi(result, 0); } @@ -133,11 +137,15 @@ next_ins: static int sf_FXTRACT(uint32_t fetchdat) { - struct float_status_t status; - floatx80 a; - floatx80 b; + struct softfloat_status_t status; + floatx80 a; + floatx80 b; +#if 0 + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +#endif FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); @@ -160,8 +168,8 @@ sf_FXTRACT(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); - b = floatx80_extract(&a, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + b = extF80_extract(&a, &status); + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(b, 0); // exponent FPU_push(); FPU_save_regi(a, 0); // fraction @@ -178,15 +186,16 @@ next_ins: static int sf_FPREM1(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; - uint64_t quotient = 0; - int flags; - int cc; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; + uint64_t quotient = 0; + int flags; + int cc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -198,18 +207,18 @@ sf_FPREM1(uint32_t fetchdat) a = FPU_read_regi(0); b = FPU_read_regi(1); flags = floatx80_ieee754_remainder(a, b, &result, "ient, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { if (flags >= 0) { cc = 0; if (flags) - cc = C2; + cc = FPU_SW_C2; else { if (quotient & 1) - cc |= C1; + cc |= FPU_SW_C1; if (quotient & 2) - cc |= C3; + cc |= FPU_SW_C3; if (quotient & 4) - cc |= C0; + cc |= FPU_SW_C0; } setcc(cc); } @@ -225,15 +234,16 @@ next_ins: static int sf_FPREM(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; - uint64_t quotient = 0; - int flags; - int cc; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; + uint64_t quotient = 0; + int flags; + int cc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -246,18 +256,18 @@ sf_FPREM(uint32_t fetchdat) b = FPU_read_regi(1); // handle unsupported extended double-precision floating encodings flags = floatx80_remainder(a, b, &result, "ient, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { if (flags >= 0) { cc = 0; if (flags) - cc = C2; + cc = FPU_SW_C2; else { if (quotient & 1) - cc |= C1; + cc |= FPU_SW_C1; if (quotient & 2) - cc |= C3; + cc |= FPU_SW_C3; if (quotient & 4) - cc |= C0; + cc |= FPU_SW_C0; } setcc(cc); } @@ -273,10 +283,11 @@ next_ins: static int sf_FYL2XP1(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -285,7 +296,7 @@ sf_FYL2XP1(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fyl2xp1(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 1); FPU_pop(); } @@ -300,13 +311,14 @@ next_ins: static int sf_FSINCOS(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - struct float_status_t status; - floatx80 y; - floatx80 sin_y; - floatx80 cos_y; + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + struct softfloat_status_t status; + floatx80 y; + floatx80 sin_y; + floatx80 cos_y; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -327,10 +339,10 @@ sf_FSINCOS(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fsincos(y, &sin_y, &cos_y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(sin_y, 0); FPU_push(); FPU_save_regi(cos_y, 0); @@ -346,10 +358,11 @@ next_ins: static int sf_FSCALE(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -357,8 +370,8 @@ sf_FSCALE(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_scale(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + result = extF80_scale(FPU_read_regi(0), FPU_read_regi(1), &status); + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -371,10 +384,11 @@ next_ins: static int sf_FSIN(uint32_t fetchdat) { - floatx80 y; - struct float_status_t status; + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -385,10 +399,10 @@ sf_FSIN(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fsin(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(y, 0); next_ins: @@ -400,10 +414,11 @@ next_ins: static int sf_FCOS(uint32_t fetchdat) { - floatx80 y; - struct float_status_t status; + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -414,10 +429,10 @@ sf_FCOS(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fcos(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(y, 0); next_ins: