// TITLE("Floating Point Control") //++ // // Copyright (c) 1992 Digital Equipment Corporation // // Module Name: // // fpctrl.s // // Abstract: // // This module implements routines that control floating point // operations. // // Author: // // Thomas Van Baak (tvb) 31-Aug-1992 // // Environment: // // Any mode. // // Revision History: // //-- #include "ksalpha.h" // // Define call frame used to exchange a floating point and integer register. // .struct 0 FpCr: .space 8 // fpcr value .space 8 // ensure 16-byte stack alignment FpFrameLength: // length of stack frame SBTTL("Get Hardware Floating Point Control Register") //++ // // ULONGLONG // _get_fpcr ( // VOID // ) // // Routine Description: // // This function obtains the current FPCR value. // // Arguments: // // None. // // Return Value: // // The current value of the FPCR is returned as the function value. // //-- NESTED_ENTRY(_get_fpcr, FpFrameLength, ra) lda sp, -FpFrameLength(sp) // allocate stack frame PROLOGUE_END excb // wait for all pending traps mf_fpcr f0, f0, f0 // get current fpcr excb // block against new traps stt f0, FpCr(sp) // store floating register in order to ldq v0, FpCr(sp) // load integer register with fpcr lda sp, FpFrameLength(sp) // deallocate stack frame ret zero, (ra) // return .end _get_fpcr SBTTL("Set Hardware Floating Point Control Register") //++ // // VOID // _set_fpcr ( // ULONGLONG FpcrValue // ) // // Routine Description: // // This function sets a new value in the FPCR. // // Arguments: // // FpcrValue (a0) - Supplies the new value for the FPCR. // // Return Value: // // None. // //-- NESTED_ENTRY(_set_fpcr, FpFrameLength, ra) lda sp, -FpFrameLength(sp) // allocate stack frame PROLOGUE_END stq a0, FpCr(sp) // store integer register in order to ldt f0, FpCr(sp) // load floating register with fpcr excb // wait for all pending traps mt_fpcr f0, f0, f0 // set new fpcr excb // block against new traps lda sp, FpFrameLength(sp) // deallocate stack frame ret zero, (ra) // return .end _set_fpcr SBTTL("Get Software Floating Point Control and Status Register") //++ // // ULONG // _get_softfpcr ( // VOID // ) // // Routine Description: // // This function obtains the current software FPCR value. // // Arguments: // // None. // // Return Value: // // The current value of the software FPCR is returned as the function value. // //-- LEAF_ENTRY(_get_softfpcr) GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 ldl v0, TeSoftFpcr(v0) // get current software fpcr value ret zero, (ra) // return .end _get_softfpcr SBTTL("Set Software Floating Point Control and Status Register") //++ // // VOID // _set_softfpcr ( // ULONG SoftFpcrValue // ) // // Routine Description: // // This function sets a new value in the software FPCR. // // Arguments: // // SoftFpcrValue (a0) - Supplies the new value for the software FPCR. // // Return Value: // // None. // //-- LEAF_ENTRY(_set_softfpcr) GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 stl a0, TeSoftFpcr(v0) // store new software fpcr value ret zero, (ra) // return .end _set_softfpcr SBTTL("Set New Floating Control Register Value") //++ // // ULONG // _ctrlfp ( // IN ULONG newctrl, // IN ULONG mask // ) // // Routine Description: // // For Alpha AXP this function sets nothing. It returns the current // rounding mode and the current IEEE exception disable mask in the // fp32 internal control word format. // // Arguments: // // newctrl (a0) - Supplies the new control bits to be set. // // mask (a1) - Supplies the mask of bits to be set. // // Return Value: // // oldctrl (v0) - Returns the old value of the control bits. // // //-- NESTED_ENTRY(_ctrlfp, FpFrameLength, ra) lda sp, -FpFrameLength(sp) // allocate stack frame PROLOGUE_END // // Get the dynamic rounding mode from the FPCR. // excb // wait for all pending traps mf_fpcr f0, f0, f0 // get current fpcr excb // block against new traps stt f0, FpCr(sp) // store floating register in order to ldq t0, FpCr(sp) // load integer register with fpcr srl t0, 58, t0 // shift rounding mode to low end and t0, 0x3, t0 // isolate rounding mode bits sll t0, 58 - 32, t0 // shift to internal cw format // // Get the IEEE exception mask bits and status bits from the software FPCR. // GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 ldl v0, TeSoftFpcr(v0) // get current software fpcr value xor v0, 0x3e, v0 // convert enable bits to disable bits or v0, t0, v0 // merge with current rounding mode lda sp, FpFrameLength(sp) // deallocate stack frame ret zero, (ra) // return .end _ctrlfp SBTTL("Get IEEE Sticky Status Bits") //++ // // ULONG // _statfp ( // VOID // ) // // Routine Description: // // This function gets the IEEE sticky status bits from the software FPCR. // // Arguments: // // None. // // Return Value: // // The current value of the status word is returned as the function value. // //-- LEAF_ENTRY(_statfp) GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 ldl v0, TeSoftFpcr(v0) // get current software fpcr value ret zero, (ra) // return .end _statfp SBTTL("Clear IEEE Sticky Status Bits") //++ // // ULONG // _clrfp ( // VOID // ) // // Routine Description: // // This function clears the IEEE sticky status bits in the software FPCR. // // Arguments: // // None. // // Return Value: // // The previous value of the status word is returned as the function value. // //-- LEAF_ENTRY(_clrfp) GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 ldl t0, TeSoftFpcr(v0) // get current software fpcr value bic t0, 0x3e0000, t1 // clear status bits stl t1, TeSoftFpcr(v0) // store new software fpcr value mov t0, v0 // get previous value ret zero, (ra) // return .end _clrfp SBTTL("Set IEEE Sticky Status Bits") //++ // // VOID // _set_statfp ( // IN ULONG sw // ) // // Routine Description: // // This function sets a IEEE sticky status bit in the software FPCR. // // Arguments: // // sw (a0) - Supplies the status bits to be set. // // Return Value: // // None. // //-- LEAF_ENTRY(_set_statfp) GET_THREAD_ENVIRONMENT_BLOCK // get Teb address in v0 ldl t0, TeSoftFpcr(v0) // get current software fpcr value or t0, a0, t0 // set status bit(s) stl t0, TeSoftFpcr(v0) // store new software fpcr value ret zero, (ra) // return .end _set_statfp SBTTL("Convert Signal NaN to Quiet NaN") //++ // // double // _nan2qnan ( // IN double x // ) // // Routine Description: // // This function converts a signaling NaN to a quiet NaN without causing // a hardware trap. // // Arguments: // // x (f16) - Supplies the signal NaN value to be converted. // // Return Value: // // The quiet NaN value is returned as the function value. // //-- NESTED_ENTRY(_nan2qnan, FpFrameLength, ra) lda sp, -FpFrameLength(sp) // allocate stack frame PROLOGUE_END stt f16, FpCr(sp) // store floating register in order to ldq t0, FpCr(sp) // load integer register ldiq t1, (1 << 51) // get NaN bit or t0, t1, t0 // convert NaN to QNaN stq t0, FpCr(sp) // store integer register in order to ldt f0, FpCr(sp) // load floating register lda sp, FpFrameLength(sp) // deallocate stack frame ret zero, (ra) // return .end _nan2qnan