fpfp
Purpose
Performs ANSI/IEEE floating-point operations.
Library
Floating-Point Library (libfp.a)(1)
IEEE Support Library (libieee.a)
Syntax
#include <sys/FP.h>
Description
The fpfp subroutines perform floating-point operations
that support ANSI/IEEE standard 754-1985 for binary
floating-point arithmetic. This section assumes that you
are familiar with the details of this standard.
The fpfp package supplies six abstract registers, each of
which can hold a single-precision (FP_FLOAT) or double-
precision (FP_DOUBLE) floating-point value. It also pro-
vides a status register that controls and reflects the
result of the floating-point operations.
This interface is used by compilers to implement
expressions that involve floating-point values. It is
not intended to be used directly by user programs. By
accessing the floating-point routines through a system-
defined table, programs can transparently access either
software floating-point routines, or a hardware floating-
point processor, if one is installed in the system. The
following hardware floating-point processors are sup-
ported:
o Floating-Point Accelerator option
o Advanced Floating-Point Accelerator option
o Advanced Processor Card with a Motorola 68881 chip
(APC/881).
On the RT PC, floating-point operations can be accessed
in any of three modes:
---------------
(1) The libfp.a library contains subroutines that implement the
floating-point operations in software. This library is not
normally linked into user programs. Instead, the table-driven
mechanism described under "Table-Driven Interface" is normally gen-
erated by language compilers.
Emulation Mode
Floating-point operations are emulated by software.
To use emulation mode, a program must explicitly
call the subroutines described under "Subroutines,"
and the subroutines in the Floating-Point Library
(libfp.a) must be linked with it using the cc or ld
command. The use of this mode is discouraged.
Direct Mode
Instructions are issued directly to the hardware
floating-point processor, yielding greater perform-
ance than either of the other modes. This mode is
available for the Floating-Point Accelerator and
Advanced Floating-Point Accelerator only. To use
direct mode, compile your program with directly by
compiling it with fcc or cc -f, instead of using the
regular cc command. &fpa2dmains. If your system
configuration includes the APC and the Advanced
Floating-Point Accelerator, then you can also use
cc -f2 to have the compiler use the direct memory
access (DMA). &fpa2dmaoff. A program compiled for
direct mode floating point will run properly only if
the correct hardware floating-point configuration is
installed.
Compatible Mode
Floating-point operations are invoked by calling
subroutines in the kernel segment that either issue
instructions to the floating-point processor, if one
is present, or simulate the operations in software,
if not. The RT PC C and FORTRAN compilers select
compatible mode by default, so that programs com-
piled with the default options will run properly
whether or not a floating-point processor is
installed. This is the preferred mode, except for
cases in which the greater performance of direct
mode is essential.
The remainder of this section gives details about compat-
ible mode.
For more information about the cc and fcc commands, see
the discussion of the cc command in AIX Operating System
Commands Reference.
Note: Although it is possible to access the hardware
floating-point registers directly, doing so is strongly
discouraged because this makes programs hardware-
dependent. Programs that use compatible mode are inde-
pendent not only of the characteristics of the
floating-point hardware, but of whether a hardware
floating-point processor is installed at all.
TABLE-DRIVEN INTERFACE
The primary interface to the compatible-mode subroutines
is through a table that is located in the kernel segment.
This table contains pointers to each of the compatible-
mode subroutines. User processes have read-only access
to this part of the kernel segment so that a simple sub-
routine call can be made, avoiding the overhead of per-
forming a system call.
Although not recommended, these subroutines can be refer-
enced directly by C programs. They must be invoked
through the external array _fpfpf, which contains
pointers to the subroutines. This array is indexed by
values of the FPFPI enumeration data type.
For example, the C code to read the status register is:
FP_STATUS fpstat;
. . .
*((unsigned *)&fpstat) = (*(unsigned (*) ( ))_fpfpf[(int)FP_getst]) ( );
Note that the subroutine _FPgetst is invoked by indexing
the _fpfpf array with the FP_getst enumeration constant.
The following example adds double values in registers 4
and 5, stores the result in register 4, and then returns
the result as well:
FP_DOUBLE drslt;
. . .
*((FP_DOUBLE *)&drslt) = (*(FP_DOUBLE (*) ( ))_fpfpf[(int)FP_add])(4, 5);
The FPFPI enumeration data type is defined in the
sys/fpfpi.h header file, and it contains the following
values:
FP_rdf, FP_rdd, FP_i2f, FP_i2d,
FP_cpf, FP_cpfi, FP_cpd, FP_cpdi,
FP_f2d, FP_f2di, FP_d2f, FP_d2fi,
FP_ngf, FP_ngfi, FP_ngd, FP_ngdi,
FP_abf, FP_abfi, FP_abd, FP_abdi,
FP_ntf, FP_ntfi, FP_ntd, FP_ntdi,
FP_rnf, FP_rnfi, FP_rnd, FP_rndi,
FP_trf, FP_trfi, FP_trd, FP_trdi,
FP_flf, FP_flfi, FP_fld, FP_fldi,
FP_cmf, FP_cmfi, FP_cmd, FP_cmdi,
FP_adf, FP_adfi, FP_add, FP_addi,
FP_sbf, FP_sbfi, FP_sbd, FP_sbdi,
FP_mlf, FP_mlfi, FP_mld, FP_mldi,
FP_dvf, FP_dvfi, FP_dvd, FP_dvdi,
FP_rmf, FP_rmfi, FP_rmd, FP_rmdi,
FP_sqf, FP_sqfi, FP_sqd, FP_sqdi,
FP_csf, FP_cfs, FP_csd, FP_cds,
FP_getst, FP_setst, FP_lmr, FP_smr,
FP_tan, FP_atan, FP_2xm1, FP_yl2x,
FP_ylp1, FP_d2f2, FP_f2d2,
FP_add3, FP_adf3, FP_sbd3, FP_sbf3,
FP_mld3, FP_mlf3, FP_dvd3, FP_dvf3,
FP_bsin, FP_bsini, FP_bcos, FP_bcosi,
FP_btan, FP_btani, FP_bexp, FP_bexpi,
FP_batan, FP_batani, FP_bacos, FP_bacosi,
FP_basin, FP_basini, FP_blog, FP_blogi,
FP_blog10, FP_blog10i, FP_blogb, FP_blogbi,
FP_batan2, FP_batan2i, FP_bscalbi,
FP_bmodf, FP_bmodfi, FP_bmodd, FP_bmoddi,
The operations named FP_xxxx in the preceding table cor-
respond to the subroutines named _FPxxxx in "Subrou-
tines."
Note that the sys/FP.h header file #includes all of the
other header files required by these floating-point rou-
tines. Therefore, your programs need to #include only
this one file.
FIXED ENTRY POINTS
In order to minimize the overhead of calling the
floating-point routines that are used most frequently, an
alternate interface that uses a nonstandard calling
sequence is available for some of the operations.
Because this is a nonstandard interface, you should not
attempt to use it in programs written in high-level lan-
guages. Use this interface in assembler language pro-
grams instead.
These entry points are located at fixed locations in low
memory. This fact allows programs to branch directly to
the routines with a balax instruction instead of using
the table-driven interface, avoiding four 032 Micro-
processor instructions that set up the constant pool
pointer and get the address of the routine indirectly.
The subroutines are the same as those described under
"Subroutines," except that the first parameter is passed
in general-purpose register 2 of the 032 Microprocessor,
and the second parameter is passed in register 3 (for a
register number or a float immediate value) or in regis-
ters 3 and 4 (for a double immediate value).
The following table lists the address of each fixed entry
point and the 032 Microprocessor general-purpose regis-
ters that are modified. The Multiplier Quotient (MQ)
register may also be modified. Other registers need not
be saved before calling the routine.
Entry Registers
Operation Point Modified
_FPrdf 0x1000 2 3
_FPrdd 0x1040 2 3
_FPcpf 0x1080 2 3
_FPcpfi 0x10C0 2 3
_FPcpd 0x1100 2 3
_FPcpdi 0x1140 2 3 4
_FPf2d 0x1180 0 2 3
_FPf2di 0x11C0 0 2 3
Entry Registers
Operation Point Modified
_FPd2f 0x1200 0 2 3
_FPd2fi 0x1240 0 2 3 4
_FPadf 0x1280 2 3
_FPadfi 0x12C0 2 3
_FPadd 0x1300 2 3
_FPaddi 0x1340 2 3 4 5
_FPsbf 0x1380 2 3
_FPsbfi 0x13C0 2 3
_FPsbd 0x1400 2 3
_FPsbdi 0x1440 2 3 4 5
_FPmlf 0x1480 2 3
_FPmlfi 0x14C0 2 3
_FPmld 0x1500 2 3
_FPmldi 0x1540 2 3 4 5
_FPdvf 0x1580 2 3
_FPdvfi 0x15C0 2 3
_FPdvd 0x1600 2 3
_FPdvdi 0x1640 2 3 4 5
_FPgetst 0x1680 2 3
Example
The following assembler subroutine adds 1.0 and 2.0 in
single precision and returns the result. The subroutine
can be called from a C-language program. See "Parame-
ters" about specifying whether or not a floating-point
operation returns the result.
.set NORESULT,0x08
.text
.globl .add12
.add12:
cal 1,-44(1)
stm 14,0(1) # Save 032 registers 14 and 15
lr 14,0
# Load 2.0 into float register 0; don't return the result
cau 3,0x4000(0) # Specify 2.0 as second parameter
balax 0x10C0 # FP_cpfi - copy float immediate
lis 2,0|NORESULT # Specify float reg 0 as first parameter;
# don't return the result
# Add 1.0 to float register 0; return the result
cau 3,0x3F80(0) # Specify 1.0 as second parameter
balax 0x12C0 # FP_adfi - add float immediate
lis 2,0 # Specify float reg 0 as first parameter;
# DO return the result
# The result is now in 032 register 2
# Return the result in register 2 (C-language calling convention)
lm 14,0(1)
brx 15
cal 1,44(1)
.data 3
.globl _add12
_add12 .long .add12
PARAMETERS
The following parameter declarations apply to all of the
floating-point subroutines:
int r1, r2, r3;
int ival;
FP_FLOAT fval;
FP_DOUBLE dval;
unsigned char *dec;
FP_STATUS status;
The r1, r2, and r3 parameters are integers in the range 0
to 5, denoting one of the six abstract floating-point
registers.
In addition, the r1 parameter can be logically OR-ed with
the value NORETBIT, called the no-result flag, which
permits greater performance by suppressing the return
value from the subroutine when it is not needed imme-
diately. (NORETBIT is defined in the sys/FP.h header
file.) This allows the central processor and a floating-
point processor to operate concurrently: after issuing a
request to the floating-point processor, the central
processor normally waits for it to finish the operation
and return the result. If the no-result flag is set,
then the central processor does not wait, but continues
running while the floating-point processor performs the
requested operation. The value returned by an operation
is undefined if the no-result flag is set.
SUBROUTINES
The following subroutines are grouped by function. The
subroutine names shown are those that appear in the
Floating-Point Library (libfp.a). See "Table-Driven
Interface" for the recommended interface to these rou-
tines. The no-result flag applies to all of them, except
as noted.
Load and Store Operations
FP_FLOAT _FPrdf (r1)
FP_DOUBLE _FPrdd (r1)
Returns the float or double value that is in reg-
ister r1.
FP_FLOAT _FPi2f (r1, ival)
FP_DOUBLE _FPi2d (r1, ival)
Converts the integer value to float or double,
stores the converted value into register r1, and
returns that value.
FP_FLOAT _FPcpf (r1, r2)
FP_FLOAT _FPcpfi (r1, fval)
FP_DOUBLE _FPcpd (r1, r2)
FP_DOUBLE _FPcpdi (r1, dval)
Copies the float or double value from register r2 or
from the val parameter to register r1, and returns
that value.
FP_DOUBLE _FPf2d (r1)
FP_DOUBLE _FPf2di (r1, fval)
FP_FLOAT _FPd2f (r1)
FP_FLOAT _FPd2fi (r1, dval)
Converts the float or double value in register r1 or
in the val parameter to double or float, stores it
into register r1, and returns that value.
FP_DOUBLE _FPf2d2 (r1, r2)
FP_FLOAT _FPd2f2 (r1, r2)
Converts the float or double value in register r2 to
double or float, stores it into register r1, and
returns that value. The value in register r2
remains unmodified.
Multiple-Register Load and Store Operations
_FPlmr Loads multiple floating-point registers with
values stored in memory.
_FPsmr Stores multiple floating-point registers into a
buffer in memory.
These subroutines require a nonstandard calling sequence
that can be performed in assembler language programs, but
not using high-level languages.
Both subroutines are passed the following parameters in
032 Microprocessor general-purpose registers:
Reg Contents
12 Specifies the address of the save area.
11 The low-order 16 bits contain a bit mask that spec-
ifies the floating-point registers to load or
store. Single-precision fpfp registers 0 through 5
are selected by setting the even bits 0, 2, 4, 6,
8, and 10, where bit 0 is the least significant bit
of the mask. The double-precision fpfp registers 0
through 5 are selected by pairs of bits: 0-1, 2-3,
4-5, 6-7, 8-9, and 10-11. For example, setting
bits 4 and 5 selects double-precision fpfp register
2. This register mapping is shown in Figure 3-2.
Both operations modify 032 Microprocessor registers 0,
11, 12, and 13.
Unary Operations
FP_FLOAT _FPngf (r1)
FP_FLOAT _FPngfi (r1, fval)
FP_DOUBLE _FPngd (r1)
FP_DOUBLE _FPngdi (r1, dval)
Negates the float or double value in register r1 or
in the val parameter, stores it into register r1,
and returns that value.
FP_FLOAT _FPabf (r1)
FP_FLOAT _FPabfi (r1, fval)
FP_DOUBLE _FPabd (r1)
FP_DOUBLE _FPabdi (r1, dval)
Makes the float or double value in register r1 or in
the val parameter positive without changing its mag-
nitude, stores it into register r1, and returns that
value.
FP_FLOAT _FPntf (r1)
FP_FLOAT _FPntfi (r1, fval)
FP_DOUBLE _FPntd (r1)
FP_DOUBLE _FPntdi (r1, dval)
Rounds the float or double value in register r1 or
in the val parameter to an integer in floating-point
format, stores the result into register r1, and
returns that value. The rounding performed depends
on the rounding mode specified in the floating-point
status word. (See "Status Register Operations.")
int _FPrnf (r1)
int _FPrnfi (r1, fval)
int _FPrnd (r1)
int _FPrndi (r1, dval)
Copies the val parameter, if given, to register r1,
then returns the integer value that is nearest to
the float or double value in register r1. Note that
the value in register r1 is not converted to an
integer. The rounding performed is independent of
the rounding mode specified in the floating-point
status register. The no-result flag does not apply
to this operation. (See "Parameters" for an expla-
nation of the no-result flag.)
int _FPtrf (r1)
int _FPtrfi (r1, fval)
int _FPtrd (r1)
int _FPtrdi (r1, dval)
Copies the val parameter, if given, to register r1,
then returns the integer part of the float or double
value in register r1. Note that the value in reg-
ister r1 is not converted to an integer. The
rounding performed is independent of the rounding
mode specified in the floating-point status reg-
ister. The no-result flag does not apply to this
operation. (See "Parameters" for an explanation of
the no-result flag.)
int _FPflf (r1)
int _FPflfi (r1, fval)
int _FPfld (r1)
int _FPfldi (r1, dval)
Copies the val parameter, if given, to register r1,
then returns the largest integer less than or equal
to the float or double value in register r1. Note
that the value in register r1 is not converted to an
integer. The rounding performed is independent of
the rounding mode specified in the floating-point
status register. The no-result flag does not apply
to this operation. (See "Parameters" for an expla-
nation of the no-result flag.)
Comparison Operations
int _FPcmf (r1, r2)
int _FPcmfi (r1, fval)
int _FPcmd (r1, r2)
int _FPcmdi (r1, dval)
Compares the float or double value in register r1 to
the float or double value in register r2 or in the
val parameter. The value returned is LESSTHAN,
EQUAL, GREATER or MININT, depending on whether the
value in register r1 is less than, equal to, greater
than, or unordered with the other value, respec-
tively. In addition, the 032 Microprocessor test
bit is set to 1 if the comparison is unordered, and
it is set to 0 otherwise.
If the r1 parameter is logically OR-ed with the
value ExceptOnUnordered, and if the operands are
unordered, then an invalid operation exception
occurs. (See "Status Register Operations" for
details about floating-point exceptions.)
The no-result flag does not apply to these compar-
ison operations. (See "Parameters" for an explana-
tion of the no-result flag.)
Simple Arithmetic Operations
FP_FLOAT _FPadf (r1, r2)
FP_FLOAT _FPadfi (r1, fval)
FP_DOUBLE _FPadd (r1, r2)
FP_DOUBLE _FPaddi (r1, dval)
Adds the float or double value in register r2 or in
the val parameter to the float or double value in
register r1, stores the result into register r1, and
then returns the result.
FP_FLOAT _FPsbf (r1, r2)
FP_FLOAT _FPsbfi (r1, fval)
FP_DOUBLE _FPsbd (r1, r2)
FP_DOUBLE _FPsbdi (r1, dval)
Subtracts the float or double value in register r2
or in the val parameter from the float or double
value in register r1, stores the result into reg-
ister r1, and then returns the result.
FP_FLOAT _FPmlf (r1, r2)
FP_FLOAT _FPmlfi (r1, fval)
FP_DOUBLE _FPmld (r1, r2)
FP_DOUBLE _FPmldi (r1, dval)
Multiplies the float or double value in register r1
by the float or double value in register r2 or in
the val parameter, stores the result into register
r1, and then returns the result.
FP_FLOAT _FPdvf (r1, r2)
FP_FLOAT _FPdvfi (r1, fval)
FP_DOUBLE _FPdvd (r1, r2)
FP_DOUBLE _FPdvdi (r1, dval)
Divides the float or double value in register r1 by
the float or double value in register r2 or in the
val parameter, stores the result into register r1,
and then returns the result.
FP_FLOAT _FPrmf (r1, r2)
FP_FLOAT _FPrmfi (r1, fval)
FP_DOUBLE _FPrmd (r1, r2)
FP_DOUBLE _FPrmdi (r1, dval)
Computes the IEEE remainder that results when the
float or double value in register r1 is divided by
the float or double value in register r2 or in the
val parameter, stores the result into register r1,
and then returns the result. The result is rounded
to the nearest value. See also _FPbmodf, _FPbmodfi,
_FPbmodd, and _FPbmoddi.
FP_FLOAT _FPsqf (r1)
FP_FLOAT _FPsqfi (r1, fval)
FP_DOUBLE _FPsqd (r1)
FP_DOUBLE _FPsqdi (r1, dval)
Computes the square root of the float or double
value in register r1 or in the val parameter, stores
the result into register r1 and then returns the
result.
Three-Operand Arithmetic Operations
FP_FLOAT _FPadf3 (r1, r2, r3)
FP_DOUBLE _FPadd3 (r1, r2, r3)
Adds the float or double values in registers r2 and
r3, stores the result into register r1, and then
returns the result.
FP_FLOAT _FPsbf3 (r1, r2, r3)
FP_DOUBLE _FPsbd3 (r1, r2, r3)
Subtracts the float or double value in register r3
from the value in register r2, stores the result
into register r1, and then returns the result.
FP_FLOAT _FPmlf3 (r1, r2, r3)
FP_DOUBLE _FPmld3 (r1, r2, r3)
Multiplies the float or double values in registers
r2 and r3, stores the result into register r1, and
then returns the result.
FP_FLOAT _FPdvf3 (r1, r2, r3)
FP_DOUBLE _FPdvd3 (r1, r2, r3)
Divides the float or double value in register r2 by
the value in register r3, stores the result into
register r1, and then returns the result.
Packed Decimal Conversion Operations
FP_FLOAT _FPcsf (r1, dec)
FP_DOUBLE _FPcsd (r1, dec)
Converts the packed decimal string pointed to by the
dec parameter to float or double, stores the result
into register r1, and then returns the result. The
dec parameter points to a 10-byte packed decimal
number, the first byte of which is 0 (for a positive
value) or 0x80 (for a negative value). The fol-
lowing 9 bytes containing 2 decimal digits each; the
left half-byte of each byte contains the more sig-
nificant digit.
void _FPcfs (r1, dec)
void _FPcds (r1, dec)
Converts the float or double value in register r1 to
packed decimal format as described for _FPcsf and
_FPcsd. In the special cases of +&infinity.,
-&infinity., and NaN, the first byte is set to 0x7F,
0xFF, or 0x0F, respectively.
Transcendental Operations
These operations implement a version of the
transcendental routines developed at the University of
California at Berkeley, which handle parameters and gen-
erate results in a manner consistent with the IEEE
floating-point standard.
Note: These operations are only available in AIX version
2.1 and later. Programs that use them will not run on
earlier versions of AIX.
FP_DOUBLE _FPbsin (r1, r2)
FP_DOUBLE _FPbsini (r1, dval)
FP_DOUBLE _FPbcos (r1, r2)
FP_DOUBLE _FPbcosi (r1, dval)
FP_DOUBLE _FPbtan (r1, r2)
FP_DOUBLE _FPbtani (r1, dval)
Computes the sine, cosine, or tangent of the double
value in register r2 or in the dval parameter,
stores the result into register r1, and then returns
the result.
FP_DOUBLE _FPbasin (r1, r2)
FP_DOUBLE _FPbasini (r1, dval)
FP_DOUBLE _FPbacos (r1, r2)
FP_DOUBLE _FPbacosi (r1, dval)
FP_DOUBLE _FPbatan (r1, r2)
FP_DOUBLE _FPbatani (r1, dval)
FP_DOUBLE _FPbatan2 (r1, r2)
FP_DOUBLE _FPbatan2i (r1, dval)
The first six subroutines compute the arcsine,
arccosine, and arctangent of the double value in
register r2 or in the dval parameter, store the
result into register r1, and then return the result.
_FPbatan2 and _FPbatan2i compute the arctangent of
y / x, where y (the value in register r1) and x
(the value in register r2 or in the dval parameter)
are both double values. The result is then stored
into register r1 and returned.
FP_DOUBLE _FPblog (r1, r2)
FP_DOUBLE _FPblogi (r1, dval)
FP_DOUBLE _FPblog10 (r1, r2)
FP_DOUBLE _FPblog10i (r1, dval)
Computes the natural or base-10 logarithm of the
double value in register r2 or in the dval param-
eter, stores the result into register r1, and then
returns the result.
FP_DOUBLE _FPbexp (r1, r2)
FP_DOUBLE _FPbexpi (r1, dval)
Computes the value of e(x), where register r2 or
the dval parameter contains a double value repres-
enting the exponent (x). The result is stored into
register r1 and returned.
FP_DOUBLE _FPbmodf (r1, r2)
FP_DOUBLE _FPbmodfi (r1, fval)
FP_DOUBLE _FPbmodd (r1, r2)
FP_DOUBLE _FPbmoddi (r1, dval)
Computes the modulo remainder that results when the
float or double value in register r1 is divided by
the float or double value in register r2 or in the
val parameter, stores the result into register r1,
and then returns the result. The result is rounded
toward zero. See also _FPrmf, _FPrmfi, _FPrmd, and
_FPrmdi.
FP_DOUBLE _FPbscalbi (r1, ival)
Computes the value of y (.) 2(N) for integral
values of N without computing 2(N). Register r1
contains y, and the ival specifies N. The result of
this operation is stored into register r1 and is
returned as the value of the subroutine.
FP_DOUBLE _FPblogb (r1, r2)
FP_DOUBLE _FPblogbi (r1, dval)
Extracts the unbiased exponent from the double value
in register r2 or in the dval parameter, stores the
result into register r1, and then returns the
result. The result is a signed integer in double-
precision floating-point format, except that the
logb of a NaN is a Nan, the logb of &infinity. is
+&infinity, and the logb of 0 is -&infinity..
Taking the logb of 0 also causes a division by zero
exception to occur. (See "Status Register Oper-
ations" for details about floating-point
exceptions.) If x is positive and finite, then the
expression _FPbscalbi (r, -_FPblogbi (s, x)) lies
strictly between 0 and 2; it is less than 1 only
when x is denormalized.
Additional Transcendental Operations
These operations are the core calculations for other log-
arithmic, hyperbolic, and trigonometric functions, and
they can be used as partial steps in calculating the
result desired by the user. A more convenient set of
transcendentals is discussed under "Transcendental Oper-
ations." The basic transcendentals are not implemented by
any of the floating-point processors, but by software
routines only.
FP_DOUBLE _FPtan (r1, r2)
Computes the partial tangent of an angle measured in
radians. Register r1 contains the angle, which must
be a double value in the range 0 < r1 < &pi./4. If
the value in register r1 is outside this range, then
an invalid operation exception occurs, and no opera-
tion is performed. The result of this operation
consists of 2 double values. The sine of the angle
is stored into register r1 and is returned as the
value of the subroutine. The cosine is stored into
register r2. To compute the tangent, divide the
sine by the cosine.
FP_DOUBLE _FPatan (r1, r2)
Computes the arctangent of y / x. This operation
requires a double value in both registers r1 and r2.
These arguments must be ordered such that the value
in r1 (x) is greater than the value in r2 (y), which
is greater than 0. If the values are not ordered in
this manner, then an invalid operation exception
occurs, and no operation is performed. The result
is stored into register r1 and is returned as the
value of the subroutine.
FP_DOUBLE _FP2xm1 (r1)
Computes the value of 2(x) - 1. Register r1 con-
tains the exponent (x), which must a double value be
in the range 0 < r1 < 0.5. If the value in reg-
ister r1 is not in this range, then an invalid oper-
ation exception occurs, and no operation is
performed. The result of this operation is stored
into register r1 and is returned as the value of the
subroutine.
FP_DOUBLE _FPyl2x (r1, r2)
Computes the value of y (.) log[2] x. This opera-
tion requires a double value in both registers r1
and r2. Register r1 contains the exponent (x),
which must be a double value the range
0 < r1 < +&infinity.. If the value in register r1
is outside this range, then an invalid operation
exception occurs, and no operation is performed.
Register r2 contains the multiplier (y), which can
be any valid double value. The result of this oper-
ation is stored into register r1 and is returned as
the value of the subroutine.
FP_DOUBLE _FPylp1 (r1, r2)
Computes the value of y (.) log[2] (x+1). This
operation requires a double value in both registers
r1 and r2. Register r1 contains x, which must be a
double value in the range: 0 < r1 < (1 - (sqrt(2) /
2) ). If the value in register r1 is outside this
range, then an invalid operation exception occurs,
and no operation is performed. Register r2 contains
the multiplier (y), which can be any valid double
value. The result of the operation is stored into
register r1 and is returned as the value of the sub-
routine. This subroutine provides more accurate
results than _FPyl2x for x values close to 1.
Status Register Operations
The floating-point status is kept in a FP_STATUS struc-
ture, which is defined with a typedef statement in the
sys/fpfp.h header file, and which contains the following
fields:
"unsigned kill : 1" Signal SIGFPE on an exception "unsigned xcp_flag : 1" An exception occurred "unsigned io_flag : 1" An invalid operation occurred "unsigned io_xpt : 1" Enable signal on invalid operation "unsigned dz_flag : 1" A division by 0
When set, the kill field enables exception trapping. The
io_xpt, dz_xpt, of_xpt, ir_xpt, and uf_xpt fields enable
trapping for each of the five exception types. Thus, for
an exception to be trapped, both kill and the xx_xpt
field for that exception must be set. See "Exception
Handling" for detailed information about exceptions and
traps.
When an exception occurs for which trapping is not
enabled, the fields io_flag, dz_flag, of_flag, ir_flag,
and uf_flag are set to indicate the exception or
exceptions that occurred. The xcp_flag field is also set
to indicate that an exception occurred. The xcp_flag and
xx_flag fields are not automatically reset to 0; this
must be done explicitly by calling _FPsetst.
The cmp_rslt field of the status word specifies the
result of a comparison operation, and it is set to one of
the following values:
0 Less than
1 Equal
2 Greater than
3 Unordered.
The rnd_mode field of the status word specifies the
rounding mode, and it can be set to one of the following
values:
FP_NEAR Rounds to the nearest value. This is the
default.
FP_ZERO Rounds toward 0.
FP_UP Rounds toward +&infinity..
FP_DOWN Rounds toward -&infinity..
FP_STATUS _FPgetst ( )
Returns the floating-point status word reflecting
the results of the most recent floating-point opera-
tion.
void _FPsetst (status)
Sets the floating-point status word to the value
provided by the status parameter.
Exception Handling
When an error is detected during a floating-point opera-
tion, an exception occurs. Each exception is one of five
types, as specified by the IEEE standard: invalid opera-
tion, overflow, underflow, division by zero, and inexact
result.
The standard also defines a default result that is
returned as the value of the operation that caused the
exception. Alternatively, you can specify a special
action to be taken when an exception occurs. Performing
a user-defined action when an exception occurs is called
exception trapping, and a user-defined trap routine is
called a trap handler. However, the default result is
sufficient for most applications, and specifying a trap
handler is usually not necessary.
When an exception occurs, the floating-point operation
checks the trap-enabling fields of the floating-point
status word. (See "Status Register Operations" for
details about the trap-enabling fields.) If either the
kill field or the xx_xpt field for the exception type is
not set, then the exception is not trapped and the fol-
lowing default actions take place:
o The xcp_flag field is set to indicate that an excep-
tion occurred.
o The appropriate xx_flag field is set to indicate the
exception type.
o The default result specified by the IEEE standard is
returned to the application program.
If both the kill field and the xx_xpt field are set, then
trapping is enabled for the given exception type. In
this case, the SIGFPE signal is sent to the process.
(AIX signals are discussed in "signal.") You can write
your own signal handler, which must determine the excep-
tion that occurred and take appropriate action, or you
can use the facility provided by the ieeetrap subroutine.
Note: If the status word setting enables the trapping of
one or more exception types and no signal handler is
specified for SIGFPE (either a user-supplied handler or
the one installed by ieeetrap), then the default action
(SIG_DFL) is taken for the signal, which terminates the
process.
The ieeetrap subroutine, which is located in the IEEE
Support Library (libieee.a), allows you to specify a trap
handler for each of the five exception types. ieeetrap
functions like the signal system call and has the fol-
lowing syntax:
int (*ieeetrap (exceptiontype, action)) ( )
int exceptiontype;
int (*action) ( );
The exceptiontype parameter identifies the type of excep-
tion and is one of the following values:
FP_INV_OPER Invalid operation
FP_OVERFLOW Overflow
FP_UNDERFLOW Underflow
FP_DIVIDE Division by zero
FP_INEXACT Inexact result.
The action parameter is one of the following:
SIG_IGN Sets the status word to disable trapping of the
specified exception type. This is the default
action for a given exception type if an action
is not specified for it.
SIG_DFL Causes the process to be terminated upon an
exception of the specified type. The process
is terminated by setting the action for the
SIGFPE signal to SIG_DFL and sending SIGFPE to
the process. This allows the parent process to
determine that the process terminated due to a
floating-point exception.
handler Causes the subroutine with the address given by
handler to be called when an exception of the
specified type occurs.
Warning: Unpredictable results can occur if you use
ieeetrap to disable trapping of a given exception type
(SIG_IGN) and then enable trapping by using _FPsetst to
set the status word. Instead, use ieeetrap to set a trap
handler for the exception type.
The ieeetrap subroutine establishes a signal handler for
SIGFPE that selects one of five actions based on the
exception type. It also sets action as the action to be
taken when an exceptiontype exception occurs.
Upon successful completion, the ieeetrap subroutine
returns the previous value of action for the specified
exceptiontype. If an error occurs, then the value BADSIG
is returned.
If the action parameter to ieeetrap specifies a handler
subroutine, then an exception of the specified type
causes the handler subroutine to be called with the fol-
lowing syntax:
#include <sys/FP.h>
#include <signal.h>
handler (sig, code, scp)
int sig, code;
struct sigcontext *scp;
The parameters are the same as those passed to the signal
handler. (See "sigvec" for a detailed description.)
Note that the value of the sig parameter is always
SIG_FPE.
The following discussion traces through the hierarchy of
structures pointed to by the scp parameter. Use
Figure 3-1 as a guide for this discussion.
The sigcontext structure, which is defined in the
sys/signal.h header file, contains a member named fpvmp,
which points to a fpvmach structure. The fpvmach struc-
ture describes the state of the virtual floating-point
machine at the time of the exception. This structure is
defined in the ieeetrap.h header file, and it contains
the following members:
"fpreg fpreg[NDPFPREGS|" Set of floating-point registers"
FP_STATUS statusreg" Status register at time of exception "fptrap fptrap" Specific information about the exception
Each fpreg structure in the array represents a double-
precision value, two single-precision values, or two long
unsigned integers. Viewing a value as a pair long
unsigned integers can be useful for displaying and
studying its bit pattern. Each register structure always
contains a double value on systems with the APC/881 but
no Advanced Floating-Point Accelerator. The FP_STATUS
structure is discussed in "Status Register Operations."
The fptrap structure, also defined in ieeetrap.h, con-
tains the following members:
"fptrapinfo fptrapinfo""
fpreg designated_result"
The fptrapinfo structure contains the following members:
"unsigned int operation : 8" Operation causing the exception "unsigned int src : 4" Source register number "unsigned int dest : 4" Destination register number "unsigned int except_flags : 5" Exceptions that occurred "unsigned int except_type :
The operation field contains one of the values defined by
the FPFPI enumeration data type, identifying the opera-
tion that caused the exception. See "Table-Driven Inter-
face" for details about FPFPI.
OL807218
Figure 3-1. Floating-Point Trap Handler Structures
The src and dest fields specify the operand registers,
but not by their abstract fpfp register numbers. The
operand registers given in src and dest are numbered from
0 to 13 for single-precision operands. Double-precision
operands occupy a pair of registers identified by the
even number of the pair. For example, 4 identifies the
double-precision value occupying registers 4 and 5, and
it corresponds to the abstract fpfp register 2. This
register mapping is shown in the following figure:
ol807217
Figure 3-2. fpfp Register Mapping
The except_flags field indicates the exception or
exceptions that resulted from the operation. This value
is constructed by logically OR-ing together one or more
of EM_INV_OPER, EM_OVERFLOW, EM_UNDERFLOW, EM_DIVIDE, and
EM_INEXACT.
The except_type field identifies the exception that
caused the trap to be taken. This is the highest-
priority exception that occurred for which trapping is
enabled. The value is one of FP_INV_OPER, FP_OVERFLOW,
FP_UNDERFLOW, FP_DIVIDE, or FP_INEXACT.
On an inexact, overflow, or underflow exception, the
designated_result in the fptrap structure contains the
designated result, as defined by the IEEE standard. It
is properly rounded to the precision of the destination
of the operation. In the case of overflow or underflow,
this result is also scaled.
Warning: When an exception is trapped, the status reg-
ister is not automatically set to reflect the exception,
nor is a result stored in the destination register. The
trap handler must do this or the results will be unpre-
dictable.
To set the status register and result value, set the
appropriate members of the fpvmach structure. That is,
set the status by modifying the bit fields of
scp"->"fpvmp"->"statusreg, and store the result into
scp"->"fpvmp"->"fpreg[dest|. (See the sys/signal.h,
ieeetrap.h, and sys/fpfp.h header files for the complete
definitions of these structures.)
Note: If the floating-point operation being performed
returns an integer value (_FPrnxx, _FPtrxx, or _FPflxx),
then store the result in the destination register as an
integer value in double-precision floating-point format.
Related Information
The description of the Floating-Point Accelerator,
Advanced Floating-Point Accelerator, or APC/881 in Hard-
ware Technical Reference.
The discussion of Floating-Point Services in Virtual
Resource Manager Technical Reference.
Assembler Language Reference.
The cc command in AIX Operating System Commands
Reference.