mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
395 lines
12 KiB
395 lines
12 KiB
// TITLE("Convert Single Floating To Long")
|
|
//++
|
|
//
|
|
// Copyright (c) 1993 IBM Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// convert.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements single floating IEEE conversion to long
|
|
// with directed rounding and fraction extraction routines.
|
|
//
|
|
// Author:
|
|
//
|
|
// Curtis R. Fawcett (crf) 15-Oct-1993
|
|
//
|
|
// Environment:
|
|
//
|
|
// User mode only.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Curtis R. Fawcett (crf) 19-Jan-1994 Removed register names
|
|
// as requested
|
|
//
|
|
//--
|
|
//
|
|
// Parameter Register Usage:
|
|
//
|
|
// f.1 - Input for FP to long values
|
|
// r.3 - Input for long to FP values
|
|
//
|
|
// Local General Purpose Register Usage:
|
|
//
|
|
// r.0 - Save Link Register
|
|
// r.3 - Fixed result pointer
|
|
// r.3 - Function return
|
|
// r.4 - GPR temporary storage
|
|
// r.5 - GPR temporary storage
|
|
// r.6 - GPR temporary storage
|
|
// r.7 - GPR temporary storage
|
|
// r.8 - GPR temporary storage
|
|
// r.10 - GPR temporary storage
|
|
//
|
|
// Local Floating-Point Register Usage:
|
|
//
|
|
// f.1 - FP function return
|
|
// f.2 - Save floating point status
|
|
// f.3 - FPR temporary storage
|
|
// f.4 - Magic number value
|
|
// f.13 - Save input value around call
|
|
//
|
|
|
|
#include "kxppc.h"
|
|
|
|
//
|
|
// Define local values
|
|
//
|
|
.set TRUE,1
|
|
.set FALSE,0
|
|
//
|
|
// Define temporary storage
|
|
//
|
|
.struct 0
|
|
.align 3
|
|
TMPSTR:
|
|
.space 8
|
|
FLTSTR:
|
|
.space 8
|
|
STEND:
|
|
|
|
//
|
|
// Define Magic conversion numbers
|
|
//
|
|
.data
|
|
DOTDATA:
|
|
.align 3
|
|
MNUM:
|
|
.word 0x80000000,0x43300000 // Single to Long Magic Number
|
|
|
|
//
|
|
// BOOL
|
|
// eFraction (
|
|
// IN FLOAT Value
|
|
// );
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// The following routine extracts the fractional part of a single
|
|
// floating value.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Value (f.1) - Supplies the floating value whose fraction is
|
|
// extracted.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The fraction value is returned as the function value.
|
|
//
|
|
//--
|
|
//
|
|
// Define the entry point
|
|
//
|
|
SPECIAL_ENTRY(eFraction)
|
|
mflr r.0 // Save the current link register
|
|
PROLOGUE_END(eFraction)
|
|
//
|
|
// Perform the extraction
|
|
//
|
|
mffs. f.2 // Get the current FP status
|
|
bf 6,ALLCLR // Jump on no floating point exception
|
|
stfd f.2,TMPSTR-STEND(r.sp) // Save FP status in memory
|
|
lwz r.10,TMPSTR-STEND(r.sp) // Get FP status into integer register
|
|
lis r.11,0xfe07 // Create mask with VXSNAN, VXISI, VXIDI, VXZDZ, VXIMZ,
|
|
ori r.11,r.11,0xf8ff // VXVC, VXSOFT, VXSQRT, and VXCVI off
|
|
and r.10,r.10,r.11 // Turn off VX bits in FP status
|
|
stw r.10,TMPSTR-STEND(r.sp) // Put new FP status back in memory
|
|
lfd f.3,TMPSTR-STEND(r.sp) // Get new FP status in floating point register
|
|
mtfsf 0xff,f.3 // Set new FP status
|
|
ALLCLR:
|
|
fctiwz. f.3,f.1 // Convert to integer (rnd to 0)
|
|
mtfsf 0xff,f.2 // Restore FP status
|
|
bt 6,ERREXT1 // Jump on flting pnt exception
|
|
stfd f.3,TMPSTR-STEND(r.sp) // Store the converted value
|
|
lwz r.3,TMPSTR-STEND(r.sp) // Fetch the integer
|
|
fmr f.13,f.1 // Save original FP value
|
|
bl ..CnvLongToSingleFP // Call conversion routine
|
|
mtlr r.0 // Restore the link register
|
|
fsub f.1,f.13,f.1 // Subtract to extract fraction
|
|
b EXIT1 // Jump to return
|
|
ERREXT1:
|
|
li r.5,0 // Set function return of zero
|
|
stw r.5,TMPSTR-STEND(r.sp) // Store function return value
|
|
lfs f.1,TMPSTR-STEND(r.sp) // Set function return value
|
|
EXIT1:
|
|
LEAF_EXIT(eFraction)
|
|
//++
|
|
//
|
|
// BOOL
|
|
// bFToFixRound (
|
|
// IN FLOAT Value,
|
|
// OUT PFIX Fixed
|
|
// );
|
|
//
|
|
// Routine Description: >>> not used? <<<
|
|
//
|
|
// The following routine converted single floating value to a long
|
|
// with rounding toward nearest.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Value (f.1) - Supplies the floating value to be converted to long.
|
|
//
|
|
// Fixed (r.4) - Supplies a pointer to a variable that receives the
|
|
// converted value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// A value of TRUE is returned if the conversion is successful.
|
|
// Otherwise, a value of FALSE is returned.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(bFToFixRound)
|
|
//
|
|
mffs. f.2 // Save the current FP status
|
|
lwz r.4,0(r.3) // Get value stored at FIXDRES
|
|
stfs f.1,0(r.3) // Store FP value
|
|
lwz r.5,0(r.3) // Get FP value in integer unit
|
|
li r.6,0x4 // Get bias base value
|
|
slwi r.6,r.6,23 // Create bias value
|
|
add r.7,r.5,r.6 // Bias the FP value
|
|
stw r.7,0(r.3) // Saved the biased FP value
|
|
xor. r.8,r.5,r.7 // Check for sign change
|
|
blt ERREXT2 // Jump if error occurs
|
|
//
|
|
lfs f.1,0(r.3) // Get bias FP value
|
|
bf 6,ALLCLR2 // Jump if no inexact set
|
|
stfd f.2,TMPSTR-STEND(r.sp) // Save FP status in memory
|
|
lwz r.10,TMPSTR-STEND(r.sp) // Get FP status into integer register
|
|
lis r.11,0xfe07 // Create mask with VXSNAN, VXISI, VXIDI, VXZDZ, VXIMZ,
|
|
ori r.11,r.11,0xf8fc // VXVC, VXSOFT, VXSQRT, and VXCVI off, RN=00
|
|
and r.10,r.10,r.11 // Turn off VX bits in FP status, set RN=00
|
|
stw r.10,TMPSTR-STEND(r.sp) // Put new FP status back in memory
|
|
lfd f.3,TMPSTR-STEND(r.sp) // Get new FP status in floating point register
|
|
mtfsf 0xff,f.3 // Set new FP status
|
|
ALLCLR2:
|
|
fctiw. f.1,f.1 // Get converted integer value
|
|
mtfsf 0xff,f.2 // Restore FP status
|
|
bt 6,ERREXT2 // Jump on flting pnt exception
|
|
stfd f.1,TMPSTR-STEND(r.sp) // Store the converted integer
|
|
lwz r.4,TMPSTR-STEND(r.sp) // Fetch result from stored value
|
|
li r.8,TRUE // Return true for function val
|
|
b EXIT2 // Jump to return
|
|
ERREXT2:
|
|
li r.8,FALSE // Return False for function val
|
|
EXIT2:
|
|
stw r.4,0(r.3) // Restore contents of FIXDRES
|
|
mr r.3,r.8 // Set the function return
|
|
LEAF_EXIT(bFToFixRound)
|
|
|
|
//++
|
|
//
|
|
// BOOL
|
|
// bFToLRound (
|
|
// IN FLOAT Value,
|
|
// OUT PLONG Long
|
|
// );
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// The following routine converted single floating value to a long
|
|
// with rounding toward nearest.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Value (f1) - Supplies the floating value to be converted to long.
|
|
//
|
|
// Long (r4) - Supplies a pointer to a variable that receives the
|
|
// converted value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// A value of TRUE is returned if the conversion is successful.
|
|
// Otherwise, a value of FALSE is returned.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(bFToLRound)
|
|
//
|
|
mffs. f.2 // Save the current FP status
|
|
bf 6,ALLCLR3 // Jump if no inexact set
|
|
stfd f.2,TMPSTR-STEND(r.sp) // Save FP status in memory
|
|
lwz r.10,TMPSTR-STEND(r.sp) // Get FP status into integer register
|
|
lis r.11,0xfe07 // Create mask with VXSNAN, VXISI, VXIDI, VXZDZ, VXIMZ,
|
|
ori r.11,r.11,0xf8fc // VXVC, VXSOFT, VXSQRT, and VXCVI off, RN=00
|
|
and r.10,r.10,r.11 // Turn off VX bits in FP status, set RN=00
|
|
stw r.10,TMPSTR-STEND(r.sp) // Put new FP status back in memory
|
|
lfd f.3,TMPSTR-STEND(r.sp) // Get new FP status in floating point register
|
|
mtfsf 0xff,f.3 // Set new FP status
|
|
ALLCLR3:
|
|
fctiw. f.1,f.1 // Get converted integer value
|
|
mtfsf 0xff,f.2 // Restore FP status
|
|
bt 6,ERREXT3 // Jump on flting pnt exception
|
|
stfd f.1,TMPSTR-STEND(r.sp) // Store the converted integer
|
|
lwz r.0,TMPSTR-STEND(r.sp) // Fetch result from stored value
|
|
stw r.0,0(r.4) // Store the converted result
|
|
li r.3,TRUE // Return true for function val
|
|
b EXIT3 // Jump to return
|
|
ERREXT3:
|
|
li r.3,FALSE // Return False for function val
|
|
EXIT3:
|
|
LEAF_EXIT(bFToLRound)
|
|
|
|
//++
|
|
//
|
|
// BOOL
|
|
// bFToLTrunc (
|
|
// IN FLOAT Value,
|
|
// OUT PLONG Long
|
|
// );
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// The following routine converted single floating value to a long
|
|
// with rounding toward zero.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Value (f1) - Supplies the floating value to be converted to long.
|
|
//
|
|
// Long (r4) - Supplies a pointer to a variable that receives the
|
|
// converted value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// A value of TRUE is returned if the conversion is successful.
|
|
// Otherwise, a value of FALSE is returned.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(bFToLTrunc)
|
|
//
|
|
mffs. f.2 // Save the current FP status
|
|
stfd f.2,TMPSTR-STEND(r.sp) // Save FP status in memory
|
|
lwz r.10,TMPSTR-STEND(r.sp) // Get FP status into integer register
|
|
lis r.11,0xfe07 // Create mask with VXSNAN, VXISI, VXIDI, VXZDZ, VXIMZ,
|
|
ori r.11,r.11,0xf8ff // VXVC, VXSOFT, VXSQRT, and VXCVI off
|
|
and r.10,r.10,r.11 // Turn off VX bits in FP status
|
|
stw r.10,TMPSTR-STEND(r.sp) // Put new FP status back in memory
|
|
lfd f.3,TMPSTR-STEND(r.sp) // Get new FP status in floating point register
|
|
mtfsf 0xff,f.3 // Set new FP status
|
|
ALLCLR4:
|
|
fctiwz. f.1,f.1 // Get converted integer value, round to zero
|
|
mtfsf 0xff,f.2 // Restore FP status
|
|
bt 6,ERREXT4 // Jump on flting pnt exception
|
|
stfd f.1,TMPSTR-STEND(r.sp) // Store the converted integer
|
|
lwz r.0,TMPSTR-STEND(r.sp) // Fetch result from stored value
|
|
stw r.0,0(r.4) // Store the converted result
|
|
li r.3,TRUE // Return true for function val
|
|
b EXIT4 // Jump to return
|
|
ERREXT4:
|
|
li r.3,FALSE // Return False for function val
|
|
EXIT4:
|
|
LEAF_EXIT(bFToLTrunc)
|
|
|
|
//++
|
|
// Name: CnvLongToSingleFP
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// The following routine converts a long to a single precision
|
|
// floating point number.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Inval (r.3) - Supplies the integer value to be converted
|
|
//
|
|
// Return Value:
|
|
//
|
|
// OUTVAL (f.1) - The converted value is returned in this register
|
|
//
|
|
//--
|
|
LEAF_ENTRY(CnvLongToSingleFP)
|
|
//
|
|
lwz r.12,[toc].data(r.toc) // Get base data pointer
|
|
lfd f.4,MNUM-DOTDATA(r.12) // Load magic number
|
|
stfd f.4,FLTSTR-STEND(r.sp) // Load magic number
|
|
xoris r.3,r.3,32768 // Continue integer conversion
|
|
stw r.3,FLTSTR-STEND(r.sp) // Store intermediate result
|
|
lfd f.1,FLTSTR-STEND(r.sp) // Load result as double FP
|
|
fsub f.1,f.1,f.4 // Subtract to do conversion
|
|
frsp f.1,f.1 // Round to single precision
|
|
//
|
|
// Return to caller
|
|
//
|
|
LEAF_EXIT(CnvLongToSingleFP)
|
|
|
|
//++
|
|
//
|
|
// LONG
|
|
// bFToLRound (
|
|
// IN FLOAT Value,
|
|
// IN PLONG Long
|
|
// );
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Multiplies a float by a long and converts the result to a long
|
|
// with round towards zero.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Value (f.1) - Supplies the floating value to be converted to long.
|
|
//
|
|
// Long (r.4) - Supplies a pointer to a variable that receives the
|
|
// converted value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Long (r.3) - Supplies the result to the caller.
|
|
//
|
|
//--
|
|
|
|
// Matt Holle
|
|
// For now, I'm commenting this out for a couple of reasons:
|
|
// 1. We're having some problems in daytona, and I'd like to
|
|
// use the portable version for a while.
|
|
// 2. The portable version will probably be as fast as this
|
|
// assembly version, and will probably be even faster on
|
|
// future parts that have different (better) floating-point
|
|
// pipelines.
|
|
//
|
|
// LEAF_ENTRY(lCvtWithRound)
|
|
//
|
|
// lwz r.12,[toc].data(r.toc) // Get base data pointer
|
|
// lfd f.4,MNUM-DOTDATA(r.12) // Load magic number
|
|
// stfd f.4,FLTSTR-STEND(r.sp) // Save magic number as temp
|
|
// xoris r.4,r.4,32768 // Continue integer conversion
|
|
// stw r.4,FLTSTR-STEND(r.sp) // Store intermediate result
|
|
// lfd f.2,FLTSTR-STEND(r.sp) // Load result as double FP
|
|
// fsub f.2,f.2,f.4 // Subtract to do conversion
|
|
//
|
|
// At this point, f.1 contains the floating input argument
|
|
// and f.2 contains the long converted to float.
|
|
//
|
|
// fmul f.2, f.1, f.2 // Perform the multiplication
|
|
// fctiwz f.2, f.2 // Cvt to int, round toward 0
|
|
// stfd f.2,TMPSTR-STEND(r.sp) // Store rounded integer value
|
|
// lwz r.3,TMPSTR-STEND(r.sp) // Get result for caller
|
|
//
|
|
// LEAF_EXIT(lCvtWithRound)
|