Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ fpfp(3) — AIX/RT 2.2.1

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

cc

     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.

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026