home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / intel / 80287.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  432.8 KB  |  8,873 lines

  1.  INTEL 80287 PROGRAMMER'S REFERENCE MANUAL 1987
  2.  
  3.  Intel Corporation makes no warranty for the use of its products and
  4.  assumes no responsibility for any errors which may appear in this document
  5.  nor does it make a commitment to update the information contained herein.
  6.  
  7.  Intel retains the right to make changes to these specifications at any
  8.  time, without notice.
  9.  
  10.  Contact your local sales office to obtain the latest specifications before
  11.  placing your order.
  12.  
  13.  The following are trademarks of Intel Corporation and may only be used to
  14.  identify Intel Products:
  15.  
  16.  Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, î,
  17.  ICE, iCEL, iCS, iDBP, iDIS, I²ICE, iLBX, im, iMDDX, iMMX, Inboard, Insite,
  18.  Intel, intel, intelBOS, Intelevision, inteligent Identifier, inteligent
  19.  Programming, Intellec, Intellink, iOSP, iPDS, iPSC, iRMX, iSBC, iSBX, iSDM,
  20.  iSXM, KEPROM, Library Manager, MAP-NET, MCS, Megachassis, MICROMAINFRAME,
  21.  MULTIBUS, MULTICHANNEL, MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP,
  22.  PC-BUBBLE, Plug-A-Bubble, PROMPT, Promware, QUEST, QueX, Quick-Pulse
  23.  Programming, Ripplemode, RMX/80, RUPI, Seamless, SLD, UPI, and VLSiCEL, and
  24.  the combination of ICE, iCS, iRMX, iSBC, iSBX, MCS, or UPI and a numerical
  25.  suffix, 4-SITE.
  26.  
  27.  MDS is an ordering code only and is not used as a product name or
  28.  trademark. MDS(R) is a registered trademark of Mohawk Data Sciences
  29.  Corporation.
  30.  
  31.  *MULTIBUS is a patented Intel bus.
  32.  
  33.  Additional copies of this manual or other Intel literature may be obtained
  34.  from:
  35.  
  36.  Intel Corporation
  37.  Literature Distribution
  38.  Mail Stop SC6-59
  39.  3065 Bowers Avenue
  40.  Santa Clara, CA 95051
  41.  
  42.  (c)INTEL CORPORATION 1987   CG-10/86
  43.  
  44.  
  45.  Preface
  46.  
  47.  ───────────────────────────────────────────────────────────────────────────
  48.  
  49.  An Introduction to the 80287
  50.  This supplement describes the 80287 Numeric Processor Extension (NPX) for
  51.  the 80286 microprocessor. Below is a brief overview of 80286 concepts, along
  52.  with some of the nomenclature used throughout this and other Intel
  53.  publications.
  54.  
  55.  
  56.  The 80286 Microsystem
  57.  The 80286 is a new VLSI microprocessor system with exceptional capabilities
  58.  for supporting large-system applications. Based on a new-generation CPU (the
  59.  Intel 80286), this powerful microsystem is designed to support multiuser
  60.  reprogrammable and real-time multitasking applications. Its dedicated system
  61.  support circuits simplify system hardware; sophisticated hardware and
  62.  software tools reduce both the time and the cost of product development.
  63.  
  64.  The 80286 is a virtual-memory microprocessor with on-chip memory management
  65.  and protection. The 80286 microsystem offers a total-solution approach,
  66.  enabling you to develop high-speed, interactive, multiuser, multitasking──
  67.  and multiprocessor──systems more rapidly and at higher performance than ever
  68.  before.
  69.  
  70.    ■  Reliability and system up-time are becoming increasingly important in
  71.       all applications. Information must be protected from misuse or
  72.       accidental loss. The 80286 includes a sophisticated and flexible
  73.       four-level protection mechanism that isolates layers of operating
  74.       system programs from application programs to maintain a high degree of
  75.       system integrity.
  76.  
  77.    ■  The 80286 provides 16 megabytes of physical address space to support
  78.       today's application requirements. This large physical memory enables
  79.       the 80286 to keep many large programs and data structures
  80.       simultaneously in memory for high-speed access.
  81.  
  82.    ■  For applications with dynamically changing memory requirements, such
  83.       as multiuser business systems, the 80286 CPU provides on-chip memory
  84.       management and virtual memory support. On an 80286-based system, each
  85.       user can have up to a gigabyte (2^(30) bytes) of virtual-address space.
  86.       This large address space virtually eliminates restrictions on the
  87.       number or size of programs that may be part of the system.
  88.  
  89.    ■  Large multiuser or real-time multitasking systems are easily supported
  90.       by the 80286. High-performance features, such as a very high-speed
  91.       task switch, fast interrupt-response time, inter-task protection, and a
  92.       quick and direct operating system interface, make the 80286 highly
  93.       suited to multiuser/multitasking applications.
  94.  
  95.    ■  The 80286 has two operating modes: Real-Address mode and
  96.       Protected-Address mode. In Real-Address mode, the 80286 is fully
  97.       compatible with the 8086, 8088, 80186, and 80188 microprocessors; all
  98.       of the extensive libraries of 8086 and 8088 software execute four to
  99.       six times faster on the 80286, without any modification.
  100.  
  101.    ■  In Protected-Address mode, the advanced memory management and
  102.       protection features of the 80286 become available, without any
  103.       reduction in performance. Upgrading 8086 and 8088 application programs
  104.       to use these new memory management and protection features usually
  105.       requires only reassembly or recompilation (some programs may require
  106.       minor modification). This compatibility between 80286 and 8086
  107.       processor families reduces both the time and the cost of
  108.       software development.
  109.  
  110.  
  111.  The Organization of This Manual
  112.  This manual describes the 80287 Numeric Processor Extension (NPX) for the
  113.  80286 microprocessor. The material in this manual is presented from the
  114.  perspective of software designers, both at an applications and at a systems
  115.  software level.
  116.  
  117.    ■  Chapter One, "Overview of Numeric Processing," gives an overview of
  118.       the 80287 NPX and reviews the concepts of numeric computation using the
  119.       80287.
  120.  
  121.    ■  Chapter Two, "Programming Numeric Applications," provides detailed
  122.       information for software designers generating applications for systems
  123.       containing an 80286 CPU with an 80287 NPX. The 80286/80287 instruction
  124.       set mnemonics are explained in detail, along with a description of
  125.       programming facilities for these systems. A comparative 80287
  126.       programming example is given.
  127.  
  128.    ■  Chapter Three, "System-Level Numeric Programming," provides
  129.       information of interest to systems software writers, including details
  130.       of the 80287 architecture and operational characteristics.
  131.  
  132.    ■  Chapter Four, "Numeric Programming Examples," provides several
  133.       detailed programming examples for the 80287, including conditional
  134.       branching, the conversion between floating-point values and their ASCII
  135.       representations, and the calculation of several trigonometric
  136.       functions. These examples illustrate assembly-language programming on
  137.       the 80287 NPX.
  138.  
  139.    ■  Appendix A, "Machine Instruction Encoding and Decoding," gives
  140.       reference information on the encoding of NPX instructions.
  141.  
  142.    ■  Appendix B, "Compatability between the 80287 NPX and the 8087,"
  143.       describes the differences between the 80287 and the 8087.
  144.  
  145.    ■  Appendix C, "Implementing the IEEE P754 Standard," gives details of
  146.       the IEEE P754 Standard.
  147.  
  148.    ■  The Glossary defines 80287 and floating-point terminology. Refer to
  149.       it as needed.
  150.  
  151.  
  152.  Related Publications
  153.  To best use the material in this manual, readers should be familiar with
  154.  the operation and architecture of 80286 systems. The following manuals
  155.  contain information related to the content of this supplement and of
  156.  interest to programmers of 80287 systems:
  157.  
  158.    ■  Introduction to the 80286, order number 210308
  159.  
  160.    ■  ASM286 Assembly Language Reference Manual, order number 121924
  161.  
  162.    ■  80286 Operating System Writer's Guide, order number 121960
  163.  
  164.    ■  80286 Hardware Reference Manual, order number 210760
  165.  
  166.    ■  Microprocessor and Peripheral Handbook, order number 210844
  167.  
  168.    ■  PL/M-286 User's Guide, order number 121945
  169.  
  170.    ■  80287 Support Library Reference Manual, order number 122129
  171.  
  172.    ■  8086 Software Toolbox Manual, order number 122203 (includes
  173.       information about 80287 Emulator Software)
  174.  
  175.  Notational Conventions
  176.  This manual uses special notation to represent sub- and superscript
  177.  characters. Subscript characters are surrounded by {curly brackets}, for
  178.  example 10{2} = 10 base 2. Superscript characters are preceeded by a caret
  179.  and enclosed within (parentheses), for example 10^(3) = 10 to the third
  180.  power.
  181.  
  182.  
  183.  Table of Contents
  184.  
  185.  ───────────────────────────────────────────────────────────────────────────
  186.  
  187.  Preface
  188.  
  189.  Chapter 1  Overview of Numeric Processing
  190.  
  191.  Introduction to the 80287 Numeric Processor Extension
  192.      Performance
  193.      Ease of Use
  194.      Applications
  195.      Upgradability
  196.      Programming Interface
  197.      Hardware Interface
  198.  
  199.  80287 Numeric Processor Architecture
  200.      The NPX Register Stack
  201.      The NPX Status Word
  202.      Control Word
  203.      The NPX Tag Word
  204.      The NPX Instruction and Data Pointers
  205.  
  206.  Computation Fundamentals
  207.      Number System
  208.      Data Types and Formats
  209.          Binary Integers
  210.          Decimal Integers
  211.          Real Numbers
  212.      Rounding Control
  213.      Precision Control
  214.      Infinity Control
  215.  
  216.  Special Computational Situations
  217.      Special Numeric Values
  218.          Nonnormal Real Numbers
  219.              Denormals and Gradual Underflow
  220.              Unnormals──Descendents of Denormal Operands
  221.          Zeros and Pseudo Zeros
  222.          Infinity
  223.          NaN (Not a Number)
  224.          Indefinite
  225.          Encoding of Data Types
  226.      Numeric Exceptions
  227.          Invalid Operation
  228.          Zero Divisor
  229.          Denormalized Operand
  230.          Numeric Overflow and Underflow
  231.          Inexact Result
  232.          Handling Numeric Errors
  233.              Automatic Exception Handling
  234.              Software Exception Handling
  235.  
  236.  Chapter 2  Programming Numeric Applications
  237.  
  238.  The 80287 NPX Instruction Set
  239.      Compatibility with the 8087 NPX
  240.      Numeric Operands
  241.      Data Transfer Instructions
  242.      Arithmetic Instructions
  243.      Comparison Instructions
  244.      Transcendental Instructions
  245.      Constant Instructions
  246.      Processor Control Instructions
  247.      Instruction Set Reference Information
  248.          Instruction Execution Time
  249.          Bus Transfers
  250.          Instruction Length
  251.  
  252.  Programming Facilities
  253.      High-Level Languages
  254.      PL/M-286
  255.      ASM286
  256.          Defining Data
  257.          Records and Structures
  258.          Addressing Modes
  259.      Comparative Programming Example
  260.      80287 Emulation
  261.  
  262.  Concurrent Processing with the 80287
  263.      Managing Concurrency
  264.      Instruction Synchronization
  265.      Data Synchronization
  266.      Error Synchronization
  267.          Incorrect Error Synchronization
  268.          Proper Error Synchronization
  269.  
  270.  Chapter 3  System-Level Numeric Programming
  271.  
  272.  80287 Architecture
  273.      Processor Extension Data Channel
  274.      Real-Address Mode and Protected Virtual-Address Mode
  275.      Dedicated and Reserved I/O Locations
  276.  
  277.  Processor Initialization and Control
  278.       System Initialization
  279.       Recognizing the 80287 NPX
  280.       Configuring the Numerics Environment
  281.       Initializing the 80287
  282.       80287 Emulation
  283.       Handling Numeric Processing Exceptions
  284.       Simultaneous Exception Response
  285.       Exception Recovery Examples
  286.  
  287.  Chapter 4  Numeric Programming Examples
  288.  
  289.  Conditional Branching Examples
  290.  
  291.  Exception Handling Examples
  292.  
  293.  Floating-Point to ASCII Conversion Examples
  294.      Function Partitioning
  295.      Exception Considerations
  296.      Special Instructions
  297.      Description of Operation
  298.      Scaling the Value
  299.          Inaccuracy in Scaling
  300.          Avoiding Underflow and Overflow
  301.          Final Adjustments
  302.      Output Format
  303.  
  304.  Trigonometric Calculation Examples
  305.      FPTAN and FPREM
  306.      Cosine Uses Sine Code
  307.  
  308.  Appendix A  Machine Instriction Encoding and Decoding
  309.  
  310.  Appendix B  Compatibility Between the 80287 NPX and the 8087
  311.  
  312.  Appendix C  Implementing The IEEE P754 Standard
  313.  
  314.      Options implemented in the 80287
  315.      Areas of the Standard Implemented in Software
  316.      Additional Software to Meet the Standard
  317.  
  318.  Glossary of 80287 and Floating-Point Terminology
  319.  
  320.  Index
  321.  
  322.  
  323.  Figures
  324.  
  325.  1-1      Evolution and Performance of Numeric Processors
  326.  1-2      80287 NPX Block Diagram
  327.  1-3      80287 Register Set
  328.  1-4      80287 Status Word
  329.  1-5      80287 Control Word Format
  330.  1-6      80287 Tag Word Format
  331.  1-7      80287 Instruction and Data Pointer Image in Memory
  332.  1-8      80287 Number System
  333.  1-9      Data Formats
  334.  1-10     Projective versus Affine Closure
  335.  1-11     Arithmetic Example Using Infinity
  336.  
  337.  2-1      FSAVE/FRSTOR Memory Layout
  338.  2-2      FSTENV/FLDENV Memory Layout
  339.  2-3      Sample 80287 Constants
  340.  2-4      Status Word RECORD Definition
  341.  2-5      Structure Definition
  342.  2-6      Sample PL/M-286 Program
  343.  2-7      Sample ASM286 Program
  344.  2-8      Instructions and Register Stack
  345.  2-9      Synchronizing References to Shared Data
  346.  2-10     Documenting Data Synchronization
  347.  2-11     Nonconcurrent FIST Instruction Code Macro
  348.  2-12     Error Synchronization Examples
  349.  
  350.  3-1      Software Routine to Recognize the 80287
  351.  
  352.  4-1      Conditional Branching for Compares
  353.  4-2      Conditional Branching for FXAM
  354.  4-3      Full-State Exception Handler
  355.  4-4      Reduced-Latency Exception Handler
  356.  4-5      Reentrant Exception Handler
  357.  4-6      Floating-Point to ASCII Conversion Routine
  358.  4-7      Calculating Trigonometric Functions
  359.  
  360.  
  361.  Tables
  362.  
  363.  1-1      Numeric Processing Speed Comparisons
  364.  1-2      Numeric Data Types
  365.  1-3      Principal NPX Instructions
  366.  1-4      Interpreting the NPX Condition Codes
  367.  1-5      Real Number Notation
  368.  1-6      Rounding Modes
  369.  1-7      Denormalization Process
  370.  1-8      Exceptions Due to Denormal Operands
  371.  1-9      Unnormal Operands and Results
  372.  1-10     Zero Operands and Results
  373.  1-11     Masked Overflow Response with Directed Rounding
  374.  1-12     Infinity Operands and Results
  375.  1-13     Binary Integer Encodings
  376.  1-14     Packed Decimal Encodings
  377.  1-15     Real and Long Real Encodings
  378.  1-16     Temporary Real Encodings
  379.  1-17     Exception Conditions and Masked Responses
  380.  
  381.  2-1      Data Transfer Instructions
  382.  2-2      Arithmetic Instructions
  383.  2-3      Basic Arithmetic Instructions and Operands
  384.  2-4      Condition Code Interpretation after FPREM
  385.  2-5      Comparison Instructions
  386.  2-6      Condition Code Interpretation after FCOM
  387.  2-7      Condition Code Interpretation after FTST
  388.  2-8      FXAM Condition Code Settings
  389.  2-9      Transcendental Instructions
  390.  2-10     Constant Instructions
  391.  2-11     Processor Control Instructions
  392.  2-12     Key to Operand Types
  393.  2-13     Execution Penalties
  394.  2-14     Instruction Set Reference Data
  395.  2-15     PL/M-286 Built-In Procedures
  396.  2-16     80287 Storage Allocation Directives
  397.  2-17     Addressing Mode Examples
  398.  
  399.  3-1      NPX Processor State Following Initialization
  400.  3-2      Precedence of NPX Exceptions
  401.  
  402.  A-1      80287 Instruction Encoding
  403.  A-2      Machine Instruction Decoding Guide
  404.  
  405.  
  406.  Chapter 1  Overview of Numeric Processing
  407.  
  408.  ───────────────────────────────────────────────────────────────────────────
  409.  
  410.  The 80287 NPX is a high-performance numerics processing element that
  411.  extends the 80286 architecture by adding significant numeric capabilities
  412.  and direct support for floating-point, extended-integer, and BCD data types.
  413.  The 80286 CPU with 80287 NPX easily supports powerful and accurate numeric
  414.  applications through its implementation of the proposed IEEE 754 Standard
  415.  for Binary Floating-Point Arithmetic.
  416.  
  417.  
  418.  Introduction to the 80287 Numeric Processor Extension
  419.  The 80287 Numeric Processor Extension (NPX) is highly compatible with its
  420.  predecessor, the earlier Intel 8087 NPX.
  421.  
  422.  The 8087 NPX was designed for use in 8086-family systems. The 8086 was the
  423.  first microprocessor family to partition the processing unit to permit
  424.  high-performance numeric capabilities. The 8087 NPX for this processor
  425.  family implemented a complete numeric processing environment in compliance
  426.  with the proposed IEEE 754 Floating-Point Standard.
  427.  
  428.  With the 80287 Numeric Processor Extension, high-speed numeric computations
  429.  have been extended to 80286 high-performance multi-tasking and multi-user
  430.  systems. Multiple tasks using the numeric processor extension are afforded
  431.  the full protection of the 80286 memory management and protection features.
  432.  
  433.  Figure 1-1 illustrates the relative performance of 8-MHz 8086/8087 and
  434.  80286/80287 systems in executing numerics-oriented applications.
  435.  
  436.  
  437.  Figure 1-1.  Evolution and Performance of Numeric Processors
  438.  
  439.      DOUBLE-PRECISION                       ┌─────────────┐
  440.         WHETSTONE           │                │ 80286/80287 │
  441.        PERFORMANCE          │                └────────────┘
  442.          (KOPS)        200 ─┼─                  
  443.                             │               
  444.                             │     ┌──────────┐
  445.                             │     │ 8086/8087 │
  446.                             │     └───────────┘
  447.                             │
  448.                        100 ─┼─
  449.                             │
  450.                             │
  451.                             │
  452.                             │
  453.                             └────────────┼────────────┼───────────
  454.                                         1980         1983
  455.  
  456.                                         YEAR INTRODUCED
  457.  
  458.  
  459.  Performance
  460.  Table 1-1 compares the execution times of several 80287 instructions with
  461.  the equivalent operations executed in software on an 8-MHz 80286. The
  462.  software equivalents are highly-optimized assembly-language procedures from
  463.  the 80287 emulator. As indicated in the table, the 80287 NPX provides about
  464.  50 to 100 times the performance of software numeric routines on the 80286
  465.  CPU. An 8-MHz 80287 multiplies 32-bit and 64-bit real numbers in about 11.9
  466.  and 16.9 microseconds, respectively. Of course, the actual performance of
  467.  the NPX in a given system depends on the characteristics of the individual
  468.  application.
  469.  
  470.  Although the performance figures shown in table 1-1 refer to operations on
  471.  real (floating-point) numbers, the 80287 also manipulates fixed-point binary
  472.  and decimal integers of up to 64 bits or 18 digits, respectively. The 80287
  473.  can improve the speed of multiple-precision software algorithms for integer
  474.  operations by 10 to 100 times.
  475.  
  476.  Because the 80287 NPX is an extension of the 80286 CPU, no software
  477.  overhead is incurred in setting up the NPX for computation. The 80287 and
  478.  80286 processors coordinate their activities in a manner transparent to
  479.  software. Moreover, built-in coordination facilities allow the 80286 CPU to
  480.  proceed with other instructions while the 80287 NPX is simultaneously
  481.  executing numeric instructions. Programs can exploit this concurrency of
  482.  execution to further increase system performance and throughput.
  483.  
  484.  
  485.  Table 1-1.  Numeric Processing Speed Comparisons
  486.  
  487.                                                    Approximate Performance
  488.                                                    Ratios: 8 MHz 80287 to
  489.                                                    8 MHz Protected Mode iAPX
  490.  ┌────── Floating-Point Instruction ────────────┐  using E80287
  491.  
  492.  FADD ST,ST (Temp Real)             Addition                1: 42
  493.  FDIV DWORD PTR (Single-Precision)  Division                1:266
  494.  FXAM (Stack(0) assumed)            Examine                 1:139
  495.  FYL2X (Stack(0),(1) assumed)       Logarithm               1: 99
  496.  FPATAN (Stack(0) assumed)          Arctangent              1:153
  497.  F2XM1 (Stack (0) assumed)          Exponentiation          1: 41
  498.  
  499.  
  500.  Ease of Use
  501.  The 80287 NPX offers more than raw execution speed for
  502.  computation-intensive tasks. The 80287 brings the functionality and power
  503.  of accurate numeric computation into the hands of the general user.
  504.  
  505.  Like the 8087 NPX that preceded it, the 80287 is explicitly designed to
  506.  deliver stable, accurate results when programmed using straightforward
  507.  "pencil and paper" algorithms. The IEEE 754 standard specifically addresses
  508.  this issue, recognizing the fundamental importance of making numeric
  509.  computations both easy and safe to use.
  510.  
  511.  For example, most computers can overflow when two single-precision
  512.  floating-point numbers are multiplied together and then divided by a third,
  513.  even if the final result is a perfectly valid 32-bit number. The 80287
  514.  delivers the correctly rounded result. Other typical examples of
  515.  undesirable machine behavior in straightforward calculations occur when
  516.  solving for the roots of a quadratic equation:
  517.  
  518.    -b ± √(b² - 4ac)
  519.    ────────────────────
  520.            2a
  521.  
  522.  for computing financial rate of return, which involves the expression:
  523.  (1+i)^(n). On most machines, straightforward algorithms will not deliver
  524.  consistently correct results (and will not indicate when they are
  525.  incorrect). To obtain correct results on traditional machines under all
  526.  conditions usually requires sophisticated numerical techniques that are
  527.  foreign to most programmers. General application programmers using
  528.  straightforward algorithms will produce much more reliable programs using
  529.  the 80287. This simple fact greatly reduces the software investment required
  530.  to develop safe, accurate computation-based products.
  531.  
  532.  Beyond traditional numerics support for scientific applications, the 80287
  533.  has built-in facilities for commercial computing. It can process decimal
  534.  numbers of up to 18 digits without round-off errors, performing exact
  535.  arithmetic on integers as large as 2^(64) or 10^(18). Exact arithmetic is
  536.  vital in accounting applications where rounding errors may introduce
  537.  monetary losses that cannot be reconciled.
  538.  
  539.  The NPX contains a number of optional facilities that can be invoked by
  540.  sophisticated users. These advanced features include two models of infinity,
  541.  directed rounding, gradual underflow, and either automatic or programmed
  542.  exception-handling facilities.
  543.  
  544.  These automatic exception-handling facilities permit a high degree of
  545.  flexibility in numeric processing software, without burdening the
  546.  programmer. While performing numeric calculations, the NPX automatically
  547.  detects exception conditions that can potentially damage a calculation. By
  548.  default, on-chip exception handlers may be invoked to field these exceptions
  549.  so that a reasonable result is produced, and execution may proceed without
  550.  program interruption. Alternatively, the NPX can signal the CPU, invoking a
  551.  software exception handler whenever various types of exceptions are
  552.  detected.
  553.  
  554.  
  555.  Applications
  556.  The NPX's versatility and performance make it appropriate to a broad array
  557.  of numeric applications. In general, applications that exhibit any of the
  558.  following characteristics can benefit by implementing numeric processing on
  559.  the 80287:
  560.  
  561.    ■  Numeric data vary over a wide range of values, or include nonintegral
  562.       values.
  563.  
  564.    ■  Algorithms produce very large or very small intermediate results.
  565.  
  566.    ■  Computations must be very precise; i.e., a large number of significant
  567.       digits must be maintained.
  568.  
  569.    ■  Performance requirements exceed the capacity of traditional
  570.       microprocessors.
  571.  
  572.    ■  Consistently safe, reliable results must be delivered using a
  573.       programming staff that is not expert in numerical techniques.
  574.  
  575.  Note also that the 80287 can reduce software development costs and improve
  576.  the performance of systems that use not only real numbers, but operate on
  577.  multiprecision binary or decimal integer values as well.
  578.  
  579.  A few examples, which show how the 80287 might be used in specific numerics
  580.  applications, are described below. In many cases, these types of systems
  581.  have been implemented in the past with minicomputers. The advent of the
  582.  80287 brings the size and cost savings of microprocessor technology to these
  583.  applications for the first time.
  584.  
  585.    ■  Business data processing──The NPX's ability to accept decimal operands
  586.       and produce exact decimal results of up to 18 digits greatly simplifies
  587.       accounting programming. Financial calculations that use power functions
  588.       can take advantage of the 80287's exponentiation and logarithmic
  589.       instructions.
  590.  
  591.    ■  Process control──The 80287 solves dynamic range problems
  592.       automatically, and its extended precision allows control functions to
  593.       be fine-tuned for more accurate and efficient performance. Control
  594.       algorithms implemented with the NPX also contribute to improved
  595.       reliability and safety, while the 80287's speed can be exploited in
  596.       real-time operations.
  597.  
  598.    ■  Computer numerical control (CNC)──The 80287 can move and position
  599.       machine tool heads with accuracy in real-time. Axis positioning also
  600.       benefits from the hardware trigonometric support provided by the 80287.
  601.  
  602.    ■  Robotics──Coupling small size and modest power requirements with
  603.       powerful computational abilities, the NPX is ideal for on-board
  604.       six-axis positioning.
  605.  
  606.    ■  Navigation──Very small, lightweight, and accurate inertial guidance
  607.       systems can be implemented with the 80287. Its built-in trigonometric
  608.       functions can speed and simplify the calculation of position from
  609.  
  610.    ■  Graphics terminals──The 80287 can be used in graphics terminals to
  611.       locally perform many functions that normally demand the attention of a
  612.       main computer; these include rotation, scaling, and interpolation. By
  613.       also using an 82720 Graphics Display Controller to perform high speed
  614.       data transfers, very powerful and highly self-sufficient terminals can
  615.       be built from a relatively small number of 80286 family parts.
  616.  
  617.    ■  Data acquisition──The 80287 can be used to scan, scale, and reduce
  618.       large quantities of data as it is collected, thereby lowering storage
  619.       requirements and time required to process the data for analysis.
  620.  
  621.  The preceding examples are oriented toward traditional numerics
  622.  applications. There are, in addition, many other types of systems that do
  623.  not appear to the end user as computational, but can employ the 80287 to
  624.  advantage. Indeed, the 80287 presents the imaginative system designer with
  625.  an opportunity similar to that created by the introduction of the
  626.  microprocessor itself. Many applications can be viewed as numerically-based
  627.  if sufficient computational power is available to support this view. This
  628.  is analogous to the thousands of successful products that have been built
  629.  around "buried" microprocessors, even though the products themselves bear
  630.  little resemblance to computers.
  631.  
  632.  
  633.  Upgradability
  634.  The architecture of the 80286 CPU is specifically adapted to allow easy
  635.  upgradability to use an 80287, simply by plugging in the 80287 NPX. For this
  636.  reason, designers of 80286 systems may wish to incorporate the 80287 NPX
  637.  into their designs in order to offer two levels of price and performance at
  638.  little additional cost.
  639.  
  640.  Two features of the 80286 CPU make the design and support of upgradable
  641.  80286 systems particularly simple:
  642.  
  643.    ■  The 80286 can be programmed to recognize the presence of an 80287 NPX;
  644.       that is, software can recognize whether it is running on an 80286 or an
  645.       80287 system.
  646.  
  647.    ■  After determining whether the 80287 NPX is available, the 80286 CPU
  648.       can be instructed to let the NPX execute all numeric instructions. If
  649.       an 80287 NPX is not available, the 80286 CPU can emulate all 80287
  650.       numeric instructions in software. This emulation is completely
  651.       transparent to the application software──the same object code may be
  652.       used by both 80286 and 80287 systems. No relinking or recompiling of
  653.       application software is necessary; the same code will simply execute
  654.       faster on the 80287 than on the 80286 system.
  655.  
  656.  To facilitate this design of upgradable 80286 systems, Intel provides a
  657.  software emulator for the 80287 that provides the functional equivalent of
  658.  the 80287 hardware, implemented in software on the 80286. Except for
  659.  timing, the operation of this 80287 emulator (E80287) is the same as for
  660.  the 80287 NPX hardware. When the emulator is combined as part of the
  661.  systems software, the 80286 system with 80287 emulation and the 80286 with
  662.  80287 hardware are virtually indistinguishable to an application program.
  663.  This capability makes it easy for software developers to maintain a single
  664.  set of programs for both systems. System manufacturers can offer the NPX
  665.  as a simple plug-in performance option without necessitating any changes
  666.  in the user's software.
  667.  
  668.  
  669.  Programming Interface
  670.  The 80286/80287 pair is programmed as a single processor; all of the 80287
  671.  registers appear to a programmer as extensions of the basic 80286 register
  672.  set. The 80286 has a class of instructions known as ESCAPE instructions, all
  673.  having a common format. These ESC instructions are numeric instructions for
  674.  the 80287 NPX. These numeric instructions for the 80287 are simply encoded
  675.  into the instruction stream along with 80286 instructions.
  676.  
  677.  All of the CPU memory-addressing modes may be used in programming the NPX,
  678.  allowing convenient access to record structures, numeric arrays, and other
  679.  memory-based data structures. All of the memory management and protection
  680.  features of the CPU are extended to the NPX as well.
  681.  
  682.  Numeric processing in the 80287 centers around the NPX register stack.
  683.  Programmers can treat these eight 80-bit registers as either a fixed
  684.  register set, with instructions operating on explicitly-designated
  685.  registers, or a classical stack, with instructions operating on the top one
  686.  or two stack elements.
  687.  
  688.  Internally, the 80287 holds all numbers in a uniform 80-bit temporary-real
  689.  format. Operands that may be represented in memory as 16-, 32-, or 64-bit
  690.  integers, 32-, 64-, or 80-bit floating-point numbers, or 18-digit packed BCD
  691.  numbers, are automatically converted into temporary-real format as they are
  692.  loaded into the NPX registers. Computation results are subsequently
  693.  converted back into one of these destination data formats when they are
  694.  stored into memory from the NPX registers.
  695.  
  696.  Table 1-2 lists each of the seven data types supported by the 80287,
  697.  showing the data format for each type. All operands are stored in memory
  698.  with the least significant digits starting at the initial (lowest) memory
  699.  address. Numeric instructions access and store memory operands using only
  700.  this initial address. For maximum system performance, all operands should
  701.  start at even memory addresses.
  702.  
  703.  Table 1-3 lists the 80287 instructions by class. No special programming
  704.  tools are necessary to use the 80287, because all of the NPX instructions
  705.  and data types are directly supported by the ASM286 Assembler and Intel's
  706.  appropriate high-level languages.
  707.  
  708.  Software routines for the 80287 may be written in ASM286 Assembler or any
  709.  of the following higher-level languages:
  710.  
  711.    PL/M-286
  712.    PASCAL-286
  713.    FORTRAN-286
  714.    C-286
  715.  
  716.  In addition, all of the development tools supporting the 8086 and 8087 can
  717.  also be used to develop software for the 80286 and 80287 operating in
  718.  Real-Address mode.
  719.  
  720.  All of these high-level languages provide programmers with access to the
  721.  computational power and speed of the 80287 without requiring an
  722.  understanding of the architecture of the 80286 and 80287 chips. Such
  723.  architectural considerations as concurrency and data synchronization are
  724.  handled automatically by these high-level languages. For the ASM286
  725.  programmer, specific rules for handling these issues are discussed in a
  726.  later section of this supplement.
  727.  
  728.  
  729.  Table 1-2. Numeric Data Types
  730.  
  731.                          Significant
  732.  Data Type        Bits     Digits     Approximate Range (Decimal)
  733.                           (Decimal)
  734.  
  735.  Word integer      16        4       -32,768 ≤ X ≤ +32,767
  736.  Short integer     32        9       -2*10^(9) ≤ X ≤ +2*10^(9)
  737.  Long integer      64        18      -9*10^(18) ≤ X ≤ +9*10^(18)
  738.  Packed decimal    80        18      -99...99 ≤ X ≤ +99...99 (18 digits)
  739.  Short real        32        6-7     8.43*10^(-37) ≤ │X│ ≤ 3.37*10^(38)
  740.  Long real         64        15-16   4.19*10^(-307) ≤ │X│ ≤ 1.67*10^(308)
  741.  Temporary real    80        19      3.4*10^(-4932) ≤ │X│ ≤ 1.2*10^(4932)
  742.  
  743.  
  744.  Table 1-3.  Principal NPX Instructions
  745.  
  746.  Class            Instruction Types
  747.  
  748.  Data Transfer    Load (all data types), Store (all data types), Exchange
  749.  
  750.  Arithmetic       Add, Subtract, Multiply, Divide, Subtract Reversed, Divide
  751.                   Reversed, Square Root, Scale, Remainder, Integer Part,
  752.                   Change Sign, Absolute Value, Extract
  753.  
  754.  Comparison       Compare, Examine, Test
  755.  
  756.  Transcendental   Tangent, Arctangent, 2^(X) -1, Y*Log{2}(X+1), Y*Log{2}(X)
  757.  
  758.  Constants        0, 1, π, Log{10}2, Log{e}2, Log{2}10, Log2{e}
  759.  
  760.  Processor        Load Control Word, Store Control Word, Store Status Word,
  761.  
  762.  Control          Load Environment, Store Environment, Save, Restore, Clear
  763.                   Exceptions, Initialize, Set Protected Mode
  764.  
  765.  
  766.  Hardware Interface
  767.  As an extension of the 80286 processor, the 80287 is wired very much in
  768.  parallel with the 80286 CPU. Four special status signals, PEREQ, PEACK,
  769.  BUSY, and ERROR, permit the two processors to coordinate their
  770.  activities. The 80287 NPX also monitors the 80286 S1, S0,
  771.  COD/INTA, READY, HLDA, and CLK pins to monitor the execution of
  772.  ESC instructions (numeric instructions) by the 80286.
  773.  
  774.  As shown in figure 1-2, the 80287 NPX is divided internally into two
  775.  processing elements; the Bus Interface Unit (BIU) and the Numeric Execution
  776.  Unit (NEU). The two units operate independently of one another: the BIU
  777.  receives and decodes instructions, requests operand transfers with memory,
  778.  and executes processor control instructions, whereas the NEU processes
  779.  individual numeric instructions.
  780.  
  781.  The BIU handles all of the status and signal lines between the 80287 and
  782.  the 80286. The NEU executes all instructions that involve the register
  783.  stack. These instructions include arithmetic, logical, transcendental,
  784.  constant, and data transfer instructions. The data path in the NEU is 84
  785.  bits wide (68 fraction bits, 15 exponent bits, and a sign bit), allowing
  786.  internal operand transfers to be performed at very high speeds.
  787.  
  788.  The 80287 executes a single numeric instruction at a time. Before executing
  789.  most ESC instructions, the 80286 tests the BUSY pin and, before initiating
  790.  the command, waits until the 80287 indicates that it is not busy. Once
  791.  initiated, the 80286 continues program execution, while the 80287 executes
  792.  the numeric instruction. Unlike the 8087, which required a WAIT instruction
  793.  to test the BUSY signal before each ESC opcode, these WAIT instructions are
  794.  permissible, but not necessary, in 80287 programs.
  795.  
  796.  In all cases, a WAIT or ESC instruction should be inserted after any 80287
  797.  store to memory (except FSTSW or FSTCW) or load from memory (except FLDENV,
  798.  FLDCW, or FRSTOR) before the 80286 reads or changes the memory value.
  799.  
  800.  When needed, all data transfers between memory and the 80287 NPX are
  801.  performed by the 80286 CPU, using its Processor Extension Data Channel.
  802.  Numeric data transfers performed by the 80286 use the same timing as any
  803.  other bus cycle, and all such transfers come under the supervision of the
  804.  80286 memory management and protection mechanisms. The 80286 Processor
  805.  Extension Data Channel and the hardware interface between the 80286 and
  806.  80287 processors are described in Chapter Six of the 80286 Hardware
  807.  Reference Manual.
  808.  
  809.  From the programmer's perspective, the 80287 can be considered just an
  810.  extension of the 80286 processor. All interaction between the 80286 and the
  811.  80287 processors on the hardware level is handled automatically by the 80286
  812.  and is transparent to the software.
  813.  
  814.  To communicate with the 80287, the 80286 uses the reserved I/O port
  815.  addresses 00F8H, 00FAH, and 00FCH (I/O ports numbered 00F8H through 00FFH
  816.  are reserved for the 80286/80287 interface). These I/O operations are
  817.  performed automatically by the 80286 and are distinct from I/O operations
  818.  that result from program I/O instructions. I/O operations resulting from
  819.  the execution of ESC instructions are completely transparent to software.
  820.  Any program may execute ESCAPE (numeric) instructions, without regard to its
  821.  current I/O Privilege Level (IOPL).
  822.  
  823.  To guarantee correct operation of the 80287, programs must not perform any
  824.  explicit I/O operations to any of the eight ports reserved for the 80287.
  825.  The IOPL of the 80286 can be used to protect the integrity of 80287
  826.  computations in multiuser reprogrammable applications, preventing any
  827.  accidental or other tampering with the 80287 (see Chapter Eight of the 80286
  828.  Operating System Writer's Guide).
  829.  
  830.  
  831.  Figure 1-2.  80287 NPX Block Diagram
  832.  
  833.         ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┬─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
  834.            BUS INTERFACE UNIT                  NUMERIC EXECUTION UNIT
  835.         │                      │
  836.            ┌──────────────┐             EXPONENT BUS        FRACTION BUS
  837.         │  │ CONTROL WORD │    │     ┌──────────┐    ║      ║     ┌───────────
  838.            ├──────────────┤          │ EXPONENT │══║INTER-║═══//PROGRAMMAB
  839.         │  │ STATUS WORD  │    │     │  MODULE  │    ║ FACE ║     //   SHIFTER
  840.            └─────────────┘          └──────────┘    ║═/══║     └──────────
  841.         │        ║             │  ┌────────────┐     ║  16  ║════════════╝
  842.                  ║       NEU      │ MICROCODE  │  16 /      ║═════╗ ┌────────
  843.         │    ┌───────┐INSTRUCTION│CONTROL UNIT│     ║      / 68   ╚│ ARITHME
  844.              │        ╞══════════└────────────┘╔════╣      ║══════╗│   MODUL
  845.         │    │  DATA  │        │        ╔═══════╝ 16 /      / 64    ║└───────
  846.  Data══════│ BUFFER │                 ║ ┌──┐       ║      ║════╗ ╚══════╝
  847.         │    │        │    ┌───│──────┐ ║ │ ┌┐┌───────────┐    ║   ┌───────
  848.              │        │══│ OPERANDS │╝ │ │T││             │(7) ╚══│ TEMPOR
  849.         │    └───────┘    │  QUEUE   │   │ │A││             │ ·      │ REGIST
  850.                  ║─────┐  └───│──────┘   │ │G││             │ ·      └───────
  851.         │  ┌────────┐  │                 │ │ ││  REGISTER   │ ·
  852.  Status═══ CONTROL │  └──────│──────────┘ │W││   STACK     │
  853.         │  │         │                      │O││             │ ·
  854.  Address══  UNIT   │         │            │R││             │
  855.         │  └─────────┘                      │D││─ 80 BITS ─│(0)
  856.                                │            └─┘└─────────────┘
  857.         └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┴─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
  858.  
  859.  
  860.  80287 Numeric Processor Architecture
  861.  To the programmer, the 80287 NPX appears as a set of additional registers
  862.  complementing those of the 80286. These additional registers consist of
  863.  
  864.    ■  Eight individually-addressable 80-bit numeric registers, organized as
  865.       a register stack
  866.  
  867.    ■  Three sixteen-bit registers containing:
  868.         an NPX status word
  869.         an NPX control word
  870.         a tag word
  871.  
  872.    ■  Four 16-bit registers containing the NPX instruction and data pointers
  873.  
  874.  All of the NPX numeric instructions focus on the contents of these NPX
  875.  registers.
  876.  
  877.  
  878.  The NPX Register Stack
  879.  The 80287 register stack is shown in figure 1-3. Each of the eight numeric
  880.  registers in the 80287's register stack is 80 bits wide and is divided into
  881.  fields corresponding to the NPX's temporary-real data type.
  882.  
  883.  Numeric instructions address the data registers relative to the register on
  884.  the top of the stack. At any point in time, this top-of-stack register is
  885.  indicated by the ST (Stack Top) field in the NPX status word. Load or push
  886.  operations decrement ST by one and load a value into the new top register.
  887.  A store-and-pop operation stores the value from the current ST register and
  888.  then increments ST by one. Like 80286 stacks in memory, the 80287 register
  889.  stack grows down toward lower-addressed registers.
  890.  
  891.  Many numeric instructions have several addressing modes that permit the
  892.  programmer to implicitly operate on the top of the stack, or to explicitly
  893.  operate on specific registers relative to the ST. The ASM286 Assembler
  894.  supports these register addressing modes, using the expression ST(0), or
  895.  simply ST, to represent the current Stack Top and ST(i) to specify the ith
  896.  register from ST in the stack (0 ≤ i ≤ 7). For example, if ST contains 011B
  897.  (register 3 is the top of the stack), the following statement would add the
  898.  contents of the top two registers on the stack (registers 3 and 5):
  899.  
  900.    FADD   ST, ST(2)
  901.  
  902.  The stack organization and top-relative addressing of the numeric registers
  903.  simplify subroutine programming by allowing routines to pass parameters on
  904.  the register stack. By using the stack to pass parameters rather than using
  905.  "dedicated" registers, calling routines gain more flexibility in how they
  906.  use the stack. As long as the stack is not full, each routine simply loads
  907.  the parameters onto the stack before calling a particular subroutine to
  908.  perform a numeric calculation. The subroutine then addresses its parameters
  909.  as ST, ST(1), etc., even though ST may, for example, refer to physical
  910.  register 3 in one invocation and physical register 5 in another.
  911.  
  912.  
  913.  Figure 1-3.  80287 Register Set
  914.  
  915.                               80287 STACK:                          TAG FIELD
  916.        79  78    64 63                                           0   1    0
  917.   R1 ╔════╤════════╤══════════════════════════════════════════════╗ ╔══════╗
  918.      ║SIGN│EXPONENT│                  SIGNIFICAND                 ║ ║      ║
  919.   R2 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  920.   R3 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  921.   R4 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  922.   R5 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  923.   R6 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  924.   R7 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  925.   R8 ╟────┼────────┼──────────────────────────────────────────────╢ ╟──────╢
  926.      ╚════╧════════╧══════════════════════════════════════════════╝ ╚══════╝
  927.  
  928.                         15                   0
  929.                         ╔═════════════════════╗
  930.                         ║  CONTROL REGISTER   ║
  931.                         ╟─────────────────────╢
  932.                         ║   STATUS REGISTER   ║
  933.                         ╟─────────────────────╢
  934.                         ║      TAG WORD       ║
  935.                         ╟─────────────────────╢
  936.                         ║                     ║
  937.                         ╟─INSTRUCTION POINTER─╢
  938.                         ║                     ║
  939.                         ╟─────────────────────╢
  940.                         ║                     ║
  941.                         ╟─   DATA POINTER    ─╢
  942.                         ║                     ║
  943.                         ╚═════════════════════╝
  944.  
  945.  
  946.  The NPX Status Word
  947.  The 16-bit status word shown in figure 1-4 reflects the overall state of
  948.  the 80287. This status word may be stored into memory using the
  949.  FSTSW/FNSTSW, FSTENV/FNSTENV, and FSAVE/FNSAVE instructions, and can be
  950.  transferred into the 80286 AX register with the FSTSW AX/FNSTSW AX
  951.  instructions, allowing the NPX status to be inspected by the CPU.
  952.  
  953.  The Busy bit (bit 15) and the BUSY pin indicate whether the 80287's
  954.  execution unit is idle (B = 0) or is executing a numeric instruction or
  955.  signalling an exception (B = 1). (The instructions FNSTSW, FNSTSW AX,
  956.  FNSTENV, and FNSAVE do not set the Busy bit themselves, nor do they require
  957.  the Busy bit to be clear in order to execute.)
  958.  
  959.  The four NPX condition code bits (C{0}-C{3}) are similar to the flags in a
  960.  CPU: the 80287 updates these bits to reflect the outcome of arithmetic
  961.  operations. The effect of these instructions on the condition code bits is
  962.  summarized in table 1-4. These condition code bits are used principally for
  963.  conditional branching. The FSTSWAX instruction stores the NPX status word
  964.  directly into the CPU AX register, allowing these condition codes to be
  965.  inspected efficiently by 80286 code.
  966.  
  967.  Bits 12-14 of the status word point to the 80287 register that is the
  968.  current Stack Top (ST). The significance of the stack top has been described
  969.  in the section on the Register Stack.
  970.  
  971.  Figure 1-4 shows the six error flags in bits 0-5 of the status word. Bit 7
  972.  is the error summary status (ES) bit. ES is set if any unmasked exception
  973.  bits are set, and is cleared otherwise. If this bit is set, the ERROR
  974.  signal is asserted. Bits 0-5 indicate whether the NPX has detected one of
  975.  six possible exception conditions since these status bits were last cleared
  976.  or reset.
  977.  
  978.  
  979.  Table 1-4.  Interpreting the NPX Condition Codes
  980.  
  981. ╓┌───────────────┌─────┌─────┌─────┌──────┌──────────────────────────────────╖
  982.  Instruction
  983.  Type            C{3}  C{2}  C{1}  C{0}   Interpretation
  984.  
  985.  Compare, Test     0     0     X     0    ST > Source or 0 (FTST)
  986.                    0     0     X     1    ST < Source or 0 (FTST)
  987.                    1     0     X     0    ST = Source or 0 (FTST)
  988.                    1     1     X     1    ST is not comparable
  989.  Instruction
  990.  Type            C{3}  C{2}  C{1}  C{0}   Interpretation
  991.                   1     1     X     1    ST is not comparable
  992.  
  993.  Remainder         Q{1} 0   Q{0} Q{2}  Complete reduction with three
  994.                                           low bits of quotient in C{0},
  995.                                           C{3}, and C{1}
  996.                    U    1     U    U   Incomplete Reduction
  997.  
  998.  Examine           0     0     0     0    Valid, positive unnormalized
  999.                    0     0     0     1    Invalid, positive, exponent = 0
  1000.                    0     0     1     0    Valid, negative, unnormalized
  1001.                    0     0     1     1    Invalid, negative, exponent = 0
  1002.                    0     1     0     0    Valid, positive, normalized
  1003.                    0     1     0     1    Infinity, positive
  1004.                    0     1     1     0    Valid, negative, normalized
  1005.                    0     1     1     1    Infinity, negative
  1006.                    1     0     0     0    Zero, positive
  1007.                    1     0     0     1    Empty Register
  1008.                    1     0     1     0    Zero, negative
  1009.                    1     0     1     1    Empty Register
  1010.  Instruction
  1011.  Type            C{3}  C{2}  C{1}  C{0}   Interpretation
  1012.                   1     0     1     1    Empty Register
  1013.                    1     1     0     0    Invalid, positive, exponent = 0
  1014.                    1     1     0     1    Empty Register
  1015.                    1     1     1     0    Invalid, negative, exponent = 0
  1016.                    1     1     1     1    Empty Register
  1017.  
  1018.  
  1019.  
  1020.  Figure 1-4.  80287 Status Word
  1021.  
  1022.    15                                     0
  1023.   ╔═╤══╤═══╤══╤══╤══╤══╤═╤══╤══╤══╤══╤══╤══╗            EXCEPTION FLAGS
  1024.   ║B│C3│S T│C2│C1│C0│ES│X│PE│UE│OE│ZE│DE│IE║                (1 = EXCEPTION
  1025.   ╚╤╧═╤╧╤╤╤╧═╤╧═╤╧═╤╧═╤╧╤╧═╤╧═╤╧═╤╧═╤╧═╤╧═╤╝                 HAS OCCURRED)
  1026.    │  │ │││  │  │  │  │ │  │  │  │  │  │  └───────────  INVALID OPERATION
  1027.    │  │ │││  │  │  │  │ │  │  │  │  │  └──────────────  DENORMALIZED OPERAND
  1028.    │  │ │││  │  │  │  │ │  │  │  │  └─────────────────  ZERO DIVIDE
  1029.    │  │ │││  │  │  │  │ │  │  │  └────────────────────  OVERFLOW
  1030.    │  │ │││  │  │  │  │ │  │  └───────────────────────  UNDERFLOW
  1031.    │  │ │││  │  │  │  │ │  └──────────────────────────  PRECISION
  1032.    │  │ │││  │  │  │  │ └────────────────────────  (RESERVED)
  1033.    │  │ │││  │  │  │  └──────────────────────────  ERROR SUMMARY STATUS
  1034.    │  └─│││──┴──┴──┴─────────────────────────────  CONDITION CODE
  1035.    │    └┴┴──────────────────────────────────────  STACK TOP POINTER
  1036.    └────────────────────────────────────────────── NEU BUSY
  1037.  
  1038.  
  1039.  Control Word
  1040.  The NPX provides the programmer with several processing options, which are
  1041.  selected by loading a word from memory into the control word. Figure 1-5
  1042.  shows the format and encoding of the fields in the control word.
  1043.  
  1044.  The low-order byte of this control word configures the 80287 error and
  1045.  exception masking. Bits 0-5 of the control word contain individual masks for
  1046.  each of the six exception conditions recognized by the 80287. The high-order
  1047.  byte of the control word configures the 80287 processing options, including
  1048.  
  1049.    ■  Precision control
  1050.    ■  Rounding control
  1051.    ■  Infinity control
  1052.  
  1053.  The Precision control bits (bits 8-9) can be used to set the 80287 internal
  1054.  operating precision at less than the default precision (64-bit significand).
  1055.  These control bits can be used to provide compatibility with the
  1056.  earlier-generation arithmetic processors having less precision than the
  1057.  80287, as required by the IEEE 754 standard. Setting a lower precision,
  1058.  however, will not affect the execution time of numeric calculations.
  1059.  
  1060.  The rounding control bits (bits 10-11) provide for directed rounding and
  1061.  true chop as well as the unbiased round-to-nearest-even mode specified in
  1062.  the IEEE 754 standard.
  1063.  
  1064.  The infinity control bit (bit 12) determines the manner in which the 80287
  1065.  treats the special values of infinity. Either affine closure (where positive
  1066.  infinity is distinct from negative infinity) or projective closure (infinity
  1067.  is treated as a single unsigned quantity) may be specified. These two
  1068.  alternative views of infinity are discussed in the section on Computation
  1069.  Fundamentals.
  1070.  
  1071.  
  1072.  Figure 1-5.  80287 Control Word Format
  1073.  
  1074.   ╔═════╤═══╤═══╤═══╤═╤═╤══╤══╤══╤══╤══╤══╗
  1075.   ║X X X│I C│R C│P C│X│X│PM│UM│OM│ZM│DM│IM║    EXCEPTION MASKS
  1076.   ╚╤═╤═╤╧═╤═╧╤═╤╧╤═╤╧╤╧╤╧═╤╧═╤╧═╤╧═╤╧═╤╧═╤╝      (1 = EXCEPTION IS MASKED)
  1077.    │ │ │  │  │ │ │ │ │ │  │  │  │  │  │  └────     INVALID OPERATION
  1078.    │ │ │  │  │ │ │ │ │ │  │  │  │  │  └───────     DENORMALIZED OPERAND
  1079.    │ │ │  │  │ │ │ │ │ │  │  │  │  └──────────     ZERO DIVIDE
  1080.    │ │ │  │  │ │ │ │ │ │  │  │  └─────────────     OVERFLOW
  1081.    │ │ │  │  │ │ │ │ │ │  │  └────────────────     UNDERFLOW
  1082.    │ │ │  │  │ │ │ │ │ │  └───────────────────     PRECISION
  1083.    │ │ │  │  │ │ │ │ │ └────────────────────── (RESERVED)
  1084.    │ │ │  │  │ │ │ │ └──────────────────────── (RESERVED)
  1085.    │ │ │  │  │ │ └─┴────────────────────────── PRECISION CONTROL
  1086.    │ │ │  │  └─┴────────────────────────────── ROUNDING CONTROL
  1087.    │ │ │  └─────────────────────────────────── INFINITY CONTROL
  1088.    │ │ │                                         (0 = PROJECTIVE, 1 = AFFINE)
  1089.    └─┴─┴────────────────────────────────────── (RESERVED)
  1090.  
  1091.  
  1092.  The NPX Tag Word
  1093.  The tag word indicates the contents of each register in the register stack,
  1094.  as shown in figure 1-6. The tag word is used by the NPX itself in order to
  1095.  track its numeric registers and optimize performance. Programmers may use
  1096.  this tag information to interpret the contents of the numeric registers.
  1097.  The tag values are stored in the tag word corresponding to the physical
  1098.  registers 0-7. Programmers must use the current Stack Top (ST) pointer
  1099.  stored in the NPX status word to associate these tag values with the
  1100.  relative stack registers ST(0) through ST(7).
  1101.  
  1102.  
  1103.  Figure 1-6.  80287 Tag Word Format
  1104.  
  1105.    15                                                                    0
  1106.   ╔════════╤════════╤════════╤════════╤════════╤════════╤════════╤════════╗
  1107.   ║ TAG(7) │ TAG(6) │ TAG(5) │ TAG(4) │ TAG(3) │ TAG(2) │ TAG(1) │ TAG(0) ║
  1108.   ╚════════╧════════╧════════╧════════╧════════╧════════╧════════╧════════╝
  1109.   TAG VALUES:
  1110.      00 = VALID;    01 = ZERO;    10 = INVALID OR INFINITY;   11 = EMPTY
  1111.  
  1112.  
  1113.  The NPX Instruction and Data Pointers
  1114.  The NPX instruction and data registers provide support for programmed
  1115.  exception-handlers. Whenever the 80287 executes a math instruction, the NPX
  1116.  internally saves the instruction address, the operand address (if present),
  1117.  and the instruction opcode. The 80287 FSTENV and FSAVE instructions store
  1118.  this data into memory, allowing exception handlers to determine the precise
  1119.  nature of any numeric exceptions that may be encountered.
  1120.  
  1121.  When stored in memory, the instruction and data pointers appear in one of
  1122.  two formats, depending on the operating mode of the 80287. Figure 1-7 shows
  1123.  these pointers as they are stored following an FSTENV instruction. In
  1124.  Real-Address mode, these values are the 20-bit physical address and 11-bit
  1125.  opcode formatted like the 8087. In Protected mode, these values are the
  1126.  32-bit virtual addresses used by the program that executed the ESC
  1127.  instruction.
  1128.  
  1129.  The instruction address saved in the 80287 will point to any prefixes that
  1130.  preceded the instruction. This is different from the 8087, for which the
  1131.  instruction address pointed only to the ESC instruction opcode.
  1132.  
  1133.  
  1134.  Figure 1-7.  80287 Instruction and Data Pointer Image in Memory
  1135.  
  1136.                                                         MEMORY OFFSET
  1137.                        ╔═══════════════════════════════╗
  1138.     REAL MODE          ║         CONTROL WORD          ║ +0
  1139.                        ╟───────────────────────────────╢
  1140.                        ║          STATUS WORD          ║ +2
  1141.                        ╟───────────────────────────────╢
  1142.                        ║           TAG WORD            ║ +4
  1143.                        ╟───────────────────────────────╢
  1144.                        ║   INSTRUCTION POINTER(15-0)   ║ +6
  1145.                        ╟───────────┬─┬─────────────────╢
  1146.                        ║INSTRUCTION│ │   INSTRUCTION   ║
  1147.                        ║  POINTER  │0│     OPCODE      ║ +8
  1148.                        ║  (19-16)  │ │     (10-0)      ║
  1149.                        ╟───────────┴─┴─────────────────╢
  1150.                        ║      DATA POINTER(15-0)       ║ +10
  1151.                        ╟───────────┬───────────────────╢
  1152.                        ║   DATA    │                   ║
  1153.                        ║  POINTER  │         0         ║ +12
  1154.                        ║  (19-16)  │                   ║
  1155.                        ╚═══════════╧═══════════════════╝
  1156.                         15       12 11                0
  1157.  
  1158.                                                         MEMORY OFFSET
  1159.                        ╔═══════════════════════════════╗
  1160.     PROTECTED MODE     ║         CONTROL WORD          ║ +0
  1161.                        ╟───────────────────────────────╢
  1162.                        ║          STATUS WORD          ║ +2
  1163.                        ╟───────────────────────────────╢
  1164.                        ║           TAG WORD            ║ +4
  1165.                        ╟───────────────────────────────╢
  1166.                        ║           IP OFFSET           ║ +6
  1167.                        ╟───────────────────────────────╢
  1168.                        ║          CS SELECTOR          ║ +8
  1169.                        ╟───────────────────────────────╢
  1170.                        ║      DATA OPERAND OFFSET      ║ +10
  1171.                        ╟───────────────────────────────╢
  1172.                        ║     DATA OPERAND SELECTOR     ║ +12
  1173.                        ╚═══════════════════════════════╝
  1174.                         15                            0
  1175.  
  1176.  
  1177.  Computation Fundamentals
  1178.  This section covers 80287 programming concepts that are common to all
  1179.  applications. It describes the 80287's internal number system and the
  1180.  various types of numbers that can be employed in NPX programs. The most
  1181.  commonly used options for rounding, precision, and infinity (selected by
  1182.  fields in the control word) are described, with exhaustive coverage of less
  1183.  frequently used facilities deferred to later sections. Exception conditions
  1184.  that may arise during execution of NPX instructions are also described along
  1185.  with the options that are available for responding to these exceptions.
  1186.  
  1187.  
  1188.  Number System
  1189.  The system of real numbers that people use for pencil and paper
  1190.  calculations is conceptually infinite and continuous. There is no upper or
  1191.  lower limit to the magnitude of the numbers one can employ in a calculation,
  1192.  or to the precision (number of significant digits) that the numbers can
  1193.  represent. When considering any real number, there is always an infinity of
  1194.  numbers both larger and smaller. There is also an infinity of numbers
  1195.  between (i.e., with more significant digits than) any two real numbers. For
  1196.  example, between 2.5 and 2.6 are 2.51, 2.5897, 2.500001, etc.
  1197.  
  1198.  While ideally it would be desirable for a computer to be able to operate on
  1199.  the entire real number system, in practice this is not possible. Computers,
  1200.  no matter how large, ultimately have fixed-size registers and memories that
  1201.  limit the system of numbers that can be accommodated. These limitations
  1202.  determine both the range and the precision of numbers. The result is a set
  1203.  of numbers that is finite and discrete, rather than infinite and continuous.
  1204.  This sequence is a subset of the real numbers that is designed to form a
  1205.  useful approximation of the real number system.
  1206.  
  1207.  Figure 1-8 superimposes the basic 80287 real number system on a real number
  1208.  line (decimal numbers are shown for clarity, although the 80287 actually
  1209.  represents numbers in binary). The dots indicate the subset of real numbers
  1210.  the 80287 can represent as data and final results of calculations. The
  1211.  80287's range is approximately ±4.19*10^(-307) to ±1.67*10^(308).
  1212.  Applications that are required to deal with data and final results outside
  1213.  this range are rare. For reference, the range of the IBM 370 is about
  1214.  ±0.54*10^(-78) to ±0.72*10^(76).
  1215.  
  1216.  The finite spacing in figure 1-8 illustrates that the NPX can represent a
  1217.  great many, but not all, of the real numbers in its range. There is always a
  1218.  gap between two adjacent 80287 numbers, and it is possible for the result of
  1219.  a calculation to fall in this space. When this occurs, the NPX rounds the
  1220.  true result to a number that it can represent. Thus, a real number that
  1221.  requires more digits than the 80287 can accommodate (e.g., a 20-digit
  1222.  number) is represented with some loss of accuracy. Notice also that the
  1223.  80287's representable numbers are not distributed evenly along the real
  1224.  number line. In fact, an equal number of representable numbers exists
  1225.  between successive powers of 2 (i.e., as many representable numbers exist
  1226.  between 2 and 4 as between 65,536 and 131,072). Therefore, the gaps between
  1227.  representable numbers are larger as the numbers increase in magnitude. All
  1228.  integers in the range ±2^(64) (approximately ±10^(18)), however, are exactly
  1229.  representable.
  1230.  
  1231.  In its internal operations, the 80287 actually employs a number system that
  1232.  is a substantial superset of that shown in figure 1-8. The internal format
  1233.  (called temporary real) extends the 80287's range to about ±3.4*10^(-4932)
  1234.  to ±1.2*10^(4932), and its precision to about 19 (equivalent decimal)
  1235.  digits. This format is designed to provide extra range and precision for
  1236.  constants and intermediate results, and is not normally intended for data
  1237.  or final results.
  1238.  
  1239.  From a practical standpoint, the 80287's set of real numbers is
  1240.  sufficiently large and dense so as not to limit the vast majority of
  1241.  microprocessor applications. Compared to most computers, including
  1242.  mainframes, the NPX provides a very good approximation of the real number
  1243.  system. It is important to remember, however, that it is not an exact
  1244.  representation, and that arithmetic on real numbers is inherently
  1245.  approximate.
  1246.  
  1247.  Conversely, and equally important, the 80287 does perform exact arithmetic
  1248.  on integer operands. That is, an operation on two integers returns an exact
  1249.  integral result, provided that the true result is an integer and is in
  1250.  range. For example, 4 ÷ 2 yields an exact integer, 1 ÷ 3 does not, and
  1251.  2^(40) * 2^(30) + 1 does not, because the result requires greater than 64
  1252.  bits of precision.
  1253.  
  1254.  
  1255.  Figure 1-8.  80287 Number System
  1256.  
  1257.  |───NEGATIVE RANGE (NORMALIZED)──|
  1258.  |                                  |
  1259.  |             -5  -4  -3  -2  -1   |
  1260.  ┌───┬───┬─┐┌───┬───┬───┬───┬───┬───┐
  1261.  │   │   │ ││░░░│░░░│▒▒▒│▒▒▒│▓▓▓│███│
  1262.  └───┴───┴─┘└───┴───┴───┴───┴───┴───┘
  1263.                                    
  1264.  │                                  │   ┌───────────────────────────────────┐
  1265.  └-1.67*10^(308)     -4.19*10^(-307)┘   │ ────────────┬──────────────       │
  1266.                                         │ ▓▓▓▓▓▓▓▓▓▓▓▓│▒▒▒▒▒▒▒▒▒▒▒▒▒▒       │
  1267.                                         │ ▓▓▓▓▓▓▓▓▓▓▓▓│▒▒▒▒▒▒▒▒▒▒▒▒▒▒       │
  1268.  |───POSITIVE RANGE (NORMALIZED)──|   │ ────────────────────────       │
  1269.  |                                  |   │                                 │
  1270.  |   1   2   3   4   5              |   │     │──┬──│                     │
  1271.  ┌───┬───┬───┬───┬───┬───┐┌─┬───┬───┐   │     │   │   └ 2.00000000000000000 │
  1272.  │███│▓▓▓│▒▒▒│▒▒▒│░░░│░░░││ │   │   │   │     │   │                         │
  1273.  └───┴───┴───┴───┴───┴───┘└─┴───┴───┘   │     │   └──── (NOT REPRESENTABLE) │
  1274.       └─┬─┘                           │     │                             │
  1275.  │       └────────┐                 │   │     └──────── 1.99999999999999999 │
  1276.  │                │    1.67*10^(308)┘   │   PRECISION:  │── 18 DIGITS ──│ │
  1277.  └4.19*10^(-307)  └─────────────────────┴───────────────────────────────────┘
  1278.  
  1279.  
  1280.  Data Types and Formats
  1281.  The 80287 recognizes seven numeric data types, divided into three classes:
  1282.  binary integers, packed decimal integers, and binary reals. A later section
  1283.  describes how these formats are stored in memory (the sign is always located
  1284.  in the highest-addressed byte). Figure 1-9 summarizes the format of each
  1285.  data type. In the figure, the most significant digits of all numbers (and
  1286.  fields within numbers) are the leftmost digits. Table 1-5 provides the
  1287.  range and number of signficant (decimal) digits that each format can
  1288.  accommodate.
  1289.  
  1290.  
  1291.  Table 1-5.  Real Number Notation
  1292.  
  1293.  ┌───────────────────┬──────────────────────────────────────────────────────┐
  1294.  │     Notation      │                         Value                        │
  1295.  ├───────────────────┼──────────────────────────────────────────────────────┤
  1296.  │Ordinary Decimal   │  178.125                                             │
  1297.  ├───────────────────┼──────────────────────────────────────────────────────┤
  1298.  │Scientific Decimal │  1{}78125E2                                         │
  1299.  ├───────────────────┼──────────────────────────────────────────────────────┤
  1300.  │Scientific Binary  │  1{)0110010001E111                                  │
  1301.  ├───────────────────┼──────────────────────────────────────────────────────┤
  1302.  │Scientific Binary  │  1{}0110010001E10000110                             │
  1303.  │(Biased Exponent)  │                                                      │
  1304.  ├───────────────────┼──────────────────────────────────────────────────────┤
  1305.  │                   │  Sign     Biased Exponent    Significand             │
  1306.  │                   ├──────────────────────────────────────────────────────┤
  1307.  │80287 Short Real   │                                                      │
  1308.  │(Normalized)       │  0        10000110          01100100010000000000000 │
  1309.  │                   │                           └────1{}(implicit)        │
  1310.  └───────────────────┴──────────────────────────────────────────────────────┘
  1311.  
  1312.  
  1313.  Figure 1-9.  Data Formats
  1314.  
  1315.                   ──────── INCREASING SIGNIFICANCE
  1316.             ╔═╤═════════╗
  1317.      WORD   ║S│MAGNITUDE║ (TWO'S
  1318.   INTEGER   ╚═╧═════════╝ COMPLEMENT)
  1319.              15        0
  1320.             ╔═╤══════════════════════╗
  1321.     SHORT   ║S│      MAGNITUDE       ║ (TWO'S
  1322.   INTEGER   ╚═╧══════════════════════╝ COMPLEMENT)
  1323.              31                     0
  1324.             ╔═╤════════════════════════════════════════════════╗
  1325.      LONG   ║S│                   MAGNITUDE                    ║ (TWO'S
  1326.   INTEGER   ╚═╧════════════════════════════════════════════════╝ COMPLEMENT)
  1327.              63                                               0
  1328.             ╔═╤═══╤════════════════════════MAGNITUDE════════════════════════╗
  1329.    PACKED   ║S│ X │d17 d16          d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0║
  1330.   DECIMAL   ╚═╧═══╧═══╧═══╧═══════════╧═══╧═══╧══╧══╧══╧══╧══╧══╧══╧══╧══╧══╝
  1331.              79   72                                                       0
  1332.             ╔═╤════════╤═════════════╗
  1333.     SHORT   ║S│ BIASED │ SIGNIFICAND ║
  1334.      REAL   ║ │EXPONENT│             ║
  1335.             ╚═╧═══════  ════════════╝
  1336.             31        22             0
  1337.             ╔═╤════════════╤══════════════════════════════════╗
  1338.      LONG   ║S│   BIASED   │           SIGNIFICAND            ║
  1339.      REAL   ║ │  EXPONENT  │                                  ║
  1340.             ╚═╧═══════════  ═════════════════════════════════╝
  1341.             63             51                                  0
  1342.             ╔═╤═════════════╤═╤═════════════════════════════════════════════╗
  1343.   TEMPORARY ║S│   BIASED    │1│                  SIGNIFICAND                ║
  1344.   REAL      ║ │  EXPONENT   │ │                                             ║
  1345.             ╚═╧═════════════╧  ════════════════════════════════════════════╝
  1346.             79            64 63                                             0
  1347.  
  1348.   NOTES:
  1349.      S  = Sign bit (0 = positive, 1 = negative)
  1350.      dn = Decimal digit (two per byte)
  1351.      X  = Bits have no significance;
  1352.           80287 ignores when loading, zeros when storing.
  1353.      Exponent Bias (normal values):
  1354.           Short Real:  127  (7FH)
  1355.           Long Real:  1023  (3FFH)
  1356.           Temporary Real:  16383  (3FFFH)
  1357.  
  1358.  
  1359.  Binary Integers
  1360.  The three binary integer formats are identical except for length, which
  1361.  governs the range that can be accommodated in each format. The leftmost bit
  1362.  is interpreted as the number's sign: 0 = positive and 1 = negative. Negative
  1363.  numbers are represented in standard two's complement notation (the binary
  1364.  integers are the only 80287 format to use two's complement). The quantity
  1365.  zero is represented with a positive sign (all bits are 0). The 80287 word
  1366.  integer format is identical to the 16-bit signed integer data type of the
  1367.  80286.
  1368.  
  1369.  
  1370.  Decimal Integers
  1371.  Decimal integers are stored in packed decimal notation, with two decimal
  1372.  digits "packed" into each byte, except the leftmost byte, which carries the
  1373.  sign bit (0 = positive, 1 = negative). Negative numbers are not stored in
  1374.  two's complement form and are distinguished from positive numbers only by
  1375.  the sign bit. The most significant digit of the number is the leftmost
  1376.  digit. All digits must be in the range 0H-9H.
  1377.  
  1378.  
  1379.  Real Numbers
  1380.  The 80287 stores real numbers in a three-field binary format that resembles
  1381.  scientific, or exponential, notation. The number's significant digits are
  1382.  held in the significand field, the exponent field locates the binary point
  1383.  within the significant digits (and therefore determines the number's
  1384.  magnitude), and the sign field indicates whether the number is positive or
  1385.  negative. (The exponent and significand are analogous to the terms
  1386.  "characteristic" and "mantissa" used to describe floating point numbers on
  1387.  some computers.) Negative numbers differ from positive numbers only in the
  1388.  sign bits of their significands.
  1389.  
  1390.  Table 1-5 shows how the real number 178.125 (decimal) is stored in the
  1391.  80287 short real format. The table lists a progression of equivalent
  1392.  notations that express the same value to show how a number can be converted
  1393.  from one form to another. The ASM286 and PL/M-286 language translators
  1394.  perform a similar process when they encounter programmer-defined real number
  1395.  constants. Note that not every decimal fraction has an exact binary
  1396.  equivalent. The decimal number 1/10, for example, cannot be expressed
  1397.  exactly in binary (just as the number 1/3 cannot be expressed exactly in
  1398.  decimal). When a translator encounters such a value, it produces a rounded
  1399.  binary approximation of the decimal value.
  1400.  
  1401.  The NPX usually carries the digits of the significand in normalized form.
  1402.  This means that, except for the value zero, the significand is an integer
  1403.  and a fraction as follows:
  1404.  
  1405.    1{}fff...ff
  1406.  
  1407.  where  indicates an assumed binary point. The number of fraction bits
  1408.  varies according to the real format: 23 for short, 52 for long, and 63 for
  1409.  temporary real. By normalizing real numbers so that their integer bit is
  1410.  always a 1, the 80287 eliminates leading zeros in small values (│X│ < 1).
  1411.  This technique maximizes the number of significant digits that can be
  1412.  accommodated in a significand of a given width. Note that, in the short and
  1413.  long real formats, the integer bit is implicit and is not actually stored;
  1414.  the integer bit is physically present in the temporary real format only.
  1415.  
  1416.  If one were to examine only the signficand with its assumed binary point,
  1417.  all normalized real numbers would have values between 1 and 2. The exponent
  1418.  field locates the actual binary point in the significant digits. Just as in
  1419.  decimal scientific notation, a positive exponent has the effect of moving
  1420.  the binary point to the right, and a negative exponent effectively moves the
  1421.  binary point to the left, inserting leading zeros as necessary. An unbiased
  1422.  exponent of zero indicates that the position of the assumed binary point is
  1423.  also the position of the actual binary point. The exponent field, then,
  1424.  determines a real number's magnitude.
  1425.  
  1426.  In order to simplify comparing real numbers (e.g., for sorting), the 80287
  1427.  stores exponents in a biased form. This means that a constant is added to
  1428.  the true exponent described above. The value of this bias is different for
  1429.  each real format (see figure 1-9). It has been chosen so as to force the
  1430.  biased exponent to be a positive value. This allows two real numbers
  1431.  (of the same format and sign) to be compared as if they are unsigned binary
  1432.  integers. That is, when comparing them bitwise from left to right
  1433.  (beginning with the leftmost exponent bit), the first bit position that
  1434.  differs orders the numbers; there is no need to proceed further with the
  1435.  comparison. A number's true exponent can be determined simply by subtracting
  1436.  the bias value of its format.
  1437.  
  1438.  The short and long real formats exist in memory only. If a number in one of
  1439.  these formats is loaded into an 80287 register, it is automatically
  1440.  converted to temporary real, the format used for all internal operations.
  1441.  Likewise, data in registers can be converted to short or long real for
  1442.  storage in memory. The temporary real format may be used in memory also,
  1443.  typically to store intermediate results that cannot be held in registers.
  1444.  
  1445.  Most applications should use the long real form to store real number data
  1446.  and results; it provides sufficient range and precision to return correct
  1447.  results with a minimum of programmer attention. The short real format is
  1448.  appropriate for applications that are constrained by memory, but it should
  1449.  be recognized that this format provides a smaller margin of safety. It is
  1450.  also useful for debugging algorithms, because roundoff problems will
  1451.  manifest themselves more quickly in this format. The temporary real format
  1452.  should normally be reserved for holding intermediate results, loop
  1453.  accumulations, and constants. Its extra length is designed to shield final
  1454.  results from the effects of rounding and overflow/underflow in intermediate
  1455.  calculations. However, the range and precision of the long real form are
  1456.  adequate for most microcomputer applications.
  1457.  
  1458.  
  1459.  Rounding Control
  1460.  Internally, the 80287 employs three extra bits (guard, round, and sticky
  1461.  bits) that enable it to represent the infinitely precise true result of a
  1462.  computation; these bits are not accessible to programmers. Whenever the
  1463.  destination can represent the infinitely precise true result, the 80287
  1464.  delivers it. Rounding occurs in arithmetic and store operations when the
  1465.  format of the destination cannot exactly represent the infinitely precise
  1466.  true result. For example, a real number may be rounded if it is stored in a
  1467.  shorter real format, or in an integer format. Or, the infinitely precise
  1468.  true result may be rounded when it is returned to a register.
  1469.  
  1470.  The NPX has four rounding modes, selectable by the RC field in the control
  1471.  word (see figure 1-5). Given a true result b that cannot be represented by
  1472.  the target data type, the 80287 determines the two representable numbers a
  1473.  and c that most closely bracket b in value (a < b < c). The processor then
  1474.  rounds (changes) b to a or to c according to the mode selected by the RC
  1475.  field as shown in table 1-6. Round introduces an error in a result that is
  1476.  less than one unit in the last place to which the result is rounded. "Round
  1477.  to nearest" is the default mode and is suitable for most applications; it
  1478.  provides the most accurate and statistically unbiased estimate of the true
  1479.  result. The chop mode is provided for integer arithmetic applications.
  1480.  
  1481.  "Round up" and "round down" are termed directed rounding and can be used to
  1482.  implement interval arithmetic. Interval arithmetic generates a certifiable
  1483.  result independent of the occurrence of rounding and other errors. The upper
  1484.  and lower bounds of an interval may be computed by executing an algorithm
  1485.  twice, rounding up in one pass and down in the other.
  1486.  
  1487.  
  1488.  Table 1-6. Rounding Modes
  1489.  
  1490.  ┌────────┬────────────────────────┬────────────────────────────────────────┐
  1491.  │RC Field│ Rounding Mode          │  Rounding Action                       │
  1492.  ├────────┼────────────────────────┼────────────────────────────────────────┤
  1493.  │   00   │ Round to nearest       │  Closer to b of a or c; if equally     │
  1494.  │        │                        │  close, select even number (the one    │
  1495.  │        │                        │  whose least significant bit is zero). │
  1496.  │        │                        │                                        │
  1497.  │   01   │ Round down (toward -∞) │ a                                      │
  1498.  │        │                        │                                        │
  1499.  │   10   │ Round up (toward +∞)   │ c                                      │
  1500.  │        │                        │                                        │
  1501.  │   11   │ Chop (toward 0)        │  Smaller in magnitude of a or c        │
  1502.  └────────┴────────────────────────┴────────────────────────────────────────┘
  1503.  
  1504.  ───────────────────────────────────────────────────────────────────────────
  1505.  NOTE
  1506.    a < b < c; a and c are representable, b is not.
  1507.  ───────────────────────────────────────────────────────────────────────────
  1508.  
  1509.  
  1510.  Precision Control
  1511.  The 80287 allows results to be calculated with either 64, 53, or 24 bits of
  1512.  precision in the significand as selected by the precision control (PC) field
  1513.  of the control word. The default setting, and the one that is best suited
  1514.  for most applications, is the full 64 bits of significance provided by the
  1515.  temporary-real format. The other settings are required by the proposed IEEE
  1516.  standard, and are provided to obtain compatibility with the specifications
  1517.  of certain existing programming languages. Specifying less precision
  1518.  nullifies the advantages of the temporary real format's extended fraction
  1519.  length, and does not increase execution speed. When reduced precision is
  1520.  specified, the rounding of the fractional value clears the unused bits on
  1521.  the right to zeros.
  1522.  
  1523.  
  1524.  Infinity Control
  1525.  The 80287's system of real numbers may be closed by either of two models of
  1526.  infinity. These two means of closing the number system, projective and
  1527.  affine closure, are illustrated schematically in figure 1-10. The setting
  1528.  of the IC field in the control word selects one model or the other. The
  1529.  default means of closure is projective, and this is recommended for most
  1530.  computations. When projective closure is selected, the NPX treats the
  1531.  special values +∞ and -∞ as a single unsigned infinity (similar to its
  1532.  treatment of signed zeros). In the affine mode the NPX respects the signs
  1533.  of +∞ and -∞.
  1534.  
  1535.  While affine mode may provide more information than projective, there are
  1536.  occasions when the sign may in fact represent misinformation. For example,
  1537.  consider an algorithm that yields an intermediate result x of +0 and -0 (the
  1538.  same numeric value) in different executions. If 1/x were then computed in
  1539.  affine mode, two entirely different values (+∞ and -∞) would result from
  1540.  numerically identical values of x. Projective mode, on the other hand,
  1541.  provides less information but never returns misinformation. In general,
  1542.  then, projective mode should be used globally, with affine mode reserved
  1543.  for local computations where the programmer can take advantage of the sign
  1544.  and knows for certain that the nature of the computations will not produce a
  1545.  misleading result.
  1546.  
  1547.  
  1548.  Figure 1-10.  Projective versus Affine Closure
  1549.  
  1550.               PROJECTIVE CLOSURE                AFFINE CLOSURE
  1551.  
  1552.                       ∞
  1553.                 ┌────────┐
  1554.                 │           │
  1555.               - │           │ +            -∞      -       +     +∞
  1556.                 │           │              ──────────┼──────────
  1557.                 └─────┼─────┘                          0
  1558.                       0
  1559.  
  1560.  
  1561.  Special Computational Situations
  1562.  Besides being able to represent positive and negative numbers, the 80287
  1563.  data formats may be used to describe other entities. These special values
  1564.  provide extra flexibility, but most users will not need to understand them
  1565.  in order to use the 80287 successfully. This section describes the special
  1566.  values that may occur in certain cases and the significance of each. The
  1567.  80286 exceptions are also described, for writers of exception handlers and
  1568.  for those interested in probing the limits of computation using the 80287.
  1569.  
  1570.  The material presented in this section is mainly of interest to programmers
  1571.  concerned with writing exception handlers. For many readers, this section
  1572.  can be browsed lightly.
  1573.  
  1574.  
  1575.  Special Numeric Values
  1576.  The 80287 data formats encompass encodings for a variety of special values
  1577.  in addition to the typical real or integer data values that result from
  1578.  normal calculations. These special values have significance and can express
  1579.  relevant information about the computations or operations that produced
  1580.  them. The various types of special values are
  1581.  
  1582.    ■  Non-normal real numbers, including
  1583.         denormals
  1584.         unnormals
  1585.  
  1586.    ■  Zeros and pseudo zeros
  1587.  
  1588.    ■  Positive and negative infinity
  1589.  
  1590.    ■  NaN (Not-a-Number)
  1591.  
  1592.    ■  Indefinite
  1593.  
  1594.  The following description explains the origins and significance of each of
  1595.  these special values. Tables 1-12 through 1-15 at the end of this
  1596.  section show how each of these special values is encoded for each of the
  1597.  numeric data types.
  1598.  
  1599.  
  1600.  Nonnormal Real Numbers
  1601.  As described previously, the 80287 generally stores nonzero real numbers in
  1602.  normalized floating-point form; that is, the integer (leading) bit of the
  1603.  significand is always a 1. This bit is explicitly stored in the temporary
  1604.  real format, and is implicitly assumed to be a one (1{}) in the short- and
  1605.  long-real formats. Since leading zeros are eliminated, normalized storage
  1606.  allows the maximum number of significant digits to be held in a significand
  1607.  of a given width.
  1608.  
  1609.  When a floating-point numeric value becomes very close to zero, normalized
  1610.  storage cannot be used to express the value accurately. To accommodate these
  1611.  instances, the 80287 can store and operate on reals that are not normalized,
  1612.  i.e., whose significands contain one or more leading zeros. Nonnormals
  1613.  typically arise when the result of a calculation yields a value that is too
  1614.  small to be represented in normal form.
  1615.  
  1616.  Nonnormal values can exist in one of two forms:
  1617.  
  1618.    ■  The floating-point exponent may be stored at its most negative value
  1619.       (a Denormal),
  1620.  
  1621.    ■  The integer bit (and perhaps other leading bits) of the significand
  1622.       may be zero (an Unnormal).
  1623.  
  1624.  The leading zeros of nonnormals permit smaller numbers to be represented,
  1625.  at the cost of some lost precision (the number of significant bits is
  1626.  reduced by the leading zeros). In typical algorithms, extremely small values
  1627.  are most likely to be generated as intermediate, rather than final results.
  1628.  By using the NPX's temporary real format for holding intermediate, values as
  1629.  small as ±3.4*10^(-4932) can be represented; this makes the occurrence of
  1630.  nonnormal numbers a rare phenomenon in 80287 applications. Nevertheless, the
  1631.  NPX can load, store, and operate on nonnormalized real numbers when they do
  1632.  occur.
  1633.  
  1634.  
  1635.  Denormals and Gradual Underflow
  1636.  A denormal is the result of the NPX's response to an underflow exception
  1637.  when that exception has been masked by the programmer (see the 80287 control
  1638.  word, figure 1-5). Underflow occurs when the absolute value of a real
  1639.  number becomes too small to be represented in the destination format, that
  1640.  is, when the exponent of the true result is too negative to be represented
  1641.  in the destination format. For example, a true exponent of -130 will cause
  1642.  underflow if the destination is short real, because -126 is the smallest
  1643.  exponent this format can accommodate. No underflow would occur if the
  1644.  destination were long real or temporary real, since these formats can handle
  1645.  exponents down to -1023 and -16,383, respectively.
  1646.  
  1647.  Most computers underflow "abruptly:" they simply return a zero result,
  1648.  which is likely to produce an unacceptable final result if computation
  1649.  continues. The 80287, on the other hand, underflows "gradually" when the
  1650.  underflow exception is masked. Gradual underflow is accomplished by
  1651.  denormalizing the result until it is just within the exponent range of the
  1652.  destination format. Denormalizing means incrementing the true result's
  1653.  exponent and inserting a corresponding leading zero in the significand,
  1654.  shifting the rest of the significand one place to the right. Denormal
  1655.  values may occur in any of the short-real, long-real, or temporary-real
  1656.  formats. Table 1-7 illustrates how a result might be denormalized to fit a
  1657.  short-real destination.
  1658.  
  1659.  The intent of the 80287's masked response to underflow is to allow
  1660.  computation to continue without program intervention, while introducing an
  1661.  error that carries about the same risk of contaminating the final result as
  1662.  roundoff error. Roundoff (precision) errors occur frequently in real number
  1663.  calculations; sometimes they spoil the result of computation, but often they
  1664.  do not. Recognizing that roundoff errors are often nonfatal, computation
  1665.  usually proceeds, and the programmer inspects the final results to see if
  1666.  these errors have had a significant effect. The 80287's masked underflow
  1667.  response allows programmers to treat underflows in a similar manner; the
  1668.  computation continues and the programmer can examine the final result to
  1669.  determine if an underflow has had important consequences. (If the underflow
  1670.  has had a significant effect, an invalid operation will probably be
  1671.  signalled later in the computation.)
  1672.  
  1673.  Denormalization produces a denormal or a zero. Denormals are readily
  1674.  identified by their exponents, which are always the minimum for their
  1675.  formats; in biased form, this is always the bit string: 00...00. This same
  1676.  exponent value is also assigned to the zeros, but a denormal has a nonzero
  1677.  significand. A denormal in a register is tagged special. Tables 1-14 and
  1678.  1-15 later in this chapter show how denormal values are encoded in each of
  1679.  the real data formats.
  1680.  
  1681.  The denormalization process may cause the loss of low-order significand
  1682.  bits as they are shifted off the right. In a severe case, all the
  1683.  significand bits of the true result are shifted out and replaced by the
  1684.  leading zeros. In this case, the result of denormalization is a true zero,
  1685.  and if the value is in a register, it is tagged as such. However, this is a
  1686.  comparatively rare occurrence and, in any case, is no worse than "abrupt"
  1687.  underflow.
  1688.  
  1689.  Denormals are rarely encountered in most applications. Typical debugged
  1690.  algorithms generate extremely small results during the evaluation of
  1691.  intermediate subexpressions; the final result is usually of an appropriate
  1692.  magnitude for its short or long real destination. If intermediate results
  1693.  are held in temporary real, as is recommended, the great range of this
  1694.  format makes underflow very unlikely. Denormals are likely to arise only
  1695.  when an application generates a great many intermediates, so many that they
  1696.  cannot be held on the register stack or in temporary real memory variables.
  1697.  If storage limitations force the use of short or long reals for
  1698.  intermediates, and small values are produced, underflow may occur, and, if
  1699.  masked, may generate denormals.
  1700.  
  1701.  Accessing a denormal may produce an exception as shown in table 1-8. (The
  1702.  denormalized exception signals that a denormal has been fetched.) Denormals
  1703.  may have reduced significance due to lost low-order bits, and an option of
  1704.  the proposed IEEE standard precludes operations on nonnormalized operands.
  1705.  This option may be implemented in the form of an exception handler that
  1706.  responds to unmasked denormalized exceptions. Most users will mask this
  1707.  exception so that computation may proceed; any loss of accuracy will be
  1708.  analyzed by the user when the final result is delivered.
  1709.  
  1710.  As table 1-8 shows, the division and remainder operations do not accept
  1711.  denormal divisors and raise the invalid operation exception. Recall also
  1712.  that the transcendental instructions require normalized operands and do not
  1713.  check for exceptions. In all other cases, the NPX converts denormals to
  1714.  unnormals, and the rules governing unnormal arithmetic then apply
  1715.  (unnormals are described in the following section).
  1716.  
  1717.  
  1718.  Table 1-7. Denormalization Process
  1719.  
  1720.  ┌──────────────────┬────────┬────────────┬───────────────────────────┐
  1721.  │Operation         │  Sign  │  Exponent │    Significand            │
  1722.  │──────────────────┼────────┼────────────┼───────────────────────────┤
  1723.  │True Result       │    0   │    -129    │    1{}01011100...00      │
  1724.  │Denormalize       │    0   │    -128    │    0{}101011100...00     │
  1725.  │Denormalize       │    0   │    -127    │    0{}0101011100...00    │
  1726.  │Denormalize       │    0   │    -126    │    0{}00101011100...00   │
  1727.  │Denormal Result  │    0   │    -126    │    0{}00101011100...00   │
  1728.  └──────────────────┴────────┴────────────┴───────────────────────────┘
  1729.  
  1730.  
  1731.  
  1732.  Table 1-8. Exceptions Due to Denormal Operands
  1733.  
  1734.  ┌─────────────────────────────┬───────────┬──────────────────────────────┐
  1735.  │Operation                    │ Exception │   Masked Response            │
  1736.  ├─────────────────────────────┼───────────┼──────────────────────────────┤
  1737.  │FLD (short/long real)        │   D       │  Load as equivalent unnormal │
  1738.  ├─────────────────────────────┼───────────┼──────────────────────────────┤
  1739.  │Arithmetic (except following)│   D       │  Convert (in a work area)    │
  1740.  │                             │           │  denormal to equivalent      │
  1741.  │                             │           │  unnormal and proceed        │
  1742.  ├─────────────────────────────┼───────────┼──────────────────────────────┤
  1743.  │Compare and test             │   D       │  Convert (in a work area)    │
  1744.  │                             │           │  denormal to equivalent      │
  1745.  │                             │           │  unnormal and proceed        │
  1746.  ├─────────────────────────────┼───────────┼──────────────────────────────┤
  1747.  │Division or FPREM with       │   I       │  Return real indefinite      │
  1748.  │denormal divisor             │           │                              │
  1749.  └─────────────────────────────┴───────────┴──────────────────────────────┘
  1750.  
  1751.  
  1752.  Unnormals──Descendents of Denormal Operands
  1753.  An unnormal is the result of a computation using denormal operands and is
  1754.  therefore the descendent of the 80287's masked underflow response. An
  1755.  unnormal may exist only in the temporary real format; it may have any
  1756.  exponent that a normal value may have (that is, in biased form any nonzero
  1757.  value), but it is distinguished from a normal by the integer bit of its
  1758.  significand, which is always 0. An unnormal in a register is tagged valid.
  1759.  Unnormals are distinct from denormals, which have an exponent of 00...00 in
  1760.  biased form.
  1761.  
  1762.  Unnormals allows arithmetic to continue following an underflow while still
  1763.  retaining their identity as numbers that may have reduced significance. That
  1764.  is, unnormal operands generate unnormal results, so long as their
  1765.  unnormality has a significant effect on the result. Unnormals are thus
  1766.  prevented from "masquerading" as normals, numbers that have full
  1767.  significance. On the other hand, if an unnormal has an insignificant effect
  1768.  on a calculation with a normal, the result will be normal. For example,
  1769.  adding a small unnormal to a large normal yields a normal result. The
  1770.  converse situation yields an unnormal.
  1771.  
  1772.  Table 1-9 shows how the instruction set deals with unnormal operands. Note
  1773.  that the unnormal may be the original operand or a temporary created by the
  1774.  80287 from a denormal.
  1775.  
  1776.  
  1777.  Table 1-9. Unnormal Operands and Results
  1778.  
  1779. ╓┌──────────────────────────────────┌────────────────────────────────────────
  1780.  Operation                          Result
  1781.  
  1782.  Addition/subtraction               Normalization of operand with larger
  1783.                                     abosolute value determines normalization
  1784.                                     of result.
  1785.  
  1786.  Multiplication                     If either operand is unnormal, result
  1787.  Operation                          Result
  1788.  
  1789. Multiplication                     If either operand is unnormal, result
  1790.                                     is unormal.
  1791.  
  1792.  Division (unnormal dividend only)  Result is unnormal.
  1793.  
  1794.  FPREM (unnormal dividend only)     Result if normalized.
  1795.  
  1796.  Division/FPREM (unnormal           Signal invalid operation.
  1797.                                     divisor)
  1798.  
  1799.  Compare/FTST                       Normalize as much as possible before
  1800.                                     making comparison.
  1801.  
  1802.  FRNDINT                            Normalize as much as possible before
  1803.                                     rounding.
  1804.  
  1805.  FSQRT                              Signal invalid operation.
  1806.  
  1807.  FST, FSTP (short/long real         If value is above destination's underflow
  1808.  Operation                          Result
  1809.  
  1810. FST, FSTP (short/long real         If value is above destination's underflow
  1811.  destination)                       boundary, then signal invalid operation;
  1812.                                     else signal underflow.
  1813.  
  1814.  FSTP (temporary real destination)  Store as usual.
  1815.  
  1816.  FIST, FISTP, FBSTP                 Signal invalid operation.
  1817.  
  1818.  FLD                                Load as usual.
  1819.  
  1820.  FXCH                               Exchange as usual.
  1821.  
  1822.  Transcendental instructions        Undefined; operands must be normal and
  1823.                                     are not checked.
  1824.  
  1825.  
  1826.  Zeros and Pseudo Zeros
  1827.  The value zero in the real and decimal integer formats may be signed either
  1828.  positive or negative, although the sign of a binary integer zero is always
  1829.  positive. For computational purposes, the value of zero always behaves
  1830.  identically, regardless of sign, and typically the fact that a zero may be
  1831.  signed is transparent to the programmer. If necessary, the FXAM instruction
  1832.  may be used to determine a zero's sign.
  1833.  
  1834.  The zeros discussed above are called true zeros; if one of them is loaded
  1835.  or generated in a register, the register is tagged zero. Table 1-10 lists
  1836.  the results of instructions executed with zero operands and also shows how a
  1837.  true zero may be created from nonzero operands.
  1838.  
  1839.  Only the temporary real format may contain a special class of values called
  1840.  pseudo zeros. A pseudo zero is an unnormal whose significand is all zeros,
  1841.  but whose (biased) exponent is nonzero (true zeros have a zero exponent).
  1842.  Neither is a pseudo zero's exponent all ones, since this encoding is
  1843.  reserved for infinities and NANs. A pseudo zero result will be produced if
  1844.  two unnormals, containing a total of more than 64 leading zero bits in their
  1845.  significands, are multiplied together. This is a remote possibility in most
  1846.  applications, but it can happen.
  1847.  
  1848.  Pseudo zero operands behave like unnormals, except in the following cases
  1849.  where they produce the same results as true zeros:
  1850.  
  1851.    ■  Compare and test instructions
  1852.  
  1853.    ■  FRNDINT (round to integer)
  1854.  
  1855.    ■  Division, where the dividend is either a true zero or a pseudo zero
  1856.       (the divisor is a pseudo zero)
  1857.  
  1858.  In addition and subtraction of a pseudo zero and a true zero or another
  1859.  pseudo zero, the pseudo zero(s) behaves like unnormals, except for the
  1860.  determination of the result's sign. The sign is determined as shown in table
  1861.  1-10 for two true zero operands.
  1862.  
  1863.  
  1864.  Infinity
  1865.  The real formats support signed representations of infinities. These values
  1866.  are encoded with a biased exponent of all ones and a significand of
  1867.  1{}00...00; if the infinity is in a register, it is tagged special. The
  1868.  significand distinguishes infinities from NANs, including real indefinite.
  1869.  
  1870.  A programmer may code an infinity, or it may be created by the NPX as its
  1871.  masked response to an overflow or a zero divide exception. Note that when
  1872.  rounding is up or down, the masked response may create the largest valid
  1873.  value representable in the destination rather than infinity. See table 1-11
  1874.  for details. As operands, infinities behave somewhat differently depending
  1875.  on how the infinity control field in the control word is set (see table
  1876.  1-12). When the projective model of infinity is selected, the infinities
  1877.  behave as a single unsigned representation; because of this, infinity
  1878.  cannot be compared with any value except infinity. In affine mode, the signs
  1879.  of the infinities are observed, and comparisons are possible.
  1880.  
  1881.  
  1882.  Table 1-10. Zero Operands and Results
  1883.  
  1884. ╓┌───────────────────────────┌───────────────────┌───────────────────────┌───
  1885.  Operation/Operands          Result              Operation/Operands      Resul
  1886.  
  1887.  FLD, FBLD                                       Division
  1888.   +0                         +0                   ±0 ÷ ±0                Inval
  1889.   -0                         -0                   ±X ÷ ±0                Zerod
  1890.  FILD                                            +0 ÷ +X, -0 ÷ -X       +0
  1891.   +0                         +0                   +0 ÷ -X, -0 ÷ +X       -0
  1892.  Operation/Operands          Result              Operation/Operands      Resul
  1893.  +0                         +0                   +0 ÷ -X, -0 ÷ +X       -0
  1894.  FST, FSTP                                        -X ÷ -Y, +X ÷ +Y       +0, u
  1895.  
  1896.  
  1897.  
  1898.   +0                         +0                   -X ÷ +Y, +X ÷ -Y       -0, u
  1899.  
  1900.  
  1901.  
  1902.   -0                         -0
  1903.   +X                        +0                  FPREM
  1904.   -X                        -0                   ±0 rem ±0              Inval
  1905.  FBSTP                                            ±X rem ±0              Inval
  1906.   +0                         +0                   +0 rem +X, +0 rem -X   +0
  1907.   -0                         -0                   -0 rem +X, -0 rem -X   -0
  1908.  FIST, FISTP                                      +X rem +Y, +X rem -Y   +0
  1909.  
  1910.  
  1911.  
  1912.   +0                         +0                   -X rem -Y, -X rem +Y   -0
  1913.  Operation/Operands          Result              Operation/Operands      Resul
  1914.  +0                         +0                   -X rem -Y, -X rem +Y   -0
  1915.  
  1916.  
  1917.  
  1918.   -0                         +0
  1919.   +X                        +0                  FSQRT
  1920.   -X                        +0                   -0                     -0
  1921.                                                   +0                     +0
  1922.  Addition
  1923.   +0 plus +0                 +0                  Compare
  1924.   -0 plus -0                 -0                   ±0: +X                 A < B
  1925.   +0 plus -0, -0 plus +0     *0                  ±0: ±0                 A = B
  1926.   -X plus +X, +X plus -X     *0                  ±0: -X                 A > B
  1927.   ±0 plus ±X, ±X plus ±0     ┼X
  1928.  
  1929.  
  1930.  
  1931.                                                  FTST
  1932.  Subtraction                                      ±0                     Zero
  1933.   +0 minus -0                +0                  FCHS
  1934.  Operation/Operands          Result              Operation/Operands      Resul
  1935.  +0 minus -0                +0                  FCHS
  1936.   -0 minus +0                -0                   +0                     -0
  1937.   +0 minus +0, -0 minus -0   *0                  -0                     +0
  1938.   +X minus +X, -X minus -X   *0                 FABS
  1939.   ±0 minus ±X, ±X minus ±0   ┼X                  ±0                     +0
  1940.                                                  F2XM1
  1941.  Multiplication                                   +0                     +0
  1942.   +0 * +0, -0 * -0           +0                   -0                     -0
  1943.   +0 * -0, -0 * +0           -0                  FRNDINT
  1944.   +0 * +X, +X * +0           +0                   +0                     +0
  1945.   +0 * -X, -X * +0           -0                   -0                     -0
  1946.   -0 * +X, +X * -0           -0                  FXTRACT
  1947.   -0 * -X, -X * -0           +0                   +0                     Both
  1948.   +X * +Y, -X * -Y           +0, underflow       -0                     Both
  1949.   +X * -Y, -X * +Y           -0, underflow
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  NaN (Not a Number)
  1955.  A NaN (Not a Number) is a member of a class of special values that exist in
  1956.  the real formats only. A NaN has an exponent of 11..11B, may have either
  1957.  sign, and may have any significand except 1{}00..00B, which is assigned to
  1958.  the infinities. A NaN in a register is tagged special.
  1959.  
  1960.  The 80287 will generate the special NaN, real indefinite, as its masked
  1961.  response to an invalid operation exception. This NaN is signed negative; its
  1962.  significand is encoded 1{}100..00. All other NaNs represent
  1963.  programmer-created values.
  1964.  
  1965.  Whenever the NPX uses an operand that is a NaN, it signals an invalid
  1966.  operation exception in its status word. If this exception is masked in the
  1967.  80287 control word, the 80287's masked exception response is to return the
  1968.  NaN as the operation result. If both operands of an instruction are NaNs,
  1969.  the result is the NaN with the larger absolute value. In this way, a NaN
  1970.  that enters a computation propagates through the computation and will
  1971.  eventually be delivered as the final result. Note, however, that the
  1972.  transcendental instructions do not check their operands, and a NaN will
  1973.  produce an undefined result.
  1974.  
  1975.  By unmasking the invalid operation exception, the programmer can use NaNs
  1976.  to trap to the exception handler. The generality of this approach and the
  1977.  large number of NaN values that are available provide the sophisticated
  1978.  programmer with a tool that can be applied to a variety of special
  1979.  situations.
  1980.  
  1981.  For example, a compiler could use NaNs as references to uninitialized
  1982.  (real) array elements. The compiler could preinitialize each array element
  1983.  with a NaN whose significand contained the index (relative position) of the
  1984.  element. If an application program attempted to access an element that it
  1985.  had not initialized, it would use the NaN placed there by the compiler. If
  1986.  the invalid operation exception were unmasked, an interrupt would occur, and
  1987.  the exception handler would be invoked. The exception handler could
  1988.  determine which element had been accessed, since the operand address field
  1989.  of the exception pointers would point to the NaN, and the NaN would contain
  1990.  the index number of the array element.
  1991.  
  1992.  NaNs could also be used to speed up debugging. In its early testing phase,
  1993.  a program often contains multiple errors. An exception handler could be
  1994.  written to save diagnostic information in memory whenever it was invoked.
  1995.  After storing the diagnostic data, it could supply a NaN as the result of
  1996.  the erroneous instruction, and that NaN could point to its associated
  1997.  diagnostic area in memory. The program would then continue, creating a
  1998.  different NaN for each error. When the program ended, the NaN results could
  1999.  be used to access the diagnostic data saved at the time the errors
  2000.  occurred. Many errors could thus be diagnosed and corrected in one test run.
  2001.  
  2002.  
  2003.  Table 1-11. Masked Overflow Response with Directed Rounding
  2004.  
  2005.  ┌───────────────────┬──────────┬───────────────────────────────────────────┐
  2006.  │    True Result    │          │                                           │
  2007.  ├──────────────┬────┤ Rounding │         Result Delivered                  │
  2008.  │Normalization │Sign│   Mode   │                                           │
  2009.  ├──────────────┼────┼──────────┼───────────────────────────────────────────┤
  2010.  │Normal        │ +  │  Up      │ +∞                                        │
  2011.  │Normal        │ +  │  Down    │ Largest finite positive number           │
  2012.  │Normal        │ -  │  Up      │ Largest finite negative number           │
  2013.  │Normal        │ -  │  Down    │ -∞                                        │
  2014.  │Unnormal      │ +  │  Up      │ +∞                                        │
  2015.  │Unnormal      │ -  │  Down    │ Largest exponent, result's significand   │
  2016.  │Unnormal      │ +  │  Up      │ Largest exponent, result's significand   │
  2017.  │Unnormal      │ -  │  Down    │ -∞                                        │
  2018.  └──────────────┴────┴──────────┴───────────────────────────────────────────┘
  2019.  
  2020.  
  2021.  Table 1-12. Infinity Operands and Results
  2022.  
  2023. ╓┌───────────────────┌───────────────────────────────┌───────────────────────╖
  2024.  Key to symbols used in this table
  2025.  
  2026.  Operation           Projective Result               Affine Result
  2027.  
  2028.  Addition
  2029.   +∞ plus +∞         Invalid operation               +∞
  2030.   -∞ plus -∞         Invalid operation               -∞
  2031.   +∞ plus -∞         Invalid operation               Invalid operation
  2032.   -∞ plus +∞         Invalid operation               Invalid operation
  2033.   ±∞ plus ±X         *∞                              *∞
  2034.   ±X plus ±∞         *∞                              *∞
  2035.  
  2036.  Subtraction
  2037.   +∞ minus -∞        Invalid operation               +∞
  2038.   -∞ minus +∞        Invalid operation               -∞
  2039.  Key to symbols used in this table
  2040.  
  2041.  Operation           Projective Result               Affine Result
  2042.  -∞ minus +∞        Invalid operation               -∞
  2043.   +∞ minus +∞        Invalid operation               Invalid operation
  2044.   -∞ minus -∞        Invalid operation               Invalid operation
  2045.   ±∞ minus ±X        *∞                              *∞
  2046.   ±X minus ±∞        ┼∞                              ┼∞
  2047.  
  2048.  Multiplication
  2049.   ±∞ * ±∞            Φ                               Φ
  2050.   ±∞ * ±Y            Φ                               Φ
  2051.   ±0 * ±∞, ±∞ * ±0   Invalid operation               Invalid operation
  2052.  
  2053.  Division
  2054.   ±∞ ÷ ±∞            Invalid operation               Invalid operation
  2055.   ±∞ ÷ ±X            Φ                               Φ
  2056.   ±X ÷ ±∞            Φ                               Φ
  2057.  
  2058.  FSQRT
  2059.   -∞                 Invalid operation               Invalid operation
  2060.  Key to symbols used in this table
  2061.  
  2062.  Operation           Projective Result               Affine Result
  2063.  -∞                 Invalid operation               Invalid operation
  2064.   +∞                 Invalid operation               +∞
  2065.  
  2066.  FPREM
  2067.   ±∞ rem ±∞          Invalid operation               Invalid operation
  2068.   ±∞ rem ±X          Invalid operation               Invalid operation
  2069.   ±Y rem ±∞          *Y                              *Y
  2070.   ±0 rem ±∞          *0                              *0
  2071.  
  2072.  FRNDINT
  2073.   ±∞                 *∞                              *∞
  2074.  
  2075.  FSCALE
  2076.   ±∞ scaled by ±∞    Invalid operation               Invalid operation
  2077.   ±∞ scaled by ±X    *∞                              *∞
  2078.   ±0 scaled by ±∞    *0                              *0
  2079.   ±Y scaled by ±     Invalid operation               Invalid operation
  2080.  
  2081.  Key to symbols used in this table
  2082.  
  2083.  Operation           Projective Result               Affine Result
  2084. 
  2085.  FXTRACT
  2086.   ±∞                 Invalid operation               Invalid operation
  2087.  
  2088.  Compare
  2089.   ±∞: ±∞             A = B                           -∞ < +∞
  2090.   ±∞: ±Y             A ? B (and) invalid operation   -∞ < Y < +∞
  2091.   ±∞: ±0             A ? B (and) invalid operation   -∞ < 0 < +∞
  2092.  
  2093.  FTST
  2094.   ±∞                 A ? B (and) invalid operation   *∞
  2095.  
  2096.  
  2097.  Indefinite
  2098.  For every 80287 numeric data type, one unique encoding is reserved for
  2099.  representing the special value indefinite. The 80287 produces this encoding
  2100.  as its response to a masked invalid-operation exception. In the case of
  2101.  reals, the indefinite value can be stored and loaded like any NaN, and it
  2102.  always retains its special identity; programmers are advised not to use this
  2103.  encoding for any other purpose. Packed decimal indefinite may be stored by
  2104.  the NPX in a FBSTP instruction; attempting to use this encoding in a FBLD
  2105.  instruction, however, will have an undefined result. In the binary
  2106.  integers, the same encoding may represent either indefinite or the largest
  2107.  negative number supported by the format (-2^(15), -2^(31), or -2^(63)). The
  2108.  80287 will store this encoding as its masked response to an invalid
  2109.  operation, or when the value in a source register represents or rounds to
  2110.  the largest negative integer representable by the destination. In situations
  2111.  where its origin may be ambiguous, the invalid operation exception flag can
  2112.  be examined to see if the value was produced by an exception response. When
  2113.  this encoding is loaded, or used by an integer arithmetic or compare
  2114.  operation, it is always interpreted as a negative number; thus indefinite
  2115.  cannot be loaded from a packed decimal or binary integer.
  2116.  
  2117.  
  2118.  Encoding of Data Types
  2119.  Tables 1-13 through 1-16 show how each of the special values just
  2120.  described is encoded for each of the numeric data types. In these tables,
  2121.  the least-significant bits are shown to the right and are stored in the
  2122.  lowest memory addresses. The sign bit is always the left-most bit of the
  2123.  highest-addressed byte.
  2124.  
  2125.  
  2126.  Table 1-13. Binary Integer Encodings
  2127.  
  2128.                Class                   Sign         Magnitude
  2129.      ┌────────────────────────────────────────────────────────────
  2130.      │         (Largest)                0            11...11
  2131.      │                                  ∙               ∙
  2132.  Positives                              ∙               ∙
  2133.      │                                  ∙               ∙
  2134.      │         (Smallest)               0            00...01
  2135.      └────────────────────────────────────────────────────────────
  2136.                 Zero                    0            00...00
  2137.      ┌────────────────────────────────────────────────────────────
  2138.      │         (Smallest)               1            11...11
  2139.      │                                  ∙               ∙
  2140.  Negatives                              ∙               ∙
  2141.      │                                  ∙               ∙
  2142.      │         (Largest/Indefinite)    1            00...00
  2143.      └────────────────────────────────────────────────────────────
  2144.                                      Word:        ───15 bits───
  2145.                                      Short:       ───31 bits───
  2146.                                      Long:        ───63 bits───
  2147.  
  2148.  
  2149.  Table 1-14. Packed Decimal Encodings
  2150.  
  2151. ╓┌──────────────────────────┌───────────────┌────────────────────────────────
  2152.  
  2153.                                             ┌─────────────────── Magnitude ───
  2154.              Class          Sign             digit      digit      digit
  2155.      ┌────────────────────────────────────────────────────────────────────────
  2156.      │       (Largest)      0       0000000  1 0 0 1    1 0 0 1    1 0 0 1
  2157.      │                      ∙          ∙                              ∙
  2158.      │                      ∙          ∙                              ∙
  2159.  Positives                  ∙          ∙                              ∙
  2160.      │       (Smallest)     0       0000000  0 0 0 0    0 0 0 0    0 0 0 0
  2161.      │
  2162.      │       Zero           0       0000000  0 0 0 0    0 0 0 0    0 0 0 0
  2163.      └────────────────────────────────────────────────────────────────────────
  2164.      ┌────────────────────────────────────────────────────────────────────────
  2165.  
  2166.                                             ┌─────────────────── Magnitude ───
  2167.              Class          Sign             digit      digit      digit
  2168.     ┌────────────────────────────────────────────────────────────────────────
  2169.      │       Zero           1       0000000  0 0 0 0    0 0 0 0    0 0 0 0
  2170.      │
  2171.      │       (Smallest)     1       0000000  0 0 0 0    0 0 0 0    0 0 0 0
  2172.  Negatives                  ∙          ∙                              ∙
  2173.      │                      ∙          ∙                              ∙
  2174.      │                      ∙          ∙                              ∙
  2175.      │       (Largest)      1       0000000  1 0 0 1    1 0 0 1    1 0 0 1
  2176.      └────────────────────────────────────────────────────────────────────────
  2177.         Indefinite         1       1111111  1 1 1 1    1 1 1 1    U U U U
  2178.                             ──── 1 byte ───  ──────────────────────── 9 bytes
  2179.  
  2180.  
  2181.  Table 1-15. Real and Long Real Encodings
  2182.  
  2183. ╓┌───────────────────────────────┌────────┌───────────┌──────────────────────╖
  2184.                                            Biased      Significand
  2185.  
  2186.                                            Biased      Significand
  2187.  
  2188.              Class                Sign     Exponent    {}ff...ff
  2189.     ┌──────────────────────────────────────────────────────────────
  2190.     │                  NaNs        0       11...11     11...11
  2191.     │                              ∙          ∙           ∙
  2192.     │                              ∙          ∙           ∙
  2193.     │                              ∙          ∙           ∙
  2194.     │                              0       11...11     00...01
  2195.     │      ────────────────────────────────────────────────────────
  2196.     │                  ∞           0       11...11     00...00
  2197.     │      ┌───────────────────────────────────────────────────────
  2198.     │      │           Normals     0       11...10     11...11
  2199.     │      │                       ∙          ∙           ∙
  2200.  Positives │                       ∙          ∙           ∙
  2201.     │      │                       ∙          ∙           ∙
  2202.     │      │                       0       00...01     00...00
  2203.     │      │         ──────────────────────────────────────────────
  2204.     │    Reals         Denormals   0       00...00     11...11
  2205.     │      │                       ∙          ∙           ∙
  2206.     │      │                       ∙          ∙           ∙
  2207.                                            Biased      Significand
  2208.  
  2209.              Class                Sign     Exponent    {}ff...ff
  2210.    │      │                       ∙          ∙           ∙
  2211.     │      │                       ∙          ∙           ∙
  2212.     │      │                       0       00...00     00...01
  2213.     │      │         ──────────────────────────────────────────────
  2214.     │      │           Zero        0       00...00     00...00
  2215.     └──────────────────────────────────────────────────────────────
  2216.     ┌──────────────────────────────────────────────────────────────
  2217.     │      │           Zero        1       00...00     00...00
  2218.     │      │         ──────────────────────────────────────────────
  2219.     │      │           Denormals   1       00...00     00...01
  2220.     │      │                       ∙          ∙           ∙
  2221.     │      │                       ∙          ∙           ∙
  2222.     │    Reals                     ∙          ∙           ∙
  2223.     │      │                       1       00...00     11...11
  2224.     │      │         ──────────────────────────────────────────────
  2225.     │      │           Normals     1       00...01     00...00
  2226.     │      │                       ∙          ∙           ∙
  2227.     │      │                       ∙          ∙           ∙
  2228.                                            Biased      Significand
  2229.  
  2230.              Class                Sign     Exponent    {}ff...ff
  2231.    │      │                       ∙          ∙           ∙
  2232.     │      │                       ∙          ∙           ∙
  2233.     │      │                       1       11...10     11...11
  2234.  Negatives └───────────────────────────────────────────────────────
  2235.     │                  ∞           1       11...11     00...00
  2236.     │      ┌───────────────────────────────────────────────────────
  2237.     │      │                       1       11...11     00...01
  2238.     │      │                       ∙          ∙           ∙
  2239.     │    NaNs                      ∙          ∙           ∙
  2240.     │      │                       ∙          ∙           ∙
  2241.     │      │         ──────────────────────────────────────────────
  2242.     │      │           Indefinite  1       11...11     10...00
  2243.     │      └───────────────────────────────────────────────────────
  2244.     │                              ∙          ∙           ∙
  2245.     │                              ∙          ∙           ∙
  2246.     │                              ∙          ∙           ∙
  2247.     │                              1       11...11     11...11
  2248.     └──────────────────────────────────────────────────────────────
  2249.                                            Biased      Significand
  2250.  
  2251.              Class                Sign     Exponent    {}ff...ff
  2252.    └──────────────────────────────────────────────────────────────
  2253.                                Short:  │ ───8 bits── │ ──23 bits── │
  2254.                                 Long:  │ ──11 bits── │ ──52 bits── │
  2255.  
  2256.  
  2257.  Table 1-16. Temporary Real Encodings
  2258.  
  2259. ╓┌───────────────────────────────────────┌──────────┌────────────────────────╖
  2260.                                          Biased     Significand
  2261.  
  2262.              Class              Sign     Exponent   1{}ff...ff
  2263.      ┌─────────────────────────────────────────────────────────
  2264.      │         NaNs              0       11...11    111...11
  2265.      │                           ∙          ∙          ∙
  2266.      │                           ∙          ∙          ∙
  2267.      │                           ∙          ∙          ∙
  2268.      │                           0       11...11    100...01
  2269.      │      ────────────────────────────────────────────────────
  2270.                                          Biased     Significand
  2271.  
  2272.              Class              Sign     Exponent   1{}ff...ff
  2273.     │      ────────────────────────────────────────────────────
  2274.      │         ∞                 0       11...11    100...00
  2275.      │      ┌────────────────────────────────────────────────────
  2276.      │      │                    0       11...10    Normals
  2277.      │      │                    ∙          ∙       111...11
  2278.      │      │                    ∙          ∙          ∙
  2279.      │      │                    ∙          ∙          ∙
  2280.      │      │                    ∙          ∙          ∙
  2281.      │      │                    ∙          ∙          ∙
  2282.      │      │                    ∙          ∙       100...00
  2283.      │      │                    ∙          ∙     ──────────────
  2284.  Positives  │                    ∙          ∙       Unnormals
  2285.      │      │                    ∙          ∙       011...11
  2286.      │    Reals                  ∙          ∙          ∙
  2287.      │      │                    ∙          ∙          ∙
  2288.      │      │                    ∙          ∙          ∙
  2289.      │      │                    0       00...01    000...00
  2290.      │      │                                     ──────────────
  2291.                                          Biased     Significand
  2292.  
  2293.              Class              Sign     Exponent   1{}ff...ff
  2294.     │      │                                     ──────────────
  2295.      │      │                                       Denormals
  2296.      │      │                    0       00...00    011...11
  2297.      │      │                    ∙          ∙          ∙
  2298.      │      │                    ∙          ∙          ∙
  2299.      │      │                    ∙          ∙          ∙
  2300.      │      │                    0       00...00    000...01
  2301.      │      ├───────────────────────────────────────────────────
  2302.      │      │        Zero        0       00...00    000...00
  2303.      └──────────────────────────────────────────────────────────
  2304.      ┌──────────────────────────────────────────────────────────
  2305.      │      │        Zero        1       00...00    000...00
  2306.      │      ├───────────────────────────────────────────────────
  2307.      │      │                                       Denormals
  2308.      │      │                    1       00...00    000...01
  2309.      │      │                    ∙          ∙          ∙
  2310.      │      │                    ∙          ∙          ∙
  2311.      │      │                    ∙          ∙          ∙
  2312.                                          Biased     Significand
  2313.  
  2314.              Class              Sign     Exponent   1{}ff...ff
  2315.     │      │                    ∙          ∙          ∙
  2316.      │      │                    1       00...00    011...11
  2317.      │      │                                     ──────────────
  2318.      │      │                    1       00...01    Unnormals
  2319.      │      │                    ∙          ∙       000...00
  2320.      │      │                    ∙          ∙          ∙
  2321.      │    Reals                  ∙          ∙          ∙
  2322.      │      │                    ∙          ∙          ∙
  2323.      │      │                    ∙          ∙       011...11
  2324.      │      │                    ∙          ∙
  2325.      │      │                                     ──────────────
  2326.  Negatives  │                    ∙          ∙       Normals
  2327.      │      │                    ∙          ∙       100...00
  2328.      │      │                    ∙          ∙          ∙
  2329.      │      │                    ∙          ∙          ∙
  2330.      │      │                    ∙          ∙          ∙
  2331.      │      │                    1       11...10    11111...11
  2332.      │      └────────────────────────────────────────────────────
  2333.                                          Biased     Significand
  2334.  
  2335.              Class              Sign     Exponent   1{}ff...ff
  2336.     │      └────────────────────────────────────────────────────
  2337.      │         ∞                 1       11...11    100...00
  2338.      │      ┌───────────────────────────────────────────────────
  2339.      │      │                    1       11...11    100...00
  2340.      │      │                    ∙          ∙          ∙
  2341.      │      │                    ∙          ∙          ∙
  2342.      │      │                    ∙          ∙          ∙
  2343.      │      │         ──────────────────────────────────────────
  2344.      │     NaNs      Indefinite  1       11...11    110...00
  2345.      │      │         ──────────────────────────────────────────
  2346.      │      │                    ∙          ∙          ∙
  2347.      │      │                    ∙          ∙          ∙
  2348.      │      │                    ∙          ∙          ∙
  2349.      │      │                    1       11...11    111...11
  2350.      └──────┴───────────────────────────────────────────────────
  2351.                                       │──15 bits──│──64 bits──│
  2352.  
  2353.  
  2354.  Numeric Exceptions
  2355.  Whenever the 80287 NPX attempts a numeric operation with invalid operands
  2356.  or produces a result that cannot be represented, the 80287 recognizes a
  2357.  numeric exception condition. Altogether, the 80287 checks for the following
  2358.  six classes of exceptions while executing numeric instructions:
  2359.  
  2360.    1.  Invalid operation
  2361.    2.  Divide-by-zero
  2362.    3.  Denormalized operand
  2363.    4.  Numeric overflow
  2364.    5.  Numeric underflow
  2365.    6.  Inexact result (precision)
  2366.  
  2367.  
  2368.  Invalid Operation
  2369.  The 80287 reports an invalid operation if any of the following occurs:
  2370.  
  2371.    ■  An attempt to load a register that is not empty (stack overflow).
  2372.  
  2373.    ■  An attempt to pop an operand from an empty register (stack underflow).
  2374.  
  2375.    ■  An operand is a NaN.
  2376.  
  2377.    ■  The operands cause the operation to be indeterminate (square root of a
  2378.       negative number, 0/0).
  2379.  
  2380.  An invalid operation generally indicates a program error.
  2381.  
  2382.  
  2383.  Zero Divisor
  2384.  If an instruction attempts to divide a finite nonzero operand by zero, the
  2385.  80287 will report a zero divide exception.
  2386.  
  2387.  
  2388.  Denormalized Operand
  2389.  If an instruction attempts to operate on a denormal, the NPX reports the
  2390.  denormalized operand exception. This exception allows users to implement in
  2391.  software an option of the proposed IEEE standard specifying that operands
  2392.  must be prenormalized before they are used.
  2393.  
  2394.  
  2395.  Numeric Overflow and Underflow
  2396.  If the exponent of a numeric result is too large for the destination real
  2397.  format, the 80287 signals a numeric overflow. Conversely, if the exponent of
  2398.  a result is too small to be represented in the destination format, a numeric
  2399.  underflow is signaled. If either of these exceptions occur, the result of
  2400.  the operation is outside the range of the destination real format.
  2401.  
  2402.  Typical algorithms are most likely to produce extremely large and small
  2403.  numbers in the calculation of intermediate, rather than final, results.
  2404.  Because of the great range of the temporary real format (recommended as the
  2405.  destination format for intermediates), overflow and underflow are
  2406.  relatively rare events in most 80287 applications.
  2407.  
  2408.  
  2409.  Inexact Result
  2410.  If the result of an operation is not exactly representable in the
  2411.  destination format, the 80287 rounds the number and reports the precision
  2412.  exception. For example, the fraction 1/3 cannot be precisely represented in
  2413.  binary form. This exception occurs frequently and indicates that some
  2414.  (generally acceptable) accuracy has been lost; it is provided for
  2415.  applications that need to perform exact arithmetic only.
  2416.  
  2417.  
  2418.  Handling Numeric Errors
  2419.  When numeric errors occur, the NPX takes one of two possible courses of
  2420.  action:
  2421.  
  2422.    ■  The NPX can itself handle the error, producing the most reasonable
  2423.       result and allowing numeric program execution to continue undisturbed.
  2424.  
  2425.    ■  A software exception handler can be invoked by the CPU to handle the
  2426.       error.
  2427.  
  2428.  Each of the six exception conditions described above has a corresponding
  2429.  flag bit in the 80287 status word and a mask bit in the 80287 control word.
  2430.  If an exception is masked (the corresponding mask bit in the control
  2431.  word = 1), the 80287 takes an appropriate default action and continues with
  2432.  the computation. If the exception is unmasked (mask = 0), the 80287 asserts
  2433.  the ERROR output to the 80286 to signal the exception and invoke a
  2434.  software exception handler.
  2435.  
  2436.  The NPX reports an exception by setting the corresponding flag in the NPX
  2437.  status word to 1. The NPX then checks the corresponding exception mask in
  2438.  the control word to determine if it should "field" the exception (mask = 1),
  2439.  or if it should signal the exception to the CPU to invoke a software
  2440.  exception handler (mask = 0).
  2441.  
  2442.  If the mask is set, the exception is said to be masked (from user
  2443.  software), and the NPX executes its on-chip masked response for that
  2444.  exception. If the mask is not set (mask = 0), the exception is unmasked,
  2445.  and the NPX performs its unmasked response. The masked response always
  2446.  produces a standard result, then proceeds with the instruction. The unmasked
  2447.  response always traps to a software exception handler, allowing the CPU to
  2448.  recognize and take action on the exception. Table 1-17 gives a complete
  2449.  description of all exception conditions and the NPX's masked response.
  2450.  
  2451.  Note that when exceptions are masked, the NPX may detect multiple
  2452.  exceptions in a single instruction, because it continues executing the
  2453.  instruction after performing its masked response. For example, the 80287
  2454.  could detect a denormalized operand, perform its masked response to this
  2455.  exception, and then detect an underflow.
  2456.  
  2457.  
  2458.  Table 1-17. Exception Conditions and Masked Responses
  2459.  
  2460. ╓┌──────────────────────────────────────┌────────────────────────────────────╖
  2461.  ───────────────────────────────────────────────────────────────────────────
  2462.        Condition                                         Masked Response
  2463.  ───────────────────────────────────────────────────────────────────────────
  2464.                               Invalid Operation
  2465.  ───────────────────────────────────────────────────────────────────────────
  2466.  Source register is tagged empty        Return real indefinite.
  2467.  (usually due to stack underflow).
  2468.  
  2469.  Destination register is not tagged     Return real indefinite
  2470.  empty (usually due to stack            (overwrite destination value).
  2471.  overflow).
  2472.  
  2473.  One or both operands is a NaN.         Return NaN with larger absolute
  2474.                                         value (ignore signs).
  2475.  
  2476.  (Compare and test operations only):    Set condition codes "not
  2477.  one or both operands is a NaN.         comparable."
  2478.  
  2479.  (Addition operations only): closure    Return real indefinite.
  2480.  ───────────────────────────────────────────────────────────────────────────
  2481.        Condition                                         Masked Response
  2482.  ───────────────────────────────────────────────────────────────────────────
  2483.                               Invalid Operation
  2484.  ───────────────────────────────────────────────────────────────────────────
  2485. (Addition operations only): closure    Return real indefinite.
  2486.  is affine and operands are
  2487.  opposite-signed infinities; or
  2488.  closure is projective and both
  2489.  operands are ∞ (signs immaterial).
  2490.  
  2491.  (Subtraction operations only):         Return real indefinite.
  2492.  closure is affine and operands are
  2493.  like-signed infinities; or closure
  2494.  is projective and both operands are
  2495.  ∞ (signs immaterial).
  2496.  
  2497.  (Multiplication operations only):      Return real indefinite.
  2498.  ∞ * 0; or 0 * ∞.
  2499.  
  2500.  (Division operations only):            Return real indefinite.
  2501.  ───────────────────────────────────────────────────────────────────────────
  2502.        Condition                                         Masked Response
  2503.  ───────────────────────────────────────────────────────────────────────────
  2504.                               Invalid Operation
  2505.  ───────────────────────────────────────────────────────────────────────────
  2506. (Division operations only):            Return real indefinite.
  2507.  ∞ ÷ ∞; or 0 ÷ 0; or 0 ÷ pseudo
  2508.  zero; or divisor is denormal
  2509.  or unormal.
  2510.  
  2511.  (FPREM instruction only): modulus      Return real indefinite, set
  2512.  (divisor) is unnormal or denormal;     condition code = "complete
  2513.  or dividend is ∞.                      remainder."
  2514.  
  2515.  (FSQRT instruction only): operand      Return real indefinite.
  2516.  is nonzero and negative; or operand
  2517.  is denormal or unnormal; or closure
  2518.  is affine and operand is -∞; or
  2519.  closure is projective and operand
  2520.  is ∞.
  2521.  
  2522.  ───────────────────────────────────────────────────────────────────────────
  2523.        Condition                                         Masked Response
  2524.  ───────────────────────────────────────────────────────────────────────────
  2525.                               Invalid Operation
  2526.  ───────────────────────────────────────────────────────────────────────────
  2527. 
  2528.  (Compare operations only): closure     Set condition code = "not
  2529.  is projective and ∞ is being           comparable."
  2530.  compared with 0, a normal or ∞.
  2531.  
  2532.  (FTST instruction only): closure is    Set condition code = "not
  2533.  projective and operand is ∞.           comparable."
  2534.  
  2535.  (FIST, FISTP instructions only):       Store integer indefinite.
  2536.  source register is empty, a NaN,
  2537.  denormal, unnormal, ∞, or exceeds
  2538.  representable range of destination.
  2539.  
  2540.  (FBSTP instruction only): source       Stored packed decimal
  2541.  register is empty, a NaN, denormal,    indefinite.
  2542.  unnormal, ∞, or exceeds 18 decimal
  2543.  ───────────────────────────────────────────────────────────────────────────
  2544.        Condition                                         Masked Response
  2545.  ───────────────────────────────────────────────────────────────────────────
  2546.                               Invalid Operation
  2547.  ───────────────────────────────────────────────────────────────────────────
  2548. unnormal, ∞, or exceeds 18 decimal
  2549.  digits.
  2550.  
  2551.  (FST, FSTP instructions only):         Store real indefinite.
  2552.  destination is short or long real
  2553.  and source register is an unnormal
  2554.  with exponent in range.
  2555.  
  2556.  (FXCH instruction only): one or        Change empty register(s) to
  2557.  both registers is tagged empty.        real indefinite and then
  2558.                                         perform exchange.
  2559.  
  2560.  
  2561. ╓┌──────────────────────────────────────┌────────────────────────────────────╖
  2562.  ───────────────────────────────────────────────────────────────────────────
  2563.        Condition                                         Masked Response
  2564.  ───────────────────────────────────────────────────────────────────────────
  2565.        Condition                                         Masked Response
  2566.  ───────────────────────────────────────────────────────────────────────────
  2567.                               Denormalized Operand
  2568.  ───────────────────────────────────────────────────────────────────────────
  2569.  (FLD instruction only): source         No special action; load as usual.
  2570.  operand is denormal.
  2571.  
  2572.  (Arithmetic operations only): one      Convert (in a work area) the
  2573.  or both operands is denormal.          operand to the equivalent unnormal
  2574.                                         and proceed.
  2575.  
  2576.  (Compare and test operations only):    Convert (in a work area) any
  2577.  one or both operands is denormal       denormal to the equivalent
  2578.  or unnormal other than pseudo          unnormal; normalize as much as
  2579.  zero).                                 possible, and proceed with
  2580.                                         operation.
  2581.  ───────────────────────────────────────────────────────────────────────────
  2582.                                   Zero Divide
  2583.  ───────────────────────────────────────────────────────────────────────────
  2584.  (Division operations only):            Return ∞ signed with "exclusive or"
  2585.  ───────────────────────────────────────────────────────────────────────────
  2586.        Condition                                         Masked Response
  2587.  ───────────────────────────────────────────────────────────────────────────
  2588. (Division operations only):            Return ∞ signed with "exclusive or"
  2589.  divisor = 0.                           of operand signs.
  2590.  ───────────────────────────────────────────────────────────────────────────
  2591.                                    Overflow
  2592.  ───────────────────────────────────────────────────────────────────────────
  2593.  (Arithmetic operations only):          Return properly signed ∞ and signal
  2594.  rounding is nearest or chop, and       precision exception.
  2595.  exponent of true result > 16,383.
  2596.  
  2597.  (FST, FSTP instructions only):         Return properly signed ∞ and signal
  2598.  rounding is nearest or chop, and       precision exception.
  2599.  exponent of true result > +127
  2600.  (short real destination) or > +1023
  2601.  (long real destination).
  2602.  ───────────────────────────────────────────────────────────────────────────
  2603.                                   Underflow
  2604.  ───────────────────────────────────────────────────────────────────────────
  2605.  (Arithmetic operations only):          Denormalize until exponent rises to
  2606.  ───────────────────────────────────────────────────────────────────────────
  2607.        Condition                                         Masked Response
  2608.  ───────────────────────────────────────────────────────────────────────────
  2609. (Arithmetic operations only):          Denormalize until exponent rises to
  2610.  exponent of true result < -16,382      -16,382 (true), round significand
  2611.  (true).                                to 64 bits. If denormalized rounded
  2612.                                         significand = 0, then return true
  2613.                                         0; else, return denormal (tag =
  2614.                                         special, biased exponent = 0).
  2615.  
  2616.  (FST, FSTP instructions only):         Denormalize until exponent rises to
  2617.  destination is short real and          -126 (true), round significand to
  2618.  exponent of true result < -126         24 bits, store true 0 if
  2619.  (true).                                denormalized rounded significand = 0;
  2620.                                         else, store denormal (biased
  2621.                                         exponent = 0).
  2622.  
  2623.  (FST, FSTP instructions only):         Denormalize until exponent rises to
  2624.  destination is long real and           -1022 (true), round significand to
  2625.  exponent of true result < -1022        53 bits, store true 0 if rounded
  2626.  (true).                                denormalized significand = 0; else,
  2627.  ───────────────────────────────────────────────────────────────────────────
  2628.        Condition                                         Masked Response
  2629.  ───────────────────────────────────────────────────────────────────────────
  2630. (true).                                denormalized significand = 0; else,
  2631.                                         store denormal (biased exponent = 0).
  2632.  ───────────────────────────────────────────────────────────────────────────
  2633.                                 Precision
  2634.  ───────────────────────────────────────────────────────────────────────────
  2635.  True rounding error occurs.            No special action.
  2636.  
  2637.  Masked response to overflow            No special action.
  2638.  exception earlier in instruction.
  2639.  
  2640.  
  2641.  Automatic Exception Handling
  2642.  As described in the previous section, when the 80287 NPX encounters an
  2643.  exception condition whose corresponding mask bit in the NPX control word is
  2644.  set, the NPX automatically performs an internal fix-up (masked-exception)
  2645.  response. The 80287 NPX has a default fix-up activity for every possible
  2646.  exception condition it may encounter. These masked-exception responses are
  2647.  designed to be safe and are generally acceptable for most numeric
  2648.  applications.
  2649.  
  2650.  As an example of how even severe exceptions can be handled safely and
  2651.  automatically using the NPX's default exception responses, consider a
  2652.  calculation of the parallel resistance of several values using only the
  2653.  standard formula (figure 1-11). If R{1} becomes zero, the circuit
  2654.  resistance becomes zero. With the divide-by-zero and precision exceptions
  2655.  masked, the 80287 NPX will produce the correct result.
  2656.  
  2657.  By masking or unmasking specific numeric exceptions in the NPX control
  2658.  word, NPX programmers can delegate responsibility for most exceptions to the
  2659.  NPX, reserving the most severe exceptions for programmed exception handlers.
  2660.  Exception-handling software is often difficult to write, and the NPX's
  2661.  masked responses have been tailored to deliver the most reasonable result
  2662.  for each condition. For the majority of applications, programmers will find
  2663.  that masking all exceptions other than Invalid Operation will yield
  2664.  satisfactory results with the least programming effort. An Invalid
  2665.  Operation exception normally indicates a fatal error in a program that must
  2666.  be corrected; this exception should not normally be masked.
  2667.  
  2668.  The exception flags in the NPX status word provide a cumulative record of
  2669.  exceptions that have occurred since these flags were last cleared. Once set,
  2670.  these flags can be cleared only by executing the FCLEX (clear exceptions)
  2671.  instruction, by reinitializing the NPX, or by overwriting the flags with an
  2672.  FRSTOR or FLDENV instruction. This allows a programmer to mask all
  2673.  exceptions (except invalid operation), run a calculation, and then inspect
  2674.  the status word to see if any exceptions were detected at any point in the
  2675.  calculation.
  2676.  
  2677.  
  2678.  Figure 1-11.  Arithmetic Example Using Infinity
  2679.  
  2680.        │                          │
  2681.        │                          │
  2682.        │           R{1}           │
  2683.        █─────────/\/\/\/──────────█                            1
  2684.        │                          │      EQUIVALENT   =   ────────────
  2685.        │                          │      RESISTANCE        1    1    1
  2686.        │           R{2}           │                       ── + ── + ──
  2687.        █─────────/\/\/\/──────────█                      R{1} R{2}  R{3}
  2688.        │                          │
  2689.        │                          │
  2690.        │           R{3}           │
  2691.        └─────────/\/\/\/──────────┘
  2692.  
  2693.  
  2694.  Software Exception Handling
  2695.  If the NPX encounters an unmasked exception condition, it signals the
  2696.  exception to the 80286 CPU using the ERROR status line between the two
  2697.  processors.
  2698.  
  2699.  The next time the 80286 CPU encounters a WAIT or ESC instruction in its
  2700.  instruction stream, the 80286 will detect the active condition of the
  2701.  ERROR status line and automatically trap to an exception response
  2702.  routine using interrupt #16──the Processor Extension Error exception.
  2703.  
  2704.  This exception response routine is typically a part of the systems
  2705.  software. Typical exception responses may include:
  2706.  
  2707.    ■  Incrementing an exception counter for later display or printing
  2708.  
  2709.    ■  Printing or displaying diagnostic information (e.g., the 80287
  2710.       environment and registers)
  2711.  
  2712.    ■  Aborting further execution
  2713.  
  2714.    ■  Using the exception pointers to build an instruction that will run
  2715.       without exception andexecuting it
  2716.  
  2717.  Application programmers on 80286 systems having systems software support
  2718.  for the 80287 NPX should consult their references for the appropriate system
  2719.  response to NPX exceptions. For systems programmers, specific details on
  2720.  writing software exception handlers are included in the section
  2721.  "System-Level Numeric Programming" later in this manual.
  2722.  
  2723.  The 80287 NPX differs from the 8087 NPX in the manner in which numeric
  2724.  exceptions are signalled to the CPU; the 8087 requires an interrupt
  2725.  controller (8259A) to interrupt the CPU, while the 80287 does not.
  2726.  Programmers upgrading 8087 software to operate on an 80287 should be aware
  2727.  of these differences and any implications they might have on numeric
  2728.  exception-handling software. Appendix B explains the differences between
  2729.  the 80287 and the 8087 NPX in greater detail.
  2730.  
  2731.  
  2732.  Chapter 2  Programming Numeric Applications
  2733.  
  2734.  ───────────────────────────────────────────────────────────────────────────
  2735.  
  2736.  Programmers developing applications for the 80287 have a wide range of
  2737.  instructions and programming alternatives from which to choose.
  2738.  
  2739.  The following sections describe the 80287 instruction set in detail, and
  2740.  follow up with a discussion of several of the programming facilities that
  2741.  are available to programmers of 80287.
  2742.  
  2743.  
  2744.  The 80287 NPX Instruction Set
  2745.  This section describes the operation of all 80287 instructions. Within this
  2746.  section, the instructions are divided into six functional classes:
  2747.  
  2748.    ■  Data Transfer instructions
  2749.    ■  Arithmetic instructions
  2750.    ■  Comparison instructions
  2751.    ■  Transcendental instructions
  2752.    ■  Constant instructions
  2753.    ■  Processor Control instructions
  2754.  
  2755.  At the end of this section, each of the instructions is described in terms
  2756.  of its execution speed, bus transfers, and exceptions, as well as a coding
  2757.  example for each combination of operands accepted by the instruction. For
  2758.  easy reference, this information is concentrated into a table, organized
  2759.  alphabetically by instruction mnemonic.
  2760.  
  2761.  Throughout this section, the instruction set is described as it appears to
  2762.  the ASM286 programmer who is coding a program. Appendix A covers the actual
  2763.  machine instruction encodings, which are principally of use to those reading
  2764.  unformatted memory dumps, monitoring instruction fetches on the bus, or
  2765.  writing exception handlers.
  2766.  
  2767.  
  2768.  Compatibility with the 8087 NPX
  2769.  The instruction set for the 80287 NPX is largely the same as that for the
  2770.  8087 NPX used with 8086 and 8088 systems. Most object programs generated for
  2771.  the 8087 will execute without change on the 80287. Several instructions are
  2772.  new to the 80287, and several 8087 instructions perform no useful function
  2773.  on the 80287. Appendix B at the back of this manual gives details of these
  2774.  instruction set differences and of the differences in the ASM86 and ASM286
  2775.  assemblers.
  2776.  
  2777.  
  2778.  Numeric Operands
  2779.  The typical NPX instruction accepts one or two operands as inputs, operates
  2780.  on these, and produces a result as an output. Operands are most often (the
  2781.  contents of) register or memory locations. The operands of some instructions
  2782.  are predefined; for example, FSQRT always takes the square root of the
  2783.  number in the top stack element. Others allow, or require, the programmer to
  2784.  explicitly code the operand(s) along with the instruction mnemonic. Still
  2785.  others accept one explicit operand and one implicit operand, which is
  2786.  usually the top stack element.
  2787.  
  2788.  Whether supplied by the programmer or utilized automatically, the two basic
  2789.  types of operands are sources and destinations. A source operand simply
  2790.  supplies one of the inputs to an instruction; it is not altered by the
  2791.  instruction. Even when an instruction converts the source operand from one
  2792.  format to another (e.g., real to integer), the conversion is actually
  2793.  performed in an internal work area to avoid altering the source operand. A
  2794.  destination operand may also provide an input to an instruction. It is
  2795.  distinguished from a source operand, however, because its content may be
  2796.  altered when it receives the result produced by the operation; that is, the
  2797.  destination is replaced by the result.
  2798.  
  2799.  Many instructions allow their operands to be coded in more than one way.
  2800.  For example, FADD (add real) may be written without operands, with only a
  2801.  source or with a destination and a source. The instruction descriptions in
  2802.  this section employ the simple convention of separating alternative operand
  2803.  forms with slashes; the slashes, however, are not coded. Consecutive
  2804.  slashes indicate an option of no explicit operands. The operands for FADD
  2805.  are thus described as
  2806.  
  2807.  //source/destination, source
  2808.  
  2809.  This means that FADD may be written in any of three ways:
  2810.  
  2811.    FADD
  2812.    FADD source
  2813.    FADD destination, source
  2814.  
  2815.  When reading this section, it is important to bear in mind that memory
  2816.  operands may be coded with any of the CPU's memory addressing modes. To
  2817.  review these modes──direct, register indirect, based, indexed, based
  2818.  indexed──refer to the 80286 Programmer's Reference Manual. Table 2-17 later
  2819.  in this chapter also provides several addressing mode examples.
  2820.  
  2821.  
  2822.  Data Transfer Instructions
  2823.  These instructions (summarized in table 2-1) move operands among elements
  2824.  of the register stack, and between the stack top and memory. Any of the
  2825.  seven data types can be converted to temporary real and loaded (pushed) onto
  2826.  the stack in a single operation; they can be stored to memory in the same
  2827.  manner. The data transfer instructions automatically update the 80287 tag
  2828.  word to reflect the register contents following the instruction.
  2829.  
  2830.  
  2831.  FLD source
  2832.  FLD (load real) loads (pushes) the source operand onto the top of the
  2833.  register stack. This is done by decrementing the stack pointer by one and
  2834.  then copying the content of the source to the new stack top. The source may
  2835.  be a register on the stack (ST(i)) or any of the real data types in memory.
  2836.  Short and long real source operands are converted to temporary real
  2837.  automatically. Coding FLD ST(0) duplicates the stack top.
  2838.  
  2839.  
  2840.  FST destination
  2841.  FST (store real) transfers the stack top to the destination, which may be
  2842.  another register on the stack or a short or long real memory operand. If the
  2843.  destination is short or long real, the significand is rounded to the width
  2844.  of the destination according to the RC field of the control word, and the
  2845.  exponent is converted to the width and bias of the destination format.
  2846.  
  2847.  If, however, the stack top is tagged special (it contains ∞, a NaN, or a
  2848.  denormal) then the stack top's significand is not rounded but is chopped (on
  2849.  the right) to fit the destination. Neither is the exponent converted, but it
  2850.  also is chopped on the right and transferred "as is." This preserves the
  2851.  value's identification as ∞ or a NaN (exponent all ones) or a denormal
  2852.  (exponent all zeros) so that it can be properly loaded and tagged later in
  2853.  the program if desired.
  2854.  
  2855.  
  2856.  Table 2-1. Data Transfer Instructions
  2857.  ┌─────────────────────────────────────────────────────────┐
  2858.  │                      Real Transfers                     │
  2859.  ├───────────┬─────────────────────────────────────────────┤
  2860.  │ FLD       │        Load real                            │
  2861.  │ FST       │        Store real                           │
  2862.  │ FSTP      │        Store real and pop                   │
  2863.  │ FXCH      │        Exchange registers                   │
  2864.  ├───────────┴─────────────────────────────────────────────┤
  2865.  │                     Integer Transfers                   │
  2866.  ├───────────┬─────────────────────────────────────────────┤
  2867.  │ FILD      │        Integer load                         │
  2868.  │ FIST      │        Integer store                        │
  2869.  │ FISTP     │        Integer store and pop                │
  2870.  ├───────────┴─────────────────────────────────────────────┤
  2871.  │                 Packed Decimal Transfers                │
  2872.  ├───────────┬─────────────────────────────────────────────┤
  2873.  │ FBLD      │        Packed decimal (BCD) load            │
  2874.  │ FBSTP     │        Packed decimal (BCD) store and pop   │
  2875.  └───────────┴─────────────────────────────────────────────┘
  2876.  
  2877.  
  2878.  FSTP destination
  2879.  FSTP (store real and pop) operates identically to FST except that the stack
  2880.  is popped following the transfer. This is done by tagging the top stack
  2881.  element empty and then incrementing ST. FSTP permits storing to a temporary
  2882.  real memory variable, whereas FST does not. Coding FSTP ST(0) is equivalent
  2883.  to popping the stack with no data transfer.
  2884.  
  2885.  
  2886.  FXCH//destination
  2887.  FXCH (exchange registers) swaps the contents of the destination and the
  2888.  stack top registers. If the destination is not coded explicitly, ST(1) is
  2889.  used. Many 80287 instructions operate only on the stack top; FXCH provides a
  2890.  simple means of effectively using these instructions on lower stack
  2891.  elements. For example, the following sequence takes the square root of the
  2892.  third register from the top:
  2893.  
  2894.    FXCH ST(3)
  2895.    FSQRT
  2896.    FXCH ST(3)
  2897.  
  2898.  
  2899.  FILD source
  2900.  FILD (integer load) converts the source memory operand from its binary
  2901.  integer format (word, short, or long) to temporary real and loads (pushes)
  2902.  the result onto the stack. The (new) stack top is tagged zero if all bits in
  2903.  the source were zero, and is tagged valid otherwise.
  2904.  
  2905.  
  2906.  FIST destination
  2907.  FIST (integer store) rounds the content of the stack top to an integer
  2908.  according to the RC field of the control word and transfers the result to
  2909.  the destination. The destination may define a word or short integer
  2910.  variable. Negative zero is stored in the same encoding as positive zero:
  2911.  0000...00.
  2912.  
  2913.  
  2914.  FISTP destination
  2915.  FISTP (integer and pop) operates like FIST and also pops the stack
  2916.  following the transfer. The destination may be any of the binary integer
  2917.  data types.
  2918.  
  2919.  
  2920.  FBLD source
  2921.  FBLD (packed decimal (BCD) load) converts the content of the source operand
  2922.  from packed decimal to temporary real and loads (pushes) the result onto the
  2923.  stack. The sign of the source is preserved, including the case where the
  2924.  value is negative zero. FBLD is an exact operation; the source is loaded
  2925.  with no rounding error.
  2926.  
  2927.  The packed decimal digits of the source are assumed to be in the range
  2928.  0-9H. The instruction does not check for invalid digits (A-FH) and the
  2929.  result of attempting to load an invalid encoding is undefined.
  2930.  
  2931.  
  2932.  FBSTP destination
  2933.  FBSTP (packed decimal (BCD) store and pop) converts the content of the
  2934.  stack top to a packed decimal integer, stores the result at the destination
  2935.  in memory, and pops the stack. FBSTP produces a rounded integer from a
  2936.  nonintegral value by adding 0.5 to the value and then chopping. Users who
  2937.  are concerned about rounding may precede FBSTP with FRNDINT.
  2938.  
  2939.  
  2940.  Arithmetic Instructions
  2941.  The 80287's arithmetic instruction set (table 2-2) provides a wealth of
  2942.  variations on the basic add, subtract, multiply, and divide operations, and
  2943.  a number of other useful functions. These range from a simple absolute value
  2944.  to a square root instruction that executes faster than ordinary division;
  2945.  80287 programmers no longer need to spend valuable time eliminating square
  2946.  roots from algorithms because they run too slowly. Other arithmetic
  2947.  instructions perform exact modulo division, round real numbers to integers,
  2948.  and scale values by powers of two.
  2949.  
  2950.  The 80287's basic arithmetic instructions (addition, subtraction,
  2951.  multiplication, and division) are designed to encourage the development of
  2952.  very efficient algorithms. In particular, they allow the programmer to
  2953.  minimize memory references and to make optimum use of the NPX register
  2954.  stack.
  2955.  
  2956.  Table 2-3 summarizes the available operation/operand forms that are
  2957.  provided for basic arithmetic. In addition to the four normal operations,
  2958.  two "reversed" instructions make subtraction and division "symmetrical" like
  2959.  addition and multiplication. The variety of instruction and operand forms
  2960.  give the programmer unusual flexibility:
  2961.  
  2962.    ■  Operands may be located in registers or memory.
  2963.  
  2964.    ■  Results may be deposited in a choice of registers.
  2965.  
  2966.    ■  Operands may be a variety of NPX data types: temporary real, long
  2967.       real, short real, short integer or word integer, with automatic
  2968.       conversion to temporary real performed by the 80287.
  2969.  
  2970.  Five basic instruction forms may be used across all six operations, as
  2971.  shown in table 2-3. The classicial stack form may be used to make the 80287
  2972.  operate like a classical stack machine. No operands are coded in this form,
  2973.  only the instruction mnemonic. The NPX picks the source operand from the
  2974.  stack top and the destination from the next stack element. It then pops the
  2975.  stack, performs the operation, and returns the result to the new stack top,
  2976.  effectively replacing the operands by the result.
  2977.  
  2978.  The register form is a generalization of the classical stack form; the
  2979.  programmer specifies the stack top as one operand and any register on the
  2980.  stack as the other operand. Coding the stack top as the destination provides
  2981.  a convenient way to access a constant, held elsewhere in the stack, from
  2982.  the stack top. The converse coding (ST is the source operand) allows, for
  2983.  example, adding the top into a register used as an accumulator.
  2984.  
  2985.  Often the operand in the stack top is needed for one operation but then is
  2986.  of no further use in the computation. The register pop form can be used to
  2987.  pick up the stack top as the sourced operand, and then discard it by
  2988.  popping the stack. Coding operands of ST(1), ST with a register pop
  2989.  mnemonic is equivalent to a classical stack operation: the top is popped
  2990.  and the result is left at the new top.
  2991.  
  2992.  The two memory forms increase the flexibity of the 80287's arithmetic
  2993.  instructions. They permit a real number or a binary integer in memory to
  2994.  be used directly as a source operand. This is a very useful facility in
  2995.  situations where operands are not used frequently enough to justify
  2996.  holding them in registers. Note that any memory addressing mode may be
  2997.  used to define these operands, so they may be elements in arrays,
  2998.  structures, or other data organizations, as well as simple scalars.
  2999.  
  3000.  The six basic operations are discussed further in the paragraphs following
  3001.  table 2-3, and descriptions of the remaining seven arithmetic operations
  3002.  follow.
  3003.  
  3004.  Table 2-2. Arithmetic Instructions
  3005.  
  3006.  Addition
  3007.  FADD                    Add real
  3008.  FADDP                   Add real and pop
  3009.  FIADD                   Integer add
  3010.  
  3011.  Subtraction
  3012.  FSUB                    Subtract real
  3013.  FSUBP                   Subtract real and pop
  3014.  FISUB                   Integer subtract
  3015.  FSUBR                   Subtract real reversed
  3016.  FSUBRP                  Subtract real reversed and pop
  3017.  FISUBR                  Integer subtract reversed
  3018.  
  3019.  Multiplication
  3020.  FMUL                    Multiply real
  3021.  FMULP                   Multiply real and pop
  3022.  FIMUL                   Integer multiply
  3023.  
  3024.  Division
  3025.  FDIV                    Divide real
  3026.  FDIVP                   Divide real and pop
  3027.  FIDIV                   Integer divide
  3028.  FDIVR                   Divide real reversed
  3029.  FDIVRP                  Divide real reversed and pop
  3030.  FIDIVR                  Integer divide reversed
  3031.  
  3032.  Other Operations
  3033.  FSQRT                   Square root
  3034.  FSCALE                  Scale
  3035.  FPREM                   Partial remainder
  3036.  FRNDINT                 Round to integer
  3037.  FXTRACT                 Extract exponent and significand
  3038.  FABS                    Absolute value
  3039.  FCHS                    Change sign
  3040.  
  3041.  
  3042.  Table 2-3. Basic Arithmetic Instruction and Operands
  3043.  
  3044.  ┌───────────────┬─────────┬────────────────────────────┬───────────────┐
  3045.  │  Instruction  │ Mnemonic│      Operand Forms         │ ASM286 Example│
  3046.  │     Form      │   Form  │   destination, source      │               │
  3047.  ├───────────────┼─────────┼────────────────────────────┼───────────────┤
  3048.  │Classical stack│   Fop   │ {ST(1),ST}                 │ FADD          │
  3049.  │Register       │   Fop   │ ST(i),ST or ST,ST(i)       │ FSUB  ST,ST(3)│
  3050.  │Register pop   │   FopP  │ ST(i),ST                   │ FMULP ST(2),ST│
  3051.  │Real memory    │   Fop   │ {ST,} short-real/long-real │ FDIV AZIMUTH  │
  3052.  │Integer memory │   Flop  │ {ST,} word-integer/        │ FIDV N_PULSES │
  3053.  │               │         │       short-integer        │               │
  3054.  └───────────────┴─────────┴────────────────────────────┴───────────────┘
  3055.  
  3056.  ───────────────────────────────────────────────────────────────────────────
  3057.  NOTES
  3058.  
  3059.    Braces({ }) surround inplicit operands; these are not coded, and
  3060.    are shown here for information only.
  3061.  
  3062.    op = ADD  destinaiton  destination + source
  3063.         SUB  destination  destination - source
  3064.         SUBR destination  soure - destination
  3065.         MUL  destination  destination ∙ source
  3066.         DIV  destination  destination ÷ source
  3067.         DIVR destination  source ÷ destination
  3068.  ───────────────────────────────────────────────────────────────────────────
  3069.  
  3070.  
  3071.  ADDITION
  3072.  FADD     //source/destination,source
  3073.  FADDP    //destination/source
  3074.  FIADD    source
  3075.  
  3076.  The addition instructions (add real, add real and pop, integer add) add
  3077.  the source and destination operands and return the sum to the destination.
  3078.  The operand at the stack top may be doubled by coding:
  3079.  
  3080.    FADD ST,ST(0)
  3081.  
  3082.  
  3083.  NORMAL SUBTRACTION
  3084.  FSUB   //source/destinaton,source
  3085.  FSUBP  //destination/source
  3086.  FISUB  source
  3087.  
  3088.  The normal subtraction instruction (subtract real,subtract real and pop,
  3089.  integer subtract) subtract the source operand from the destination and
  3090.  return the difference to the destination.
  3091.  
  3092.  
  3093.  REVERSED SUBTRACTION
  3094.  FSUBR   //source/destinaton,source
  3095.  FSUBRP  //destination/source
  3096.  FISUBR  source
  3097.  
  3098.  The reversed subtraction instructions (subtract real reversed, subtract
  3099.  real reversed and pop, integer subtract reversed) subtract the destination
  3100.  from the source and return the difference to the destination.
  3101.  
  3102.  
  3103.  MULTIPLICATION
  3104.  FMUL    //source/destination,source
  3105.  FMULP   destination,source
  3106.  FIMUL   source
  3107.  
  3108.  The multiplication instructions (multiply real, multiply real and pop,
  3109.  integer multiply) multiply the source and destination operands and return
  3110.  the product to the destination. Coding FMUL ST,ST(0) squares the content
  3111.  of the stack top.
  3112.  
  3113.  
  3114.  NORMAL DIVISION
  3115.  FDIV    //source/destination,source
  3116.  FDIVP   destination,source
  3117.  FIDIV   source
  3118.  
  3119.  The normal division instructions (divide real, divide real and pop,
  3120.  integer divide) divide the destination by the source and return the
  3121.  quotient to the destination.
  3122.  
  3123.  
  3124.  REVERSED DIVISION
  3125.  FDIVR    //source destination, source
  3126.  FDIVRP   destination,source
  3127.  FIDIVR   source
  3128.  
  3129.  The reversed division instructions (divide real reversed, divide real
  3130.  reversed and pop, integer divide reversed) divide the source operand by
  3131.  the destination and return the quotient to the destination.
  3132.  
  3133.  
  3134.  FSQRT
  3135.  FSQRT (square root) replaces the content of the top stack element with its
  3136.  square root. (Note: The square root of -0 is defined to be -0.)
  3137.  
  3138.  
  3139.  FSCALE
  3140.  FSCALE (scale) interprets the value contained in ST(1) as an integer and
  3141.  adds this value to the exponent of the number in ST. This is equivalent to
  3142.  
  3143.    ST  ST * 2^(ST(1))
  3144.  
  3145.  Thus FSCALE provides rapid multiplication or division by integal powers of
  3146.  2. It is particularly useful for scaling the elements of a vector.
  3147.  
  3148.  Note that FSCALE assumes the scale factor in ST(1) is an integral value in
  3149.  the range -2^(15) ≤ x < 2^(15). If the value is not integral, but is
  3150.  in-range and is greater in magnitude than 1, FSCALE uses the nearest integer
  3151.  smaller in magnitude; i.e., it chops the value toward 0. If the value is out
  3152.  of range, or 0 < │x│ < 1, the instruction will produce an undefined result
  3153.  and will not signal an exception. The recommended practice is to load the
  3154.  scale factor from a word integer to ensure correct operation.
  3155.  
  3156.  
  3157.  FPREM
  3158.  FPREM (partial remainder) performs modulo division of the top stack
  3159.  element by the next stack element, i.e., ST(1) is the modulus. FPREM
  3160.  produces an exact result; the precision exception does not occur. The sign
  3161.  of the remainder is the same as the sign of the orginal dividend.
  3162.  
  3163.  FPREM operates by performing successive scaled subtractions; obtaining the
  3164.  exact remainder when the operands differ greatly in magnitude can consume
  3165.  large amounts of execution time. Because the 80287 cas only be preempted
  3166.  between instructions, the remainder function could seriously increase
  3167.  interrupt latency in these cases. Accordingly, the instruction is designed
  3168.  to be executed interactively in a software-controlled loop.
  3169.  
  3170.  FPREM can reduce a magnitude difference of up to 264 in one execution. If
  3171.  FPREM produces a remainder that is less than the modulus, the function is
  3172.  complete and bit C2 of the status word condition code is cleared. If the
  3173.  function is incomplete, C2 is set to 1; the result is ST is then called
  3174.  the partial remainder. Software can inspect C2 by storing the status word
  3175.  following execution of FPREM and re-execute the instruction (using the
  3176.  partial remainder in ST as the dividend), until C2 is cleared.
  3177.  Alternatively, a program can determine when the function is complete by
  3178.  comparing ST to ST(1). If ST > ST(1), then FPREM must be executed again; if
  3179.  ST = ST(1), then the remainder is 0; if ST < ST(1), then the remainder is
  3180.  ST. A higher priority interrupting routine that needs the 80287 can force a
  3181.  context switch between the instructions in the remainder loop.
  3182.  
  3183.  An important use for FPREM is to reduce arguments (operands) of periodic
  3184.  transcendental functions to the range permitted by these instructions. For
  3185.  example, the FPTAN (tangent) instruction requires its argument to be less
  3186.  than π/4. Using π/4 as a modulus, FPTAN will reduce an argument so that it
  3187.  is in range of FPTAN. Because FPREM produces an exact result, the argument
  3188.  reduction does not introduce roundoff error into the calculation, even if
  3189.  several iterations are required to bring the argument into range. (The
  3190.  rounding of π does not create the effect of a rounded argument, but of a
  3191.  rounded period.)
  3192.  
  3193.  FPREM also provides the least-significant three bits of the quotient
  3194.  generated by FPREM (in C{3}, C{1}, C{0}). This is also important for
  3195.  trancendental argument reduction, because it locates the original angle in
  3196.  the correct one of eight π/4 segments of the unit circle (see table 2-4).
  3197.  If the quotient is less than 4, then C0 will be the value of C3 before
  3198.  FPREM was executed. If the quotient is less than 2, then C3 will be the
  3199.  value of C1 before FPREM was executed.
  3200.  
  3201.  
  3202.  FRNDINT
  3203.  FRNDINT (round to integer) rounds the top stack element to an integer. For
  3204.  example, assume that ST contains the 80287 real number encoding of the
  3205.  decimal value 155.625. FRNDINT will change the value to 155 if the RC field
  3206.  of the control word is set to down or chop, or to 156 if it is set to up or
  3207.  nearest.
  3208.  
  3209.  
  3210.  FXTRACT
  3211.  FXTRACT (extract exponent and significand) "decomposes" the number in the
  3212.  stack top into two numbers that represent the actual value of the operand's
  3213.  exponent and significand fields. The "exponent" replaces the original
  3214.  operand on the stack and the "significand" is pushed onto the stack.
  3215.  Following execution of FXTRACT, ST (the new stack top) contains the value of
  3216.  the original significand expressed as a real number: its sign is the same as
  3217.  the operand's, its exponent is 0 true (16,383 or 3FFFH biased), and its
  3218.  significand is identical to the original operand's. ST(1) contains the
  3219.  value of the original operand's true (unbiased) exponent expressed as a real
  3220.  number. If the original operand is zero, FXTRACT produces zeros in ST and
  3221.  ST(1) and both are signed as the original operand.
  3222.  
  3223.  To clarify the operation of FXTRACT, assume ST contains a number of whose
  3224.  true exponent is +4 (i.e., its exponent field contains 4003H). After
  3225.  executing FXTRACT, ST(1) will contain the real number +4.0; its sign will be
  3226.  positive, its exponent field will contain 4001H (+2 true) and its
  3227.  significand field will contain 1{}00...00B. In other words, the value in
  3228.  ST(1) will be 1.0 * 2^(2) = 4. If ST contains an operand whose true exponent
  3229.  is -7 (i.e., its exponent field contains 3FF8H), then FXTRACT will return an
  3230.  "exponent" of -7.0; after the instruction executes, ST(1)'s sign and
  3231.  exponent fields will contain C001H (negative sign, true exponent of 2), and
  3232.  its significand will be 1{}1100...00B. In other words, the value in ST(1)
  3233.  will be -1.11 * 2^(2) = -7.0. In both cases, following FXTRACT, ST's sign
  3234.  and significand fields will be the same as the original operand's, and its
  3235.  exponent field will contain 3FFFH (0 true).
  3236.  
  3237.  FXTRACT is useful in conjunction with FBSTP for converting numbers in 80287
  3238.  temporary real format to decimal representations (e.g., for printing or
  3239.  displaying). It can also be useful for debugging, because it allows the
  3240.  exponent and significant parts of a real number to be examined separately.
  3241.  
  3242.  
  3243.  FABS
  3244.  FABS (absolute value) changes the top stack element to its absolute value
  3245.  by making its sign positive.
  3246.  
  3247.  
  3248.  FCHS
  3249.  FCHS (change sign) complements (reverses) the sign of the top stack
  3250.  element.
  3251.  
  3252.  
  3253.  Table 2-4.  Condition Code Interpretation after FPREM
  3254.  
  3255.  ┌─────────────────────────────────────────────────────────────────────┐
  3256.  │ ┌──Condition Code──┐                                                │
  3257.  │ C3    C2    C1    C0      Interpretation after FPREM                │
  3258.  ├─────┬─────┬─────┬─────┬─────────────────────────────────────────────┤
  3259.  │  X  │  1  │  X  │  X  │  Incomplete Reduction;                      │
  3260.  │     │     │     │     │    further iteration is required for        │
  3261.  │     │     │     │     │    complete reduction.                      │
  3262.  │     │     │     │     │  Complete Reduction;                        │
  3263.  │     │     │     │     │    C1, C3, and C0 contain the three least-  │
  3264.  │     │     │     │     │    significant bits of quotient:            │
  3265.  │  0  │  0  │  0  │  0  │  (Quotient) MOD 8 = 0                       │
  3266.  │  0  │  0  │  0  │  1  │  (Quotient) MOD 8 = 4                       │
  3267.  │  0  │  0  │  1  │  0  │  (Quotient) MOD 8 = 1                       │
  3268.  │  0  │  0  │  1  │  1  │  (Quotient) MOD 8 = 5                       │
  3269.  │  1  │  0  │  0  │  0  │  (Quotient) MOD 8 = 2                       │
  3270.  │  1  │  0  │  0  │  1  │  (Quotient) MOD 8 = 6                       │
  3271.  │  1  │  0  │  1  │  0  │  (Quotient) MOD 8 = 3                       │
  3272.  │  1  │  0  │  1  │  1  │  (Quotient) MOD 8 = 7                       │
  3273.  └─────┴─────┴─────┴─────┴─────────────────────────────────────────────┘
  3274.  
  3275.  
  3276.  Comparison Instructions
  3277.  Each of these instructions (table 2-5) analyzes the top stack element,
  3278.  often in relationship to another operand, and reports the result in the
  3279.  status word condition code. The basic operations are compare, test (compare
  3280.  with zero), and examine (report tag, sign, and normalization). Special
  3281.  forms of the compare operation are provided to optimize algorithms by
  3282.  allowing direct comparisons with binary integers and real numbers in memory,
  3283.  as well as popping the stack after a comparison.
  3284.  
  3285.  The FSTSW (store status word) instruction may be used following a
  3286.  comparison to transfer the condition code to memory for inspection.
  3287.  
  3288.  Note that instructions other than those in the comparison group may update
  3289.  the condition code. To ensure that the status word is not altered
  3290.  inadvertently, store it immediately following a comparison operation.
  3291.  
  3292.  
  3293.  FCOM //source
  3294.  FCOM (compare real) compares the stack top to the source operand. The
  3295.  source operand may be a register on the stack, or a short or long real
  3296.  memory operand. If an operand is not coded, ST is compared to ST(1).
  3297.  Positive and negative forms of zero compare identically as if they were
  3298.  unsigned. Following the instruction, the condition codes reflect the order
  3299.  of the operands as shown in table 2-6.
  3300.  
  3301.  NaNs and ∞ (projective) cannot be compared and return C3 = C0 = 1 as shown
  3302.  in the table.
  3303.  
  3304.  
  3305.  FCOMP //source
  3306.  FCOMP (compare real and pop) operates like FCOM, and in addition pops the
  3307.  stack.
  3308.  
  3309.  
  3310.  FCOMPP
  3311.  FCOMPP (compare real and pop twice) operates like FCOM and additionally
  3312.  pops the stack twice, discarding both operands. The comparison is of the
  3313.  stack top to ST(1); no operands may be explicitly coded.
  3314.  
  3315.  
  3316.  FICOM  source
  3317.  FICOM (integer compare) converts the source operand, which may reference a
  3318.  word or short binary integer variable, to temporary real and compares the
  3319.  stack top to it.
  3320.  
  3321.  
  3322.  FICOMP source
  3323.  FICOMP (integer compare and pop) operates identically to FICOM and
  3324.  additionally discards the value in ST by popping the stack.
  3325.  
  3326.  
  3327.  FTST
  3328.  FTST (test) tests the top stack element by comparing it to zero. The result
  3329.  is posted to the condition codes as shown in table 2-7.
  3330.  
  3331.  
  3332.  FXAM
  3333.  FXAM (examine) reports the content of the top stack element as
  3334.  positive/negative and NaN/unnormal/denormal/normal/zero, or empty.
  3335.  Table 2-8 lists and interprets all the condition code values that FXAM
  3336.  generates. Although four different encodings may be returned for an empty
  3337.  register, bits C3 and C0 of the condition code are both 1 in all encodings.
  3338.  Bits C2 and C1 should be ignored when examining for empty.
  3339.  
  3340.  
  3341.  Table 2-5. Comparison Instructions
  3342.  
  3343.  FCOM                 Compare real
  3344.  FCOMP                Compare real and pop
  3345.  FCOMPP               Compare real and pop twice
  3346.  FICOM                Integer compare
  3347.  FICOMP               Integer compare and pop
  3348.  FTST                 Test
  3349.  FXAM                 Examine
  3350.  
  3351.  
  3352.  Table 2-6. Condition Code Interpretation after FCOM
  3353.  
  3354.  ┌── Condition Code ──┐
  3355.  C3    C2     C1     C0     Interpretation after FCOM
  3356.  
  3357.  0     0      X      0      ST > source
  3358.  0     0      X      1      ST < source
  3359.  1     0      X      0      ST = source
  3360.  1     1      X      1      ST is not comparable
  3361.  
  3362.  
  3363.  Table 2-7. Condition Code Interpretation after FTST
  3364.  
  3365.  ┌── Condition Code ──┐
  3366.  C3    C2     C1     C0     Interpretation after FTST
  3367.  
  3368.  0     0      X      0      ST > 0
  3369.  0     0      X      1      ST < 0
  3370.  1     0      X      0      ST = 0
  3371.  1     1      X      1      ST is not comparable; (i.e., it
  3372.                             is a NaN or projective infinity)
  3373.  
  3374.  
  3375.  Table 2-8. FXAM Condition Code Settings
  3376.  
  3377.  ┌─── Condition Code ───┐
  3378.  C3     C2      C1     C0           Interpretation
  3379.  
  3380.  0      0       0      0            + Unnormal
  3381.  0      0       0      1            + NaN
  3382.  0      0       1      0            - Unnormal
  3383.  0      0       1      1            - NaN
  3384.  0      1       0      0            + Normal
  3385.  0      1       0      1            + ∞
  3386.  0      1       1      0            - Normal
  3387.  0      1       1      1            - ∞
  3388.  1      0       0      0            + 0
  3389.  1      0       0      1            Empty
  3390.  1      0       1      0            - 0
  3391.  1      0       1      1            Empty
  3392.  1      1       0      0            + Denormal
  3393.  1      1       0      1            Empty
  3394.  1      1       1      0            - Denormal
  3395.  1      1       1      1            Empty
  3396.  
  3397.  
  3398.  Transcendental Instructions
  3399.  The instructions in this group (table 2-9) perform the time-consuming core
  3400.  calculations for all common trigonometric, inverse trigonometric,
  3401.  hyperbolic, inverse hyperbolic, logarithmic, and exponential functions.
  3402.  Prologue and epilogue software may be used to reduce arguments to the range
  3403.  accepted by the instructions and to adjust the result to correspond to the
  3404.  original arguments if necessary. The transcendentals operate on the top one
  3405.  or two stack elements, and they return their results to the stack, also.
  3406.  
  3407.  ───────────────────────────────────────────────────────────────────────────
  3408.  NOTE
  3409.    The transcendental instructions assume that their operands are valid and
  3410.    in-range. The instruction descriptions in this section provide the
  3411.    allowed operand range of each instruction.
  3412.  ───────────────────────────────────────────────────────────────────────────
  3413.  
  3414.  All operands to a transcendental must be normalized; denormals, unnormals,
  3415.  infinities, and NaNs are considered invalid. (Zero operands are accepted by
  3416.  some functions and are considered out-of-range by others). If a
  3417.  transcendental operand is invalid or out-of-range, the instruction will
  3418.  produce an undefined result without signalling an exception. It is the
  3419.  programmer's responsibility to ensure that operands are valid and in-range
  3420.  before executing a transcendental. For periodic functions, FPREM may be
  3421.  used to bring a valid operand into range.
  3422.  
  3423.  
  3424.  FPTAN
  3425.  0 ≤ ST(0) ≤ π/4
  3426.  
  3427.  FPTAN (partial tangent) computes the function Y/X = TAN(Θ). Θ is taken
  3428.  from the top stack element; it must lie in the range 0 ≤ Θ ≤ π/4. The result
  3429.  of the operation is a ratio; Y replaces Θ in the stack and X is pushed,
  3430.  becoming the new stack top.
  3431.  
  3432.  The ratio result of FPTAN and the ratio argument of FPATAN are designed to
  3433.  optimize the calculation of the other trigonometric functions, including
  3434.  SIN, COS, ARCSIN, and ARCCOS. These can be derived from TAN and ARCTAN via
  3435.  standard trigonometric identities.
  3436.  
  3437.  
  3438.  FPATAN
  3439.  0 ≤ ST(1) < ST(0) < ∞
  3440.  
  3441.  FPATAN (partial arctangent) computes the function Θ = ARCTAN(Y/X). X is
  3442.  taken from the top stack element and Y from ST(1). Y and X must observe the
  3443.  inequality 0 ≤ Y < X < ∞. The instruction pops the stack and returns Θ to
  3444.  the (new) stack top, overwriting the Y operand.
  3445.  
  3446.  
  3447.  F2XM1
  3448.  0 ≤ ST(0) ≤ 0.5
  3449.  
  3450.  F2XM1 (2 to the X minus 1) calculates the function Y = 2^(X) - 1. X is taken
  3451.  from the stack top and must be in the range 0 ≤ X ≤ 0.5. The result Y
  3452.  replaces X at the stack top.
  3453.  
  3454.  This instruction is designed to produce a very accurate result even when X
  3455.  is close to 0. To obtain Y = 2^(X), add 1 to the result delivered by F2XM1.
  3456.  
  3457.  The following formulas show how values other than 2 may be raised to a
  3458.  power of X:
  3459.  
  3460.    10^(x) = 2^(x * LOG{2}10)
  3461.     e^(x) = 2^(x * LOG{2}e)
  3462.     y^(x) = 2^(x * LOG{2}Y)
  3463.  
  3464.  As shown in the next section, the 80287 has built-in instructions for
  3465.  loading the constants LOG{2}10 and LOG{2}e, and the FYL2X instruction may be
  3466.  used to calculate X * LOG{2}Y.
  3467.  
  3468.  
  3469.  FYL2X
  3470.  0 < ST(0) < ∞ - ∞ < ST(1) < ∞
  3471.  
  3472.  FYL2X (Y log base 2 of X) calculates the function Z = Y * LOG{2}X. X is
  3473.  taken from the stack top and Y from ST(1). The operands must be in the
  3474.  ranges 0 < X < ∞ and -∞ < Y < +∞. The instruction pops the stack and returns
  3475.  Z at the (new) stack top, replacing the Y operand.
  3476.  
  3477.  This function optimizes the calculations of log to any base other than two,
  3478.  because a multiplication is always required:
  3479.  
  3480.    LOG{n}2 * LOG{2}X
  3481.  
  3482.  
  3483.  FYL2XP1
  3484.  0 ≤ │ST(0)│ < (1 - (√2/2))
  3485.  -∞ < ST(1) < ∞
  3486.  
  3487.  FYL2XP1 (Y log base 2 of (X + 1)) calculates the function
  3488.  Z = Y * LOG{2}(X+1). X is taken from the stack top and must be in the range
  3489.  0 ≤ │X│ < (1 - (√2/2)). Y is taken from ST(1) and must be in the range
  3490.  -∞ < Y < ∞. FYL2XP1 pops the stack and returns Z at the (new) stack top,
  3491.  replacing Y.
  3492.  
  3493.  The instruction provides improved accuracy over FYL2X when computing the
  3494.  log of a number very close to 1, for example 1 + ε where ε << 1. Providing ε
  3495.  rather than 1 + ε as the input to the function allows more significant
  3496.  digits to be retained.
  3497.  
  3498.  
  3499.  Table 2-9. Transcendental Instructions
  3500.  
  3501.  FPTAN        Partial tangent
  3502.  FPATAN       Partial arctangent
  3503.  F2XM1        2^(X) - 1
  3504.  FYL2X        Y * log{2}X
  3505.  FYL2XP1      Y * log{2}(X + 1)
  3506.  
  3507.  
  3508.  Constant Instructions
  3509.  Each of these instructions (table 2-10) loads (pushes) a commonly-used
  3510.  constant onto the stack. The values have full temporary real precision (64
  3511.  bits) and are accurate to approximately 19 decimal digits. Because a
  3512.  temporary real constant occupies 10 memory bytes, the constant
  3513.  instructions, which are only two bytes long, save storage and improve
  3514.  execution speed, in addition to simplifying programming.
  3515.  
  3516.  FLDZ
  3517.  FLDZ (load zero) loads (pushes) +0.0 onto the stack.
  3518.  
  3519.  FLD1
  3520.  FLD1 (load one) loads (pushes) +1.0 onto the stack.
  3521.  
  3522.  FLDPI
  3523.  FLDPI (load π) loads (pushes) π onto the stack.
  3524.  
  3525.  FLDL2T
  3526.  FLDL2T (load log base 2 of 10) loads (pushes) the value LOG{2}10 onto the
  3527.  stack.
  3528.  
  3529.  FLDL2E
  3530.  FLDL2E (load log base 2 of e) loads (pushes) the value LOG{2}e onto the
  3531.  stack.
  3532.  
  3533.  FLDLG2
  3534.  FLDLG2 (load log base 10 of 2) loads (pushes) the value LOG{10}2 onto the
  3535.  stack.
  3536.  
  3537.  FLDLN2
  3538.  FLDLN2 (load log base e of 2) loads (pushes) the value LOG{e}2 onto the
  3539.  stack.
  3540.  
  3541.  
  3542.  Table 2-10. Constant Instructions
  3543.  
  3544.  FLDZ              Load +0.0
  3545.  FLD1              Load +1.0
  3546.  FLDPI             Load π
  3547.  FLDL2T            Load log{2}10
  3548.  FLDL2E            Load log{2}e
  3549.  FLDLG2            Load log{10}2
  3550.  FLDLN2            Load log{e}2
  3551.  
  3552.  
  3553.  Processor Control Instructions
  3554.  The processor control instructions shown in table 2-11 are not typically
  3555.  used in calculations; they provide control over the 80287 NPX for
  3556.  system-level activities. These activities include initialization, exception
  3557.  handling, and task switching.
  3558.  
  3559.  As shown in table 2-11, many of the NPX processor control instructions have
  3560.  two forms of assembler mnemonic:
  3561.  
  3562.    ■  A wait form, where the mnemonic is prefixed only with an F, such as
  3563.       FSTSW. This form checks for unmasked numeric errors.
  3564.  
  3565.    ■  A no-wait form, where the mnemonic is prefixed with an FN, such as
  3566.       FNSTSW. This form ignores unmasked numeric errors.
  3567.  
  3568.  When the control instruction is coded using the no-wait form of the
  3569.  mnemonic, the ASM286 assembler does not precede the ESC instruction with a
  3570.  wait instruction, and the CPU does not test the ERROR status line from the
  3571.  NPX before executing the processor control instruction.
  3572.  
  3573.  Only the processor control class of instructions have this alternate
  3574.  no-wait form. All numeric instructions are automatically synchronized by the
  3575.  80286, with the CPU testing the BUSY status line and only executing the
  3576.  numeric instruction when this line is inactive. Because of this automatic
  3577.  synchronization by the 80286, numeric instructions for the 80287 need not be
  3578.  preceded by a CPU wait instruction in order to execute correctly.
  3579.  
  3580.  It should also be noted that the 8087 instructions FENI and FDISI perform
  3581.  no function in the 80287. If these opcodes are detected in an 80286/80287
  3582.  instruction stream, the 80287 will perform no specific operation and no
  3583.  internal states will be affected. For programmers interested in porting
  3584.  numeric software from 8087 environments to the 80286, however, it should be
  3585.  noted that program sections containing these exception-handling instructions
  3586.  are not likely to be completely portable to the 80287. Appendix B contains
  3587.  a more complete description of the differences between the 80287 and the
  3588.  8087 NPX.
  3589.  
  3590.  
  3591.  Table 2-11. Processor Control Instructions
  3592.  
  3593.  FINIT/FNINIT                  Initialize processor
  3594.  FSETPM                        Set Protected Mode
  3595.  FLDCW                         Load control word
  3596.  FSTCW/FNSTCW                  Store control word
  3597.  FSTSW/FNSTSW                  Store status word
  3598.  FSTSW AX/FNSTSW AX            Store status word to AX
  3599.  FCLEX/FNCLEX                  Clear exceptions
  3600.  FSTENV/FNSTENV                Store Environment
  3601.  FLDENV                        Load environment
  3602.  FSAVE/FNSAVE                  Save state
  3603.  FRSTOR                        Restore state
  3604.  FINCSTP                       Increment stack pointer
  3605.  FDECSTP                       Decrement stack pointer
  3606.  FFREE                         Free register
  3607.  FNOP                          No operation
  3608.  FWAIT                         CPU Wait
  3609.  
  3610.  
  3611.  FINIT/FNINIT
  3612.  FINIT/FNINIT (initialize processor) sets the 80287 NPX into a known state,
  3613.  unaffected by any previous activity. The no-wait form of this instruction
  3614.  will cause the 80287 to abort any previous numeric operations currently
  3615.  executing in the NEU. This instruction performs the functional equivalent
  3616.  of a hardware RESET, with one exception; FINIT/FNINIT does not affect the
  3617.  current 80287 operating mode (either Real-Address mode or Protected mode).
  3618.  FINIT checks for unmasked numeric exceptions, FNINIT does not.
  3619.  
  3620.  Note that if FNINIT is executed while a previous 80287 memory-referencing
  3621.  instruction is running, 80287 bus cycles in progress will be aborted. This
  3622.  instruction may be necessary to clear the 80287 if a Processor Extension
  3623.  Segment Overrun Exception (Interrupt 9) is detected by the CPU.
  3624.  
  3625.  
  3626.  FSETPM
  3627.  FSETPM (set Protected mode) sets the operating mode of the 80287 to
  3628.  Protected Virtual-Address mode. When the 80287 is first initialized
  3629.  following hardware RESET, it operates in Real-Address mode, just as does the
  3630.  80286 CPU. Once the 80287 NPX has been set into Protected mode, only a
  3631.  hardware RESET can return the NPX to operation in Real-Address mode.
  3632.  
  3633.  When the 80287 operates in Protected mode, the NPX exception pointers are
  3634.  represented differently than they are in Real-Address mode (see the FSAVE
  3635.  and FSTENV instructions that follow). This distinction is evident primarily
  3636.  to writers of numeric exception handlers, however. For general application
  3637.  programmers, the operating mode of the 80287 need not be a concern.
  3638.  
  3639.  
  3640.  FLDCW source
  3641.  FLDCW (load control word) replaces the current processor control word with
  3642.  the word defined by the source operand. This instruction is typically used
  3643.  to establish or change the 80287's mode of operation. Note that if an
  3644.  exception bit in the status word is set, loading a new control word that
  3645.  unmasks that exception and clears the interrupt enable mask will generate an
  3646.  immediate interrupt request before the next instruction is executed. When
  3647.  changing modes, the recommended procedure is to first clear any exceptions
  3648.  and then load the new control word.
  3649.  
  3650.  
  3651.  FSTCW/FNSTCW destination
  3652.  FSTCW/FNSTCW (store control word) writes the current processor control word
  3653.  to the memory location defined by the destination. FSTCW checks for unmasked
  3654.  numeric exceptions, FNSTCW does not.
  3655.  
  3656.  
  3657.  FSTSW/FNSTSW destination
  3658.  FSTSW/FNSTCW (store status word) writes the current value of the 80287
  3659.  status word to the destination operand in memory. The instruction is used to
  3660.  
  3661.    ■  Implement conditional branching following a comparison or FPREM
  3662.       instruction (FSTSW)
  3663.  
  3664.    ■  Poll the 80287 to determine if it is busy (FNSTSW)
  3665.  
  3666.    ■  Invoke exception handlers in environments that do not use interrupts
  3667.       (FSTSW).
  3668.  
  3669.  FSTSW checks for unmasked numeric exceptions, FNSTSW does not.
  3670.  
  3671.  
  3672.  FSTSW AX/FNSTSW AX
  3673.  FSTSW AX/FNSTSW AX (store status word to AX) is a special 80287 instruction
  3674.  that writes the current value of the 80287 status word directly into the
  3675.  80286 AX register. This instruction optimizes conditional branching in
  3676.  numeric programs, where the 80286 CPU must test the condition of various NPX
  3677.  status bits. The waited form checks for unmasked numeric exceptions, the
  3678.  non-waited for does not.
  3679.  
  3680.  When this instruction is executed, the 80286 AX register is updated with
  3681.  the NPX status word before the CPU executes any further instructions. In
  3682.  this way, the 80286 can immediately test the NPX status word without any
  3683.  WAIT or other synchronization instructions required.
  3684.  
  3685.  
  3686.  FCLEX/FNCLEX
  3687.  FCLEX/FNCLEX (clear exceptions) clears all exception flags, the error
  3688.  status flag and the busy flag in the status word. As a consequence, the
  3689.  80287's ERROR line goes inactive. FCLEX checks for unmasked numeric
  3690.  exceptions, FNCLEX does not.
  3691.  
  3692.  
  3693.  FSAVE/FNSAVE destination
  3694.  FSAVE/FNSAVE (save state) writes the full 80287 state──environment plus
  3695.  register stack──to the memory location defined by the destination operand.
  3696.  Figure 2-1 shows the layout of the 94-byte save area; typically the
  3697.  instruction will be coded to save this image on the CPU stack. FNSAVE
  3698.  delays its execution until all NPX activity completes normally. Thus, the
  3699.  save image reflects the state of the NPX following the completion of any
  3700.  running instruction. After writing the state image to memory, FSAVE/FNSAVE
  3701.  initializes the 80287 as if FINIT/FNINIT had been executed.
  3702.  
  3703.  FSAVE/FNSAVE is useful whenever a program wants to save the current state
  3704.  of the NPX and initialize it for a new routine. Three examples are
  3705.  
  3706.    ■  An operating system needs to perform a context switch (suspend the
  3707.       task that had been running and give control to a new task).
  3708.  
  3709.    ■  An exception handler needs to use the 80287.
  3710.  
  3711.    ■  An application task wants to pass a "clean" 80287 to a subroutine.
  3712.  
  3713.  FSAVE checks for unmasked numeric errors before executing, FNSAVE does not.
  3714.  An FWAIT should be executed before CPU interrupts are enabled or any
  3715.  subsequent 80287 instruction is executed. Other CPU instructions may be
  3716.  executed between the FNSAVE/FSAVE and the FWAIT.
  3717.  
  3718.  
  3719.  Figure 2-1.  FSAVE/FRSTOR Memory Layout
  3720.  
  3721.                                             ────────────┐INCREASING
  3722.                          ╔═════════════════════════╗     │ADDRESS
  3723.          REAL MODE       ║      CONTROL WORD       ║ +0  │
  3724.                          ╟─────────────────────────╢     │
  3725.                          ║       STATUS WORD       ║ +2  │
  3726.                          ╟─────────────────────────╢     
  3727.                          ║        TAG WORD         ║ +4
  3728.                          ╟─────────────────────────╢
  3729.                        ┌─║INSTRUCTION POINTER(15-0)║ +6
  3730.                        │ ╟───────────┬─┬───────────╢
  3731.             INSTRUCTION│ ║INSTRUCTION│ │INSTRUCTION║
  3732.                 POINTER┤ ║  POINTER  │0│  OPCODE   ║ +8
  3733.                        │ ║  (19-14)  │ │  (10-0)   ║
  3734.                        ╞═╟───────────┴─┴───────────╢
  3735.                 OPERAND│ ║   DATA POINTER(15-0)    ║ +10
  3736.                 POINTER┤ ╟───────────┬─────────────╢
  3737.                        │ ║   DATA    │             ║
  3738.                        └─║  POINTER  │      0      ║ +12
  3739.                          ║  (19-16)  │             ║
  3740.                          ╚══╦════════╧══════════╦══╝
  3741.                           ┌─║ SIGNIFICAND 15-0  ║ +14
  3742.                           │ ╟───────────────────╢
  3743.                           │ ║ SIGNIFICAND 31-16 ║ +16
  3744.                  TOP STACK┤ ╟───────────────────╢
  3745.                 ELEMENT:ST│ ║ SIGNIFICAND 47-32 ║ +18
  3746.                           │ ╟───────────────────╢
  3747.                           │ ║ SIGNIFICAND 63-48 ║ +20
  3748.                           │ ╟──────────────────╢
  3749.                           └─║S│  EXPONENT 14-0  ║ +22
  3750.                             ╟─┴─────────────────╢
  3751.                           ┌─║ SIGNIFICAND 15-0  ║ +14
  3752.                           │ ╟───────────────────╢
  3753.                           │ ║ SIGNIFICAND 31-16 ║ +16
  3754.                 NEXT STACK┤ ╟───────────────────╢
  3755.              ELEMENT:ST(1)│ ║ SIGNIFICAND 47-32 ║ +18
  3756.                           │ ╟───────────────────╢
  3757.                           │ ║ SIGNIFICAND 63-48 ║ +20
  3758.                           │ ╟──────────────────╢
  3759.                           └─║S│  EXPONENT 14-0  ║ +22
  3760.                             ╟─┴─────────────────╢
  3761.                             ╟─┴─────────────────╢
  3762.                             ≈                   ≈
  3763.                             ╟───────────────────╢
  3764.                           ┌─║ SIGNIFICAND 15-0  ║ +84
  3765.                           │ ╟───────────────────╢
  3766.                           │ ║ SIGNIFICAND 31-16 ║ +86
  3767.                 LAST STACK┤ ╟───────────────────╢
  3768.              ELEMENT:ST(7)│ ║ SIGNIFICAND 47-32 ║ +88
  3769.                           │ ╟───────────────────╢
  3770.                           │ ║ SIGNIFICAND 63-48 ║ +90
  3771.                           │ ╟──────────────────╢
  3772.                           └─║S│  EXPONENT 14-0  ║ +92
  3773.                             ╚═╧═════════════════╝
  3774.  
  3775.  
  3776.                                            ────────────┐INCREASING
  3777.                                                         │ADDRESSES
  3778.                            ╔═════════════════════╗      │
  3779.          PROTECTED MODE    ║    CONTROL WORD     ║ +0   │
  3780.                            ╟─────────────────────╢      │
  3781.                            ║     STATUS WORD     ║ +2   │
  3782.                            ╟─────────────────────╢      
  3783.                            ║      TAG WORD       ║ +4
  3784.                            ╟─────────────────────╢
  3785.                            ║      IP OFFSET      ║ +6
  3786.                            ╟─────────────────────╢
  3787.                            ║     CS SELECTOR     ║ +8
  3788.                            ╟─────────────────────╢
  3789.                            ║ DATA OPERAND OFFSET ║ +10
  3790.                            ╟─────────────────────╢
  3791.                            ║DATA OPERAND SELECTOR║ +12
  3792.                            ╚╦═══════════════════╦╝
  3793.                           ┌─║ SIGNIFICAND 15-0  ║ +14
  3794.                           │ ╟───────────────────╢
  3795.                           │ ║ SIGNIFICAND 31-16 ║ +16
  3796.                  TOP STACK┤ ╟───────────────────╢
  3797.                 ELEMENT:ST│ ║ SIGNIFICAND 47-32 ║ +18
  3798.                           │ ╟───────────────────╢
  3799.                           │ ║ SIGNIFICAND 63-48 ║ +20
  3800.                           │ ╟──────────────────╢
  3801.                           └─║S│  EXPONENT 14-0  ║ +22
  3802.                             ╟─┴─────────────────╢
  3803.                           ┌─║ SIGNIFICAND 15-0  ║ +24
  3804.                           │ ╟───────────────────╢
  3805.                           │ ║ SIGNIFICAND 31-16 ║ +26
  3806.                 NEXT STACK┤ ╟───────────────────╢
  3807.              ELEMENT:ST(1)│ ║ SIGNIFICAND 47-32 ║ +28
  3808.                           │ ╟───────────────────╢
  3809.                           │ ║ SIGNIFICAND 63-48 ║ +30
  3810.                           │ ╟──────────────────╢
  3811.                           └─║S│  EXPONENT 14-0  ║ +32
  3812.                             ╟─┴─────────────────╢
  3813.                             ≈                   ≈
  3814.                             ╟───────────────────╢
  3815.                             ║ SIGNIFICAND 15-0  ║ +84
  3816.                           ┌─╟───────────────────╢
  3817.                           │ ║ SIGNIFICAND 31-16 ║ +86
  3818.                           │ ╟───────────────────╢
  3819.                 LAST STACK┤ ║ SIGNIFICAND 47-32 ║ +88
  3820.              ELEMENT:ST(7)│ ╟───────────────────╢
  3821.                           │ ║ SIGNIFICAND 63-48 ║ +90
  3822.                           │ ╟──────────────────╢
  3823.                           │ ║S│  EXPONENT 14-0  ║ +92
  3824.                           └─╚═╧═════════════════╝
  3825.  
  3826.  ─────────────────────────────────────────────────────────────────────────────
  3827.  NOTES:
  3828.    a = INSTRUCTION POINTER
  3829.    b = OPERAND POINTER
  3830.    S = Sign
  3831.    Bit 0 of each field is rightmost, least significant
  3832.          bit of corresponding register field.
  3833.    Bit 63 of significand is integer bit (assumed
  3834.          binary point is immediately to the right.)
  3835.  ─────────────────────────────────────────────────────────────────────────────
  3836.  
  3837.  
  3838.  FRSTOR source
  3839.  FRSTOR (restore state) reloads the 80287 from the 94-byte memory area
  3840.  defined by the source operand. This information should have been written by
  3841.  a previous FSAVE/FNSAVE instruction and not altered by any other
  3842.  instruction. An FWAIT is not required after FRSTOR. FRSTOR will
  3843.  automatically wait and check for interrupts until all data transfers are
  3844.  completed before continuing to the next instruction.
  3845.  
  3846.  Note that the 80287 "reacts" to its new state at the conclusion of the
  3847.  FRSTOR; it will, for example, generate an exception request if the exception
  3848.  and mask bits in the memory image so indicate when the next WAIT or
  3849.  error-checking-ESC instruction is executed.
  3850.  
  3851.  
  3852.  FSTENV/FNSTENV destination
  3853.  FSTENV/FNSTENV (store environment) writes the 80287's basic
  3854.  status──control, status, and tag words, and exception pointers──to the
  3855.  memory location defined by the destination operand. Typically, the
  3856.  environment is saved on the CPU stack. FSTENV/FNSTENV is often used by
  3857.  exception handlers because it provides access to the exception pointers that
  3858.  identify the offending instruction and operand. After saving the
  3859.  environment, FSTENV/FNSTENV sets all exception masks in the processor.
  3860.  FSTENV checks for pending errors before executing, FNSTENV does not.
  3861.  
  3862.  Figure 2-2 shows the format of the environment data in memory. FNSTENV does
  3863.  not store the environment until all NPX activity has completed. Thus, the
  3864.  data saved by the instruction reflects the 80287 after any previously
  3865.  decoded instruction has been executed. After writing the environment image
  3866.  to memory, FNSTENV/FSTENV initializes the 80287 state as if FNINIT/FINIT
  3867.  had been executed.
  3868.  
  3869.  FSTENV/FNSTENV must be allowed to complete before any other 80287
  3870.  instruction is decoded. When FSTENV is coded, an explicit FWAIT, or
  3871.  assembler-generated WAIT, should precede any subsequent 80287 instruction.
  3872.  
  3873.  
  3874.  Figure 2-2.  FSTENV/FLDENV Memory Layout
  3875.  
  3876.              REAL MODE                            PROTECTED MODE
  3877.    15                            0 MEMORY  15                        0 MEMORY
  3878.   ╔═══════════════════════════════╗OFFSET ╔═══════════════════════════╗OFFSET
  3879.   ║         CONTROL WORD          ║ +0    ║       CONTROL WORD        ║ +0
  3880.   ╟───────────────────────────────╢       ╟───────────────────────────╢
  3881.   ║          STATUS WORD          ║ +2    ║        STATUS WORD        ║ +2
  3882.   ╟───────────────────────────────╢       ╟───────────────────────────╢
  3883.   ║           TAG WORD            ║ +4    ║         TAG WORD          ║ +4
  3884.   ╟───────────────────────────────╢       ╟───────────────────────────╢
  3885.   ║   INSTRUCTION POINTER(15-0)   ║ +6    ║         IP OFFSET         ║ +6
  3886.   ╟───────────┬─┬─────────────────╢       ╟───────────────────────────╢
  3887.   ║INSTRUCTION│ │   INSTRUCTION   ║       ║                           ║
  3888.   ║  POINTER  │0│     OPCODE      ║ +8    ║        CS SELECTOR        ║ +8
  3889.   ║  (19-14)  │ │     (10-0)      ║       ║                           ║
  3890.   ╟───────────┴─┴─────────────────╢       ╟───────────────────────────╢
  3891.   ║      DATA POINTER(15-0)       ║ +10   ║    DATA OPERAND OFFSET    ║ +10
  3892.   ╟───────────┬───────────────────╢       ╟───────────────────────────╢
  3893.   ║   DATA    │                   ║       ║                           ║
  3894.   ║  POINTER  │         0         ║ +12   ║   DATA OPERAND SELECTOR   ║ +12
  3895.   ║  (19-16)  │                   ║       ║                           ║
  3896.   ╚═══════════╧═══════════════════╝       ╚═══════════════════════════╝
  3897.    15       12 11                0
  3898.  
  3899.  
  3900.  FLDENV source
  3901.  FLDENV (load environment) reloads the environment from the memory area
  3902.  defined by the source operand. This data should have been written by a
  3903.  previous FSTENV/FNSTENV instruction. CPU instructions (that do not reference
  3904.  the environment image) may immediately follow FLDENV. An FWAIT is not
  3905.  required after FLDENV. FLDENV will automatically wait for all data
  3906.  transfers to complete before executing the next instruction.
  3907.  
  3908.  Note that loading an environment image that contains an unmasked exception
  3909.  will cause a numeric exception when the next WAIT or error-checking-ESC
  3910.  instruction is executed.
  3911.  
  3912.  
  3913.  FINCSTP
  3914.  FINCSTP (increment stack pointer) adds 1 to the stack top pointer (ST) in
  3915.  the status word. It does not alter tags or register contents, nor does it
  3916.  transfer data. It is not equivalent to popping the stack, because it does
  3917.  not set the tag of the previous stack top to empty. Incrementing the stack
  3918.  pointer when ST = 7 produces ST = 0.
  3919.  
  3920.  
  3921.  FDECSTP
  3922.  FDECSTP (decrement stack pointer) subtracts 1 from ST, the stack top
  3923.  pointer in the status word. No tags or registers are altered, nor is any
  3924.  data transferred. Executing FDECSTP when ST = 0 produces ST = 7.
  3925.  
  3926.  
  3927.  FFREE destination
  3928.  FFREE (free register) changes the destination register's tag to empty; the
  3929.  content of the register is unaffected.
  3930.  
  3931.  
  3932.  FNOP
  3933.  FNOP (no operation) stores the stack top to the stack top (FST ST,ST(0))
  3934.  and thus effectively performs no operation.
  3935.  
  3936.  
  3937.  FWAIT (CPU Instruction)
  3938.  FWAIT is not actually an 80287 instruction, but an alternate mnemonic for
  3939.  the CPU WAIT instruction. The FWAIT or WAIT mnemonic should be coded
  3940.  whenever the programmer wants to synchronize the CPU to the NPX, that is, to
  3941.  suspend further instruction decoding until the NPX has completed the current
  3942.  instruction. FWAIT will check for unmasked numeric exceptions.
  3943.  
  3944.  ───────────────────────────────────────────────────────────────────────────
  3945.  NOTE
  3946.    A CPU instruction should not attempt to access a memory operand until the
  3947.    80287 instruction has completed. For example, the following coding shows
  3948.    how FWAIT can be used to force the CPU instruction to wait for the 80287:
  3949.  
  3950.       FIST     VALUE
  3951.       FWAIT    ; Wait for FIST to complete
  3952.       MOV      AX,VALUE
  3953.  ───────────────────────────────────────────────────────────────────────────
  3954.  
  3955.  More information on when to code an FWAIT instruction is given in a
  3956.  following section of this chapter, "Concurrent Processing with the 80287."
  3957.  
  3958.  
  3959.  Instruction Set Reference Information
  3960.  Table 2-14 later in this chapter lists the operating characteristics of all
  3961.  the 80287 instructions. There is one table entry for each instruction
  3962.  mnemonic; the entries are in alphabetical order for quick lookup. Each entry
  3963.  provides the general operand forms accepted by the instruction as well as a
  3964.  list of all exceptions that may be detected during the operation.
  3965.  
  3966.  One entry exists for each combination of operand types that can be coded
  3967.  with the mnemonic. Table 2-12 explains the operand identifiers allowed in
  3968.  table 2-14. Following this entry are columns that provide execution time in
  3969.  clocks, the number of bus transfers run during the operation, the length of
  3970.  the instruction in bytes, and an ASM286 coding sample.
  3971.  
  3972.  
  3973.  Instruction Execution Time
  3974.  The execution of an 80287 instruction involves three principal activities,
  3975.  each of which may contribute to the overall execution time of the
  3976.  instruction:
  3977.  
  3978.    ■  80286 CPU overhead involved in handling the ESC instruction opcode
  3979.       and setting up the 80287 NPX
  3980.  
  3981.    ■  Instruction execution by the 80287 NPX
  3982.  
  3983.    ■  Operand transfers between the 80287 NPX and memory or a CPU register
  3984.  
  3985.  The timing of these various activities is affected by the individual clock
  3986.  frequencies of the 80286 CPU and the 80287 NPX. In addition, slow memories
  3987.  requiring the insertion of wait states in bus cycles, and bus contention due
  3988.  to other processors in the system, may lengthen operand transfer times.
  3989.  
  3990.  In calculating an overall execution time for an individual numeric
  3991.  instruction, analysts must take each of these activities into account. In
  3992.  most cases, it can be assumed that the numeric instructions have already
  3993.  been prefetched by the 80286 and are awaiting execution.
  3994.  
  3995.    ■  The CPU overhead in handling the ESC instruction opcode takes only a
  3996.       single CPU bus cycle before the 80287 begins its execution of the
  3997.       numeric instruction. The timing of this bus cycle is determined by the
  3998.       CPU clock. Additional CPU activity is required to set up the 80287's
  3999.       instruction and data pointer registers, but this activity occurs after
  4000.       the 80287 has begun executing its instruction, and so this parallel
  4001.       activity does not affect total execution time.
  4002.  
  4003.    ■  The duration of individual numeric instructions executing on the 80287
  4004.       varies for each instruction. Table 2-14 quotes a typical execution
  4005.       clock count and a range for each 80287 instruction. Dividing the
  4006.       figures in the table by 10 (for a 10-MHz 80287 NPX clock) produces an
  4007.       execution time in microseconds. The typical case is an estimate for
  4008.       operand values that normally characterize most applications. The range
  4009.       encompasses best- and worst-case operand values that may be found in
  4010.       extreme circumstances.
  4011.  
  4012.    ■  The operand transfer time required to transfer operands between the
  4013.       80287 and memory or a CPU register depends on the number of words to be
  4014.       transferred, the frequency of the CPU clock controlling bus timing, the
  4015.       number of wait states added to accommodate slower memories, and
  4016.       whether operands are based at even or odd memory addresses. Some
  4017.       (small) additional number of bus cycles may also be lost due to the
  4018.       asynchronous nature of the PEREQ/PEACK handshaking between the 80286
  4019.       and 80287, and this interaction varies with relative frequencies of
  4020.       the CPU and NPX clocks.
  4021.  
  4022.  The execution clock counts for the NPX execution of instructions shown in
  4023.  table 2-14 assume that no exceptions are detected during execution. Invalid
  4024.  operation, denormalized operand (unmasked), and zero divide exceptions
  4025.  usually decrease execution time from the typical figure, but execution
  4026.  still falls within the indicated range. The precision exception has no
  4027.  effect on execution time. Unmasked overflow and underflow, and masked
  4028.  denormalized exceptions impose additional execution penalties as shown in
  4029.  table 2-13. Absolute worst-case execution times are therefore the high
  4030.  range figure plus the largest penalty that may be encountered.
  4031.  
  4032.  
  4033.  Table 2-12. Key to Operand Types
  4034.  
  4035. ╓┌───────────────┌───────────────────────────────────────────────────────────╖
  4036.  Identifier      Explanation
  4037.  
  4038.  ST              Stack top; the register currently at the top of the stack.
  4039.  
  4040.  ST(i)           A register in the stack i (0≤i≤7) stack elements from the
  4041.                  top. ST(1) is the next-on-stack register, ST(2) is below
  4042.                  ST(1), etc.
  4043.  
  4044.  Short-real      A short real (32 bits) number in memory.
  4045.  
  4046.  Long-real       A long real (64 bits) number in memory.
  4047.  
  4048.  Temp-real       A temporary real (80 bits) number in memory.
  4049.  
  4050.  Packed-decimal  A packed decimal integer (18 digits, 10 bytes) in memory.
  4051.  
  4052.  Word-integer    A word binary integer (16 bits) in memory.
  4053.  
  4054.  Short-integer   A short binary integer (32 bits) in memory.
  4055.  Identifier      Explanation
  4056. Short-integer   A short binary integer (32 bits) in memory.
  4057.  
  4058.  Long-integer    A long binary integer (64 bits) in memory.
  4059.  
  4060.  nn-bytes        A memory area nn bytes long.
  4061.  
  4062.  
  4063.  Bus Transfers
  4064.  NPX instructions that reference memory require bus cycles to transfer
  4065.  operands between the NPX and memory. The actual number of transfers depends
  4066.  on the length of the operand and the alignment of the operand in memory.
  4067.  In table 2-14, the first figure gives execution clocks for even-addressed
  4068.  operands, while the second gives the clock count for odd-addressed operands.
  4069.  
  4070.  For operands aligned at word boundaries, that is, based at even memory
  4071.  addresses, each word to be transferred requires one bus cycle between the
  4072.  80286 data channel and memory, and one bus cycle to the NPX. For operands
  4073.  based at odd memory addresses, each word transfer requires two bus cycles
  4074.  to transfer individual bytes between the 80286 data channel and memory, and
  4075.  one bus cycle to the NPX.
  4076.  
  4077.  ───────────────────────────────────────────────────────────────────────────
  4078.  NOTE
  4079.    For best performance, operands for the 80287 should be aligned along word
  4080.    boundaries; that is, based at even memory addresses. Operands based at odd
  4081.    memory addresses are transferred to memory essentially byte-at-a-time and
  4082.    may take half again as long to transfer as word-aligned operands.
  4083.  ───────────────────────────────────────────────────────────────────────────
  4084.  
  4085.  Additional transfer time is required if slow memories are being used,
  4086.  requiring the insertion of wait states into the CPU bus cycle. In
  4087.  multiprocessor environments, the bus may not be available immediately; this
  4088.  overhead can also increase effective transfer time.
  4089.  
  4090.  
  4091.  Table 2-13. Execution Penalties
  4092.  
  4093.  Exception                 Additional Clocks
  4094.  Overflow (unmasked)              14
  4095.  Underflow (unmasked)             16
  4096.  Denormalized (masked)            33
  4097.  
  4098.  
  4099.  Instruction Length
  4100.  80287 instructions that do not reference memory are two bytes long. Memory
  4101.  reference instructions vary between two and four bytes. The third and fourth
  4102.  bytes are for the 8- or 16-bit displacement values used in conjunction with
  4103.  the standard 80286 memory-addressing modes.
  4104.  
  4105.  Note that the lengths quoted in table 2-14 for the processor control
  4106.  instructions (FNINIT, FNSTCW, FNSTSW, FNSTSW AX, FNCLEX, FNSTENV, and
  4107.  FNSAVE) do not include the one-byte CPU wait instruction inserted by the
  4108.  ASM286 assembler if the control instruction is coded using the wait form of
  4109.  the mnemonic (e.g. FINIT, FSTCW, FSTSW, FSTSW AX, FCLEX, FSTENV, and
  4110.  FSAVE). Wait and no-wait forms of the processor control instructions have
  4111.  been described in the preceding section titled "Processor Control
  4112.  Instructions."
  4113.  
  4114.  
  4115.  Table 2-14. Instruction Set Reference Data
  4116.  
  4117. ╓┌────────────────────┌──────────────────────┌───────────────┌───────┌───────
  4118.                       ⌐Execution Clocks¬     Operand Word    Code
  4119.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4120.  ─────────────────────────────────────────────────────────────────────────────
  4121.  FABS                  FABS (no operands)
  4122.                        Absolute value                        Exceptions: I
  4123.  
  4124.  (no operands)         14         10-17          0           2       FABS
  4125.  ─────────────────────────────────────────────────────────────────────────────
  4126.  FADD                  FADD\\source\destination,source
  4127.                        Add real                              Execptions: I,D,O
  4128.  
  4129.  \\ST,ST(i)\ST(i),ST   85         70-100         0           2       FADD,ST,S
  4130.  short-real            105        90-120         2           2-4     FADD AIR_
  4131.  long-real             110        95-125         4           2-4     FADD [BX]
  4132.  ─────────────────────────────────────────────────────────────────────────────
  4133.  FADDP                 FADDP destination, source
  4134.                        Add real and pop                      Exceptions: I,D,O
  4135.  
  4136.  ST(i),ST              90         75-105         0           2       FADDP ST(
  4137.  ─────────────────────────────────────────────────────────────────────────────
  4138.  FBLD                  FBLD source
  4139.                       ⌐Execution Clocks¬     Operand Word    Code
  4140.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4141. FBLD                  FBLD source
  4142.                        Packed decimal (BCD) load             Exceptions: I
  4143.  
  4144.  packed-decimal        300        290-310        5           2-4     FBLD YTD_
  4145.  ─────────────────────────────────────────────────────────────────────────────
  4146.  FBSTP                 FBSTP destination
  4147.                        Packed decimal (BCD) store and pop    Exceptions: I
  4148.  
  4149.  packed-decimal        530        520-540        5           2-4     FBSTP [BX
  4150.  ─────────────────────────────────────────────────────────────────────────────
  4151.  FCHS                  FCHS (no operands)
  4152.                        Change sign                           Exceptions: I
  4153.  (no operands)         15         10-17          0           2       FCHS
  4154.  ─────────────────────────────────────────────────────────────────────────────
  4155.  FCLEX/FNCLEX          FCLEX/FNCLEX(no operands)
  4156.                        Clear exceptions                      Exceptions: None
  4157.  
  4158.  (no operands)         5          2-8            0           2       FNCLEX
  4159.  ─────────────────────────────────────────────────────────────────────────────
  4160.                       ⌐Execution Clocks¬     Operand Word    Code
  4161.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4162. ─────────────────────────────────────────────────────────────────────────────
  4163.  FCOM                  FCOM //source
  4164.                        Compare real                          Exceptions: I, D
  4165.  
  4166.  //ST(i)               45         40-50          0           2       FCOM ST(1
  4167.  short-real            65         60-70          2           2-4     FCOM [BP]
  4168.  long-real             70         65-75          4           2-4     FCOM WAVE
  4169.  ─────────────────────────────────────────────────────────────────────────────
  4170.  FCOMP                 FCOMP //source
  4171.                        Compare real and pop                  Exceptions: I, D
  4172.  
  4173.  //ST(i)               47         42-52          0           2       FCOMP ST(
  4174.  short-real            68         63-73          2           2-4     FCOMP [BP
  4175.  long-real             72         67-77          4           2-4     FCOMP DEN
  4176.  ─────────────────────────────────────────────────────────────────────────────
  4177.  FCOMPP                FCOMPP (no operands)
  4178.                        Compare real and pop twice                    Exception
  4179.  
  4180.  (no operands)         50         45-55          0           2       FCOMPP
  4181.                       ⌐Execution Clocks¬     Operand Word    Code
  4182.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4183. (no operands)         50         45-55          0           2       FCOMPP
  4184.  ─────────────────────────────────────────────────────────────────────────────
  4185.  FDECSTP               FDECSTP (no operands)
  4186.                        Decrement stack pointer               Exceptions: None
  4187.  
  4188.  (no operands)         9          6-12           0           2       FDECSTP
  4189.  ─────────────────────────────────────────────────────────────────────────────
  4190.  FDIV                  FDIV //source/destination,source
  4191.                        Divide real                           Exceptions: I, D,
  4192.  
  4193.  //ST(i),ST            198        193-203        0           2       FDIV
  4194.  short-real            220        215-225        2           2-4     FDIV DIST
  4195.  long-real             225        220-230        4           2-4     FDIV ARC
  4196.  ─────────────────────────────────────────────────────────────────────────────
  4197.  FDIVP                 FDIVP destination, source
  4198.                        Divide real and pop                   Exceptions: I, D,
  4199.  
  4200.  ST(i),ST              202        197-207        0           2       FDIVP ST(
  4201.  ─────────────────────────────────────────────────────────────────────────────
  4202.                       ⌐Execution Clocks¬     Operand Word    Code
  4203.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4204. ─────────────────────────────────────────────────────────────────────────────
  4205.  FDIVR                 FDIVR //source/destination, source
  4206.                        Divide real reversed                  Exceptions: I, D,
  4207.  
  4208.  //ST,ST(i)/ST(i),ST   199        194-204        0           2       FDIVR ST(
  4209.  short-real            221        216-226        2           2-4     FDIVR [BX
  4210.  long-real             226        221-231        4           2-4     FDIVR REC
  4211.  ─────────────────────────────────────────────────────────────────────────────
  4212.  FDIVRP                FDIVRP destination, source
  4213.                        Divide real reversed and pop          Exceptions: I, D,
  4214.  
  4215.  ST(i),ST              203        198-208        0           2       FDIVRP ST
  4216.  ─────────────────────────────────────────────────────────────────────────────
  4217.  FFREE                 FFREE destination
  4218.                        Free register                         Exceptions: None
  4219.  
  4220.  ST(i)                 11         9-16           0           2       FFREE ST(
  4221.  ─────────────────────────────────────────────────────────────────────────────
  4222.  FIADD                 FIADD source
  4223.                       ⌐Execution Clocks¬     Operand Word    Code
  4224.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4225. FIADD                 FIADD source
  4226.                        Integer add                           Exceptions: I, D,
  4227.  
  4228.  word-integer          120        102-137        1           2-4     FIADD DIS
  4229.  short-integer         125        108-143        2           2-4     FIADD PUL
  4230.  ─────────────────────────────────────────────────────────────────────────────
  4231.  FICOM                 FICOM source
  4232.                        Integer compare                       Exceptions: I, D
  4233.  
  4234.  word-integer          80         72-86          1           2-4     FICOM TOO
  4235.  short-integer         85         78-91          2           2-4     FICOM [BP
  4236.  ─────────────────────────────────────────────────────────────────────────────
  4237.  FICOMP                FICOMP source
  4238.                        Integer compare and pop               Exceptions: I, D
  4239.  
  4240.  word-integer          82         74-88          1           2-4     FICOMP [B
  4241.  short-integer         87         80-93          2           2-4     FICOMP N_
  4242.  ─────────────────────────────────────────────────────────────────────────────
  4243.  FIDIV                 FIDIV source
  4244.                       ⌐Execution Clocks¬     Operand Word    Code
  4245.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4246. FIDIV                 FIDIV source
  4247.                        Integer divide                        Exceptions: I, D,
  4248.  
  4249.  word-integer          230        224-238        1           2-4     FIDIV SUR
  4250.  short-integer         236        230-243        2           2-4     FIDIV REL
  4251.  ─────────────────────────────────────────────────────────────────────────────
  4252.  FIDIVR                FIDIVR source
  4253.                        Integer divide reversed               Exceptions: I, D,
  4254.  
  4255.  word-integer          230        225-239        1           2-4     FIDIVR [B
  4256.  short-integer         237        231-245        2           2-4     FIDIVR FR
  4257.  ─────────────────────────────────────────────────────────────────────────────
  4258.  FILD                  FILD source
  4259.                        Integer load                          Exceptions: I
  4260.  
  4261.  word-integer          50         46-54          1           2-4     FILD [BX]
  4262.  short-integer         56         52-60          2           2-4     FILD STAN
  4263.  long-integer          64         60-68          4           2-4     FILD RESP
  4264.  ─────────────────────────────────────────────────────────────────────────────
  4265.                       ⌐Execution Clocks¬     Operand Word    Code
  4266.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4267. ─────────────────────────────────────────────────────────────────────────────
  4268.  FIMUL                 FIMUL source
  4269.                        Integer multiply                      Exceptions: I, D,
  4270.  
  4271.  word-integer          130        124-138        1           2-4     FIMUL BEA
  4272.  short-integer         136        130-144        2           2-4     FIMUL POS
  4273.  ─────────────────────────────────────────────────────────────────────────────
  4274.  FINCSTP               FINCSTP (no operands)
  4275.                        Increment stack pointer               Exceptions: None
  4276.  
  4277.  (no operands)         9          6-12           0           2       FINCSTP
  4278.  ─────────────────────────────────────────────────────────────────────────────
  4279.  FINIT/FNINIT          FINIT/FNINIT (no operands)
  4280.                        Initialize processor                  Exceptions: None
  4281.  
  4282.  (no operands)         5          2-8            0           2       FINIT
  4283.  ─────────────────────────────────────────────────────────────────────────────
  4284.  FIST                  FIST destination
  4285.                        Integer store                         Exceptions: I, P
  4286.                       ⌐Execution Clocks¬     Operand Word    Code
  4287.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4288.                       Integer store                         Exceptions: I, P
  4289.  
  4290.  word-integer          86         80-90          1           2-4     FIST OBS.
  4291.  short-integer         88         82-92          2           2-4     FIST [BP;
  4292.  ─────────────────────────────────────────────────────────────────────────────
  4293.  FISTP                 FISTP destination
  4294.                        Integer store and pop                 Exceptions: I, P
  4295.  
  4296.  word-integer          88         82-92          1           2-4     FISTP [BX
  4297.  short-integer         90         84-94          2           2-4     FISTP COR
  4298.  long-integer          100        94-105         4           2-4     FISTP PAN
  4299.  ─────────────────────────────────────────────────────────────────────────────
  4300.  FISUB                 FISUB source
  4301.                        Integer subtract                      Exceptions: I, D,
  4302.  
  4303.  word-integer          120        102-137        1           2-4     FISUB BAS
  4304.  short-integer         125        108-143        2           2-4     FISUB TRA
  4305.  ─────────────────────────────────────────────────────────────────────────────
  4306.  FISUBR                FISUBR source
  4307.                       ⌐Execution Clocks¬     Operand Word    Code
  4308.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4309. FISUBR                FISUBR source
  4310.                        Integer subtract reversed             Exceptions: I, D,
  4311.  
  4312.  word-integer          120        103-139        1           2-4     FISUBR FL
  4313.  short-integer         125        109-144        2           2-4     FISUBR BA
  4314.  ─────────────────────────────────────────────────────────────────────────────
  4315.  FLD                   FLD source
  4316.                        Load real                             Exceptions: I, D
  4317.  
  4318.  ST(i)                 20         17-22          0           2       FLD ST(0)
  4319.  short-real            43         38-56          2           2-4     FLD READI
  4320.  long-real             46         40-60          4           2-4     FLD BP].T
  4321.  temp-real             57         53-65          5           2-4     FLD SAVER
  4322.  ─────────────────────────────────────────────────────────────────────────────
  4323.  FLDCW                 FLDCW source
  4324.                        Load control word                     Exceptions: None
  4325.  
  4326.  2-bytes               10         7-14           1           2-4     FLDCW CON
  4327.  ─────────────────────────────────────────────────────────────────────────────
  4328.                       ⌐Execution Clocks¬     Operand Word    Code
  4329.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4330. ─────────────────────────────────────────────────────────────────────────────
  4331.  FLDENV                FLDENV source
  4332.                        Load environment                      Exceptions: None
  4333.  
  4334.  14-bytes              40         35-45          7           2-4     FLDENV [B
  4335.  ─────────────────────────────────────────────────────────────────────────────
  4336.  FLDLG2                FLDLG2 (no operands)
  4337.                        Load log{10}2                         Exceptions: I
  4338.  
  4339.  (no operands)         21         18-24          0           2       FLDLG2
  4340.  ─────────────────────────────────────────────────────────────────────────────
  4341.  FLDLN2                FLDLN2 (no operands)
  4342.                        Load log{e}2                          Exceptions: I
  4343.  
  4344.  (no operands)         20         17-23          0           2       FLDLN2
  4345.  ─────────────────────────────────────────────────────────────────────────────
  4346.  FLDL2E                FLDL2E (no operands)
  4347.                        Load log{2}e                          Exceptions: I
  4348.  
  4349.                       ⌐Execution Clocks¬     Operand Word    Code
  4350.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4351. 
  4352.  (no operands)         18         15-21          0           2       FLDL2E
  4353.  ─────────────────────────────────────────────────────────────────────────────
  4354.  FLDL2T                FLDL2T (no operands)
  4355.                        Load log{2}10                         Exceptions: I
  4356.  
  4357.  (no operands)         19         16-22          0           2       FLDL2T
  4358.  ─────────────────────────────────────────────────────────────────────────────
  4359.  FLDPI                 FLDPI (no operands)
  4360.                        Load π                                Exceptions: I
  4361.  
  4362.  (no operands)         19         16-22          0           2       FLDPI
  4363.  ─────────────────────────────────────────────────────────────────────────────
  4364.  FLDZ                  FLDZ (no operands)
  4365.                        Load +0.0                             Exceptions: I
  4366.  
  4367.  (no operands)         14         11-17          0           2       FLDZ
  4368.  ─────────────────────────────────────────────────────────────────────────────
  4369.  FLD1                  FLD1 (no operands)
  4370.                       ⌐Execution Clocks¬     Operand Word    Code
  4371.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4372. FLD1                  FLD1 (no operands)
  4373.                        Load +1.0                             Exceptions: I
  4374.  
  4375.  (no operands)         18         15-21          0           2       FLD1
  4376.  ─────────────────────────────────────────────────────────────────────────────
  4377.  FMUL                  FMUL //source/destination,source
  4378.                        Multiply real                         Exceptions: I, D,
  4379.  
  4380.  //ST(i),ST/T,ST(i)    97         90-105        0           2       FMUL ST,S
  4381.  //ST(i),ST/ST,ST(i)   138        130-145        0           2       FMUL ST,S
  4382.  short-real            118        110-125        2           2-4     FMUL SPEE
  4383.  long-real            120        112-126        4           2-4     FMUL [BP]
  4384.  long-real             161        154-168        4           2-4     FMUL [BP]
  4385.  ─────────────────────────────────────────────────────────────────────────────
  4386.  FMULP                 FMULP destination, source
  4387.                        Multiply real and pop                 Exceptions: I, D,
  4388.  
  4389.  ST(i),ST             100        94-108         0           2       FMULP ST(
  4390.  ST(i),ST              142        134-148        0           2       FMULP ST(
  4391.                       ⌐Execution Clocks¬     Operand Word    Code
  4392.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4393. ST(i),ST              142        134-148        0           2       FMULP ST(
  4394.  ─────────────────────────────────────────────────────────────────────────────
  4395.  FNOP                  FNOP (no operands)
  4396.                        No operation                          Exceptions: None
  4397.  
  4398.  (no operands)         13         10-16          0           2       FNOP
  4399.  ─────────────────────────────────────────────────────────────────────────────
  4400.  FPATAN                FPATAN (no operands)
  4401.                        Partial arctangent                    Exceptions: U, P
  4402.  
  4403.  (no operands)         650        250-800        0           2       FPATAN
  4404.  ─────────────────────────────────────────────────────────────────────────────
  4405.  FPREM                 FPREM (no operands)
  4406.                        Partial remainder                     Exceptions: I, D,
  4407.  
  4408.  (no operands)         125        15-190         0           2       FPREM
  4409.  ─────────────────────────────────────────────────────────────────────────────
  4410.  FPTAN                 FPTAN (no operands)
  4411.                        Partial tangent                       Exceptions: I, P
  4412.                       ⌐Execution Clocks¬     Operand Word    Code
  4413.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4414.                       Partial tangent                       Exceptions: I, P
  4415.  
  4416.  (no operands)         450        30-540         0           2       FPTAN
  4417.  ─────────────────────────────────────────────────────────────────────────────
  4418.  FRNDINT               FRNDINT (no operands)
  4419.                        Round to integer                      Exceptions: I, P
  4420.  
  4421.  (no operands)         45         16-50          0           2       FRNDINT
  4422.  ─────────────────────────────────────────────────────────────────────────────
  4423.  FRSTOR                FRSTOR source
  4424.                        Restore saved state                   Exceptions: None
  4425.  
  4426.  94-bytes                            ()         47          2-4     FRSTOR [B
  4427.  ─────────────────────────────────────────────────────────────────────────────
  4428.  FSAVE/FNSAVE          FSAVE/FNSAVE destination
  4429.                        Save state                            Exceptions: None
  4430.  
  4431.  94-bytes                            ()         47          2-4     FSAVE [BP
  4432.  ─────────────────────────────────────────────────────────────────────────────
  4433.                       ⌐Execution Clocks¬     Operand Word    Code
  4434.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4435. ─────────────────────────────────────────────────────────────────────────────
  4436.  FSCALE                FSCALE (no operands)
  4437.                        Scale                                 Exceptions: I, O,
  4438.  
  4439.  (no operands)         35         32-38           0           2      FSCALE
  4440.  ─────────────────────────────────────────────────────────────────────────────
  4441.  FSETPM                FSETPM (no operands)
  4442.                        Set protected mode                    Exceptions: None
  4443.  
  4444.  (no operands)                     2-8            0           2      FSETPM
  4445.  ─────────────────────────────────────────────────────────────────────────────
  4446.  FSQRT                 FSQRT (no operands)
  4447.                        Square root                           Exceptions: I, D,
  4448.  
  4449.  (no operands)         183          80-186         0         2       FSQRT
  4450.  ─────────────────────────────────────────────────────────────────────────────
  4451.  FST                   FST destination
  4452.                        Store real                            Exceptions: I, O,
  4453.  
  4454.                       ⌐Execution Clocks¬     Operand Word    Code
  4455.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4456. 
  4457.  ST(i)                  18          15-22          0         2       FST ST(3)
  4458.  short-real             87          84-90          2         2-4     FST CORRE
  4459.  long-real             100          96-104         4         2-4     FST MEAN_
  4460.  ─────────────────────────────────────────────────────────────────────────────
  4461.  FSTCW/                FSTCW destination
  4462.  FNSTCW                Store control word                    Exceptions: None
  4463.  
  4464.  2-bytes               15           12-18          1         2-4     FSTCW SAV
  4465.  ─────────────────────────────────────────────────────────────────────────────
  4466.  FSTENV/               FSTENV destination
  4467.  FNSTENV               Store environment                     Exceptions: None
  4468.  
  4469.  14-bytes              45           40-50          7         2-4     FSTENV [B
  4470.  ─────────────────────────────────────────────────────────────────────────────
  4471.  FSTP                  FSTP destination
  4472.                        Store real and pop                    Exceptions: I, O,
  4473.  
  4474.  ST(i)                  20          17-24          0         2       FSTP ST(2
  4475.                       ⌐Execution Clocks¬     Operand Word    Code
  4476.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4477. ST(i)                  20          17-24          0         2       FSTP ST(2
  4478.  short-real             89          86-92          2         2-4     FSTP [BX]
  4479.  long-real             102          98-106         4         2-4     FSTP TOTA
  4480.  temp-real              55          52-58          5         2-4     FSTP REG_
  4481.  ─────────────────────────────────────────────────────────────────────────────
  4482.  FSTSW/                FSTSW destination
  4483.  FNSTSW                Store status word                     Exceptions: None
  4484.  
  4485.  2-bytes               15           12-18          1         2-4     FSTSW SAV
  4486.  ─────────────────────────────────────────────────────────────────────────────
  4487.  FSTSW AX/             FSTSW AX
  4488.  FNSTSWAX              Store status word to AX               Exceptions: None
  4489.  
  4490.  AX                                 10-16          1         2       FSTSW AX
  4491.  ─────────────────────────────────────────────────────────────────────────────
  4492.  FSUB                  FSUB //source/destination,source
  4493.                        Subtract real                         Exceptions: I, D,
  4494.  
  4495.  //ST,ST(i)/ST(i),ST    85          70-100         0         2       FSUB ST,S
  4496.                       ⌐Execution Clocks¬     Operand Word    Code
  4497.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4498. //ST,ST(i)/ST(i),ST    85          70-100         0         2       FSUB ST,S
  4499.  short-real            105          90-120         2         2-4     FSUB BASE
  4500.  long-real             110          95-125         4         2-4     FSUB COOR
  4501.  ─────────────────────────────────────────────────────────────────────────────
  4502.  FSUBP                 FSUBP destination, source
  4503.                        Subtract real and pop                 Exceptions: I, D,
  4504.  
  4505.  ST(i),ST              90           75-105         0         2       FSUBP ST(
  4506.  ─────────────────────────────────────────────────────────────────────────────
  4507.  FSUBR                 FSUBR //source/destination, source
  4508.                        Subtract real reversed                Exceptions: I, D,
  4509.  
  4510.  //ST,ST(i)/ST(i),ST    87          70-100         0         2       FSUBR ST,
  4511.  short-real            105          90-120         2         2-4     FSUBR VEC
  4512.  long-real             110          95-125         4         2-4     FSUBR [BX
  4513.  ─────────────────────────────────────────────────────────────────────────────
  4514.  FSUBRP                FSUBRP destination, source
  4515.                        Subtract real reversed and pop        Exceptions: I, D,
  4516.  
  4517.                       ⌐Execution Clocks¬     Operand Word    Code
  4518.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4519. 
  4520.  ST(i),ST              90           75-105         0         2       FSUBRP ST
  4521.  ─────────────────────────────────────────────────────────────────────────────
  4522.  FTST                  FTST (no operands)
  4523.                        Test stack top against +0.0           Exceptions: I, D
  4524.  (no operands)         42           38-48          0         2       FTST
  4525.  ─────────────────────────────────────────────────────────────────────────────
  4526.  FWAIT                 FWAIT (no operands)
  4527.                        (CPU) Wait while 80287 is busy        Exceptions: None
  4528.  
  4529.  (no operands)         3+5n        3+5n          0         1       FWAIT
  4530.  ─────────────────────────────────────────────────────────────────────────────
  4531.  FXAM                  FXAM (no operands)
  4532.                        Examine stack top                     Exceptions: None
  4533.  
  4534.  (no operands)         17           12-23          0         2       FXAM
  4535.  ─────────────────────────────────────────────────────────────────────────────
  4536.  FXCH                  FXCH //destination
  4537.                        Exchange registers                            Exception
  4538.                       ⌐Execution Clocks¬     Operand Word    Code
  4539.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4540.                       Exchange registers                            Exception
  4541.  
  4542.  //ST(i)               12           10-15          0         2       FXCH ST(2
  4543.  ─────────────────────────────────────────────────────────────────────────────
  4544.  FXTRACT               FXTRACT (no operands)
  4545.                        Extract exponent and significant              Exception
  4546.  
  4547.  (no operands)         50           27-55          0         2       FXTRACT
  4548.  ─────────────────────────────────────────────────────────────────────────────
  4549.  FYL2X                 FYL2X (no operands)
  4550.                        Y * Log{2}X                           Exceptions: P (op
  4551.  
  4552.  (no operands)         950        900-1100         0         2       FYL2X
  4553.  ─────────────────────────────────────────────────────────────────────────────
  4554.  FYL2XP1               FYL2XP1 (no operands)
  4555.                        Y * log{2}(X + 1)                     Exceptions: P (op
  4556.  
  4557.  (no operands)         850        700-1000         0         2       FYL2XP1
  4558.  ─────────────────────────────────────────────────────────────────────────────
  4559.                       ⌐Execution Clocks¬     Operand Word    Code
  4560.  Operands              Typical    Range       Transfers      Bytes   Coding Ex
  4561. ─────────────────────────────────────────────────────────────────────────────
  4562.  F2XM1                 F2XM1 (no operands)
  4563.                        2^(2-1)                             Exceptions: U, P (o
  4564.  
  4565.  (no operands)         500        310-630          0         2       F2XM1
  4566.  ─────────────────────────────────────────────────────────────────────────────
  4567.  
  4568.  
  4569.  
  4570.  Programming Facilities
  4571.  As described previously, the 80287 NPX is programmed simply as an extension
  4572.  of the 80286 CPU. This section describes how programmers in ASM286 and in a
  4573.  variety of higher-level languages can work with the 80287.
  4574.  
  4575.  The level of detail in this section is intended to give programmers a basic
  4576.  understanding of the software tools that can be used with the 80287, but
  4577.  this information does not document the full capabilities of these
  4578.  facilities. For a complete list of documentation on all the languages
  4579.  available for 80286 systems, readers should consult Intel's Literature
  4580.  Guide.
  4581.  
  4582.  
  4583.  High-Level Languages
  4584.  For programmers using high-level languages, the programming and operation
  4585.  of the NPX is handled automatically by the compiler. A variety of Intel
  4586.  high-level languages are available that automatically make use of the 80287
  4587.  NPX when appropriate. These languages include
  4588.  
  4589.    PL/M-286
  4590.    FORTRAN-286
  4591.    PASCAL-286
  4592.    C-286
  4593.  
  4594.  Each of these high-level languages has special numeric libraries allowing
  4595.  programs to take advantage of the capabilities of the 80287 NPX. No special
  4596.  programming conventions are necessary to make use of the 80287 NPX when
  4597.  programming numeric applications in any of these languages.
  4598.  
  4599.  Programmers in PL/M-286 and ASM286 can also make use of many of these
  4600.  library routines by using routines contained in the 80287 Support Library,
  4601.  described in the 80287 Support Library Reference Manual, Order Number
  4602.  122129. These library routines provide many of the functions provided by
  4603.  higher-level languages, including exception handlers,
  4604.  ASCII-to-floating-point conversions, and a more complete set of
  4605.  transcendental functions than that provided by the 80287 instruction set.
  4606.  
  4607.  
  4608.  PL/M-286
  4609.  Programmers in PL/M-286 can access a very useful subset of the 80287's
  4610.  numeric capabilities. The PL/M-286 REAL data type corresponds to the NPX's
  4611.  short real (32-bit) format. This data type provides a range of about
  4612.  8.43*10^(-37) ≤ ABS(X) ≤ 3.38*10^(38), with about seven significant
  4613.  decimal digits. This representation is adequate for the data manipulated by
  4614.  many microcomputer applications.
  4615.  
  4616.  The utility of the REAL data type is extended by the PL/M-286 compiler's
  4617.  practice of holding intermediate results in the 80287's temporary real
  4618.  format. This means that the full range and precision of the processor are
  4619.  utilized for intermediate results. Underflow, overflow, and rounding errors
  4620.  are most likely to occur during intermediate computations rather than during
  4621.  calculation of an expression's final result. Holding intermediate results in
  4622.  temporary real format greatly reduces the likelihood of overflow and
  4623.  underflow and eliminates roundoff as a serious source of error until the
  4624.  final assignment of the result is performed.
  4625.  
  4626.  The compiler generates 80287 code to evaluate expressions that contain REAL
  4627.  data types, whether variables or constants or both. This means that
  4628.  addition, subtraction, multiplication, division, comparison, and assignment
  4629.  of REALs will be performed by the NPX. INTEGER expressions, on the other
  4630.  hand, are evaluated on the CPU.
  4631.  
  4632.  Five built-in procedures (table 2-15) give the PL/M-286 programmer access
  4633.  to 80287 functions manipulated by the processor control instructions. Prior
  4634.  to any arithmetic operations, a typical PL/M-286 program will set up the NPX
  4635.  after power up using the INIT$REAL$MATH$UNIT procedure and then issue
  4636.  SET$REAL$MODE to configure the NPX. SET$REAL$MODE loads the 80287 control
  4637.  word, and its 16-bit parameter has the format shown in figure 1-5. The
  4638.  recommended value of this parameter is 033EH (projective closure, round to
  4639.  nearest, 64-bit precision, all exceptions masked except invalid operation).
  4640.  Other settings may be used at the programmer's discretion.
  4641.  
  4642.  If any exceptions are unmasked, an exception handler must be provided in
  4643.  the form of an interrupt procedure that is designated to be invoked by CPU
  4644.  interrupt pointer (vector) number 16. The exception handler can use the
  4645.  GET$REAL$ERROR procedure to obtain the low-order byte of the 80287 status
  4646.  word and to then clear the exception flags. The byte returned by
  4647.  GET$REAL$ERROR contains the exception flags; these can be examined to
  4648.  determine the source of the exception.
  4649.  
  4650.  The SAVE$REAL$STATUS and RESTORE$REAL$STATUS procedures are provided for
  4651.  multi-tasking environments where a running task that uses the 80287 may be
  4652.  preempted by another task that also uses the 80287. It is the responsibility
  4653.  of the preempting task to issue SAVE$REAL$STATUS before it executes any
  4654.  statements that affect the 80287; these include the INIT$REAL$MATH$UNIT and
  4655.  SET$REAL$MODE procedures as well as arithmetic expressions.
  4656.  SAVE$REAL$STATUS saves the 80287 state (registers, status, and control
  4657.  words, etc.) on the CPU's stack. RESTORE$REAL$STATUS reloads the state
  4658.  information; the preempting task must invoke this procedure before
  4659.  terminating in order to restore the 80287 to its state at the time the
  4660.  running task was preempted. This enables the preempted task to resume
  4661.  execution from the point of its preemption.
  4662.  
  4663.  
  4664.  Table 2-15. PL/M-286 Built-In Procedures
  4665.  
  4666.                           80287
  4667.  Procedure                Instruction        Description
  4668.  
  4669.  INIT$REAL$MATH$UNIT     FINIT              Initialize processor.
  4670.  
  4671.  SET$REAL$MODE            FLDCW              Set exception masks, rounding
  4672.                                              precision, and infinity
  4673.                                              controls.
  4674.  
  4675.  GET$REAL$ERROR          FNSTSW & FNCLEX    Store, then clear, exception
  4676.                                              flags.
  4677.  
  4678.  SAVE$REAL$STATUS         FNSAVE             Save processor state.
  4679.  
  4680.  RESTORE$REAL$STATUS      FRSTOR             Restore processor state.
  4681.  
  4682.  
  4683.  ASM286
  4684.  The ASM286 assembly language provides programmmers with complete access to
  4685.  all of the facilities of the 80286 and 80287 processors.
  4686.  
  4687.  The programmer's view of the 80286/80287 hardware is a single machine with
  4688.  these resources:
  4689.  
  4690.    ■  160 instructions
  4691.    ■  12 data types
  4692.    ■  8 general registers
  4693.    ■  4 segment registers
  4694.    ■  8 floating-point registers, organized as a stack
  4695.  
  4696.  
  4697.  Defining Data
  4698.  The ASM286 directives shown in table 2-16 allocate storage for 80287
  4699.  variables and constants. As with other storage allocation directives, the
  4700.  assembler associates a type with any variable defined with these directives.
  4701.  The type value is equal to the length of the storage unit in bytes (10 for
  4702.  DT, 8 for DQ, etc.). The assembler checks the type of any variable coded in
  4703.  an instruction to be certain that it is compatible with the instruction. For
  4704.  example, the coding FIADD ALPHA will be flagged as an error if ALPHA's type
  4705.  is not 2 or 4, because integer addition is only available for word and
  4706.  short integer data types. The operand's type also tells the assembler which
  4707.  machine instruction to produce; although to the programmer there is only an
  4708.  FIADD instruction, a different machine instruction is required for each
  4709.  operand type.
  4710.  
  4711.  On occasion it is desirable to use an instruction with an operand that has
  4712.  no declared type. For example, if register BX points to a short integer
  4713.  variable, a programmer may want to code FIADD [BX]. This can be done by
  4714.  informing the assembler of the operand's type in the instruction, coding
  4715.  FIADD DWORD PTR [BX]. The corresponding overrides for the other storage
  4716.  allocations are WORD PTR, QWORD PTR, and TBYTE PTR.
  4717.  
  4718.  The assembler does not, however, check the types of operands used in
  4719.  processor control instructions. Coding FRSTOR [BP] implies that the
  4720.  programmer has set up register BP to point to the stack location where the
  4721.  processor's 94-byte state record has been previously saved.
  4722.  
  4723.  The initial values for 80287 constants may be coded in several different
  4724.  ways. Binary integer constants may be specified as bit strings, decimal
  4725.  integers, octal integers, or hexadecimal strings. Packed decimal values are
  4726.  normally written as decimal integers, although the assembler will accept
  4727.  and convert other representations of integers. Real values may be written as
  4728.  ordinary decimal real numbers (decimal point required), as decimal numbers
  4729.  in scientific notation, or as hexadecimal strings. Using hexadecimal strings
  4730.  is primarily intended for defining special values such as infinities, NaNs,
  4731.  and nonnormalized numbers. Most programmers will find that ordinary decimal
  4732.  and scientific decimal provide the simplest way to initialize 80287
  4733.  constants. Figure 2-3 compares several ways of setting the various 80287
  4734.  data types to the same initial value.
  4735.  
  4736.  Note that preceding 80287 variables and constants with the ASM286 EVEN
  4737.  directive ensures that the operands will be word-aligned in memory. This
  4738.  will produce the best system performance. All 80287 data types occupy
  4739.  integral numbers of words so that no storage is "wasted" if blocks of
  4740.  variables are defined together and preceded by a single EVEN declarative.
  4741.  
  4742.  
  4743.  Table 2-16. 80287 Storage Allocation Directives
  4744.  
  4745.  Directive    Interpretation        Data Types
  4746.  
  4747.  DW           Define Word           Word integer
  4748.  DD           Define Doubleword     Short integer, short real
  4749.  DQ           Define Quadword       Long integer, long real
  4750.  DT           Define Tenbyte        Packed decimal, temporary real
  4751.  
  4752.  
  4753.  Records and Structures
  4754.  The ASM286 RECORD and STRUC (structure) declaratives can be very useful in
  4755.  NPX programming. The record facility can be used to define the bit fields of
  4756.  the control, status, and tag words. Figure 2-4 shows one definition of the
  4757.  status word and how it might be used in a routine that polls the 80287 until
  4758.  it has completed an instruction.
  4759.  
  4760.  Because STRUCtures allow different but related data types to be grouped
  4761.  together, they often provide a natural way to represent "real world" data
  4762.  organizations. The fact that the structure template may be "moved" about in
  4763.  memory adds to its flexibility. Figure 2-5 shows a simple structure that
  4764.  might be used to represent data consisting of a series of test score
  4765.  samples. A structure could also be used to define the organization of the
  4766.  information stored and loaded by the FSTENV and FLDENV instructions.
  4767.  
  4768.  
  4769.  Figure 2-3.  Sample 80287 Constants
  4770.  
  4771.    ;  THE FOLLOWING ALL ALLOCATE THE CONSTANT: -126
  4772.    ;  NOTE TWO'S COMPLETE STORAGE OF NEGATIVE BINARY INTEGERS.
  4773.    ;
  4774.       EVEN                                  ; FORCE WORK ALIGNMENT
  4775.    WORD_INTEGER    DW  111111111000010B     ; BIT STRING
  4776.    SHORT_INTEGER   DD  OFFFFFF82H           ; HEX STRING MUST START
  4777.                                             ; WITH DIGIT
  4778.    LONG_INTEGER    DQ  -126                 ; ORDINARY DECIMAL
  4779.    SHORT_REAL      DD  -126.0               ; NOTE PRESENCE OF '.'
  4780.    LONG_REAL       DD  -1.26E2              ; "SCIENTIFIC"
  4781.    PACKED_DECIMAL  DT  -126                 ; ORDINARY DECIMAL INTEGER
  4782.  
  4783.    ;  IN THE FOLLOWING, SIGN AND EXPONENT IS 'C005'
  4784.    ;     SIGNIFICAND IS '7E00...00', 'R' INFORMS ASSEMBLER THAT
  4785.    ;     THE STRING REPRESENTS A REAL DATA TYPE.
  4786.    ;
  4787.    TEMP_REAL       DT  0C0057E00000000000000R   ; HEX STRING
  4788.  
  4789.  
  4790.  Figure 2-4.  Status Word RECORD Definition
  4791.  
  4792.  ;  RESERVE SPACE FOR STATUS WORD
  4793.  STATUS_WORD
  4794.  ;  LAY OUT STATUS WORD FIELDS
  4795.  STATUS RECORD
  4796.  &    BUSY:               1,
  4797.  &    COND_CODE 3:        1,
  4798.  &    STACK_TOP:          3,
  4799.  &    COND_CODE 2:        1,
  4800.  &    COND_CODE 1:        1,
  4801.  &    COND_CODE 0:        1,
  4802.  &    INT_REQ:            1,
  4803.  &    RESERVED:           1,
  4804.  &    P_FLAG:             1,
  4805.  &    U_FLAG:             1,
  4806.  &    O_FLAG:             1,
  4807.  &    Z_FLAG:             1,
  4808.  &    D_FLAG:             1,
  4809.  &    I_FLAG:             1,
  4810.  ;  POLL STATUS WORD UNTIL 80287 IS NOT BUSY
  4811.  POLL:   FNSTSW   STATUS_WORD
  4812.          TEST     STATUS_WORD, MASK_BUSY
  4813.          JNZ      POLL
  4814.  
  4815.  
  4816.  Figure 2-5.  Structure Definition
  4817.  
  4818.    SAMPLE        STRUC
  4819.  
  4820.       N_OBS          DD    ?  ; SHORT INTEGER
  4821.       MEAN           DQ    ?  ; LONG REAL
  4822.       MODE           DW    ?  ; WORD INTEGER
  4823.       STD_DEV        DQ    ?  ; LONG REAL
  4824.       ; ARRAY OF OBSERVATIONS -- WORD INTEGER
  4825.       TEST_SCORES    DW    1000 DUP (?)
  4826.    SAMPLE ENDS
  4827.  
  4828.  
  4829.  Addressing Modes
  4830.  80287 memory data can be accessed with any of the CPU's five memory
  4831.  addressing modes. This means that 80287 data types can be incorporated in
  4832.  data aggregates ranging from simple to complex according to the needs of the
  4833.  application. The addressing modes, and the ASM286 notation used to specify
  4834.  them in instructions, make the accessing of structures, arrays, arrays of
  4835.  structures, and other organizations direct and straightforward. Table 2-17
  4836.  gives several examples of 80287 instructions coded with operands that
  4837.  illustrate different addressing modes.
  4838.  
  4839.  
  4840.  Table 2-17. Addressing Mode Examples
  4841.  
  4842.  ┌─── Coding───────────────┐    Interpretation
  4843.  
  4844.  FIADD   ALPHA                  ALPHA is a simple scalar (mode is direct).
  4845.  
  4846.  FDIVR   ALPHA.BETA             BETA is a field in a structure that is
  4847.                                 "overlaid" on ALPHA (mode is direct).
  4848.  
  4849.  FMUL    QWORD PTR [BX]         BX contains the address of a long real
  4850.                                 variable (mode is register indirect).
  4851.  
  4852.  FSUB    ALPHA [SI]             ALPHA is an array and SI contains the
  4853.                                 offset of an array element from the start of
  4854.                                 the array (mode is indexed).
  4855.  
  4856.  FILD    [BP].BETA              BP contains the address of a structure on
  4857.                                 the CPU stack and BETA is a field in the
  4858.                                 structure (mode is based).
  4859.  
  4860.  FBLD    TBYTE PTR [BX] [DI]    BX contains the address of a packed
  4861.                                 decimal array and DI contains the offset of
  4862.                                 an array element (mode is based indexed).
  4863.  
  4864.  
  4865.  Comparative Programming Example
  4866.  Figures 2-6 and 2-7 show the PL/M-286 and ASM286 code for a simple 80287
  4867.  program, called ARRSUM. The program references an array (X$ARRAY), which
  4868.  contains 0-100 short real values; the integer variable N$OF$X indicates the
  4869.  number of array elements the program is to consider. ARRSUM steps through
  4870.  X$ARRAY accumulating three sums:
  4871.  
  4872.    ■  SUM$X, the sum of the array values
  4873.  
  4874.    ■  SUM$INDEXES, the sum of each array value times its index, where the
  4875.       index of the first element is 1, the second is 2, etc.
  4876.  
  4877.    ■  SUM$SQUARES, the sum of each array element squared
  4878.  
  4879.  (A true program, of course, would go beyond these steps to store and use
  4880.  the results of these calculations.) The control word is set with the
  4881.  recommended values: projective closure, round to nearest, 64-bit precision,
  4882.  interrupts enabled, and all exceptions masked invalid operation. It is
  4883.  assumed that an exception handler has been written to field the invalid
  4884.  operation, if it occurs, and that it is invoked by interrupt pointer 16.
  4885.  Either version of the program will run on an actual or an emulated 80287
  4886.  without altering the code shown.
  4887.  
  4888.  The PL/M-286 version of ARRSUM (figure 2-6) is very straightforward and
  4889.  illustrates how easily the 80287 can be used in this language. After
  4890.  declaring variables the program calls built-in procedures to initialize the
  4891.  processor (or its emulator) and to load to the control word. The program
  4892.  clears the sum variables and then steps through X$ARRAY with a DO-loop. The
  4893.  loop control takes into account PL/M-286's practice of considering the index
  4894.  of the first element of an array to be 0. In the computation of SUM$INDEXES,
  4895.  the built-in procedure FLOAT converts I+1 from integer to real because the
  4896.  language does not support "mixed mode" arithmetic. One of the strengths of
  4897.  the NPX, of course, is that it does support arithmetic on mixed data types
  4898.  (because all values are converted internally to the 80-bit temporary real
  4899.  format).
  4900.  
  4901.  The ASM286 version (figure 2-7) defines the external procedure INIT287,
  4902.  which makes the different initialization requirements of the processor and
  4903.  its emulator transparent to the source code. After defining the data and
  4904.  setting up the segment registers and stack pointer, the program calls
  4905.  INIT287 and loads the control word. The computation begins with the next
  4906.  three instructions, which clear three registers by loading (pushing) zeros
  4907.  onto the stack. As shown in figure 2-8, these registers remain at the
  4908.  bottom of the stack throughout the computation while temporary values are
  4909.  pushed on and popped off the stack above them.
  4910.  
  4911.  The program uses the CPU LOOP instruction to control its iteration through
  4912.  X_ARRAY; register CX, which LOOP automatically decrements, is loaded with
  4913.  N_OF_X, the number of array elements to be summed. Register SI is used to
  4914.  select (index) the array elements. The program steps through X_ARRAY from
  4915.  back to front, so SI is initialized to point at the element just beyond the
  4916.  first element to be processed. The ASM286 TYPE operator is used to determine
  4917.  the number of bytes in each array element. This permits  changing X_ARRAY to
  4918.  a long real array by simply changing its definition (DD to DQ) and
  4919.  reassembling.
  4920.  
  4921.  Figure 2-8 shows the effect of the instructions in the program loop on the
  4922.  NPX register stack. The figure assumes that the program is in its first
  4923.  iteration, that N_OF_X is 20, and that X_ARRAY(19) (the 20th element)
  4924.  contains the value 2.5. When the loop terminates, the three sums are left
  4925.  as the top stack elements so that the program ends by simply popping them
  4926.  into memory variables.
  4927.  
  4928.  
  4929.  Figure 2-6.  Sample PL/M-286 Program
  4930.  
  4931.  PL/M-286 COMPILER   ARRAYSUM
  4932.  
  4933.  SERIES-III PL/M-286 V 1.0 COMPILATION OF MODULE ARRAYSUM
  4934.  OBJECT MODULE PLACED IN :F6:D.OBJ
  4935.  COMPILER INVOLKED BY   PLM286.86 :F6:D.SRC XREF
  4936.  
  4937.              /******************************************
  4938.              *                                         *
  4939.              *     ARRAYSUM MOD                        *
  4940.              *                                         *
  4941.              ******************************************/
  4942.  
  4943.   1          array$sum:     do;
  4944.  
  4945.   2    1     declare (sum$x,sum$indexes,sum$squares) real;
  4946.   3    1     declare x$array(100) real;
  4947.   4    1     declare (n$of$x,i) integer;
  4948.   5    1     declare control$287 literally '033eh';
  4949.  
  4950.              /* Assume x$array and n$of$x are initalized */
  4951.  
  4952.              /* Prepare the 80287 of its emulator */
  4953.   6    1     call init$real$math$unit;
  4954.   7    1     call set$real$mode(control$287);
  4955.  
  4956.              /* Clear sums */
  4957.   8    1     sum$x, sum$indexes, (sum$squares - 0) 0;
  4958.  
  4959.              /* Loop through array, accumulating sums */
  4960.   9    1     do i = 0 to n$of$x-1;
  4961.  10    2       sum$x = sum$x = x$array(i);
  4962.  11    2       sum$indexes = sum$indexes +
  4963.                      (x$array(i) * float(i±1));
  4964.  12    2       sum$squares = sum$squares + (x$array(i)*x$array(i));
  4965.  13    2     end;
  4966.  
  4967.              /* etc. */
  4968.  
  4969.  14    1     end array$sum;
  4970.  
  4971.  PL/M-286 COMPILER     ARRAYSUM
  4972.                        CROSS-REFERENCE LISTING
  4973.  
  4974.  DEFN   ADDR   SIZE  NAME,ATTRIBUTES, AND REFERENCES
  4975.  
  4976.      1  0006H   117  ARRAYSUM             PROCEDURE STACK=002H
  4977.      5               CONTROL287           LITERALLY '033eh'    7
  4978.                      FLOAT                BUILTIN             11
  4979.      4  019EH     2  I                    INTEGER              9*    9    10
  4980.                      INITREALMATHUNIT     BUILTIN              6
  4981.      4  019CH     2  NDFX                 INTEGER              9
  4982.                      SETREALMODE          BUILTIN              7
  4983.      2  0004H     4  SUMINDEXES           REAL          8*    11    11*
  4984.      2  0008H     4  SUMSQAURES           REAL          8*    12    12*
  4985.      2  0000H     4  SUMX                 REAL          8*    10    10*
  4986.      3  000CH   400  XARRAY               REAL ARRAY(100)            10    11
  4987.  
  4988.  MODULE INFORMATION
  4989.        CODE AREA SIZE     = 0077H    119D
  4990.        CONSTANT AREA SIZE = 0004H      4D
  4991.        VARIABLE AREA SIZE = 01A0H    416D
  4992.        MAXIMUM STACK SIZE = 0002H      2D
  4993.        33 LINES READ
  4994.        0 PROGRAM WARNINGS
  4995.        0 PROGRAM ERRORS
  4996.  
  4997.  DICTIONARY SUMMARY
  4998.        96KB MEMORY AVILABLE
  4999.        3KB MEMORY USED  (3%)
  5000.        0KB DISK SPACE USED
  5001.  
  5002.  END OF PL/M-286 COMPILATION
  5003.  
  5004.  
  5005.  Figure 2-7.  Sample ASM286 Program
  5006.  
  5007.  iAPX286 MACRO ASSEMBLER     EXAMPLE ASM286_PROGRAM
  5008.  
  5009.  SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE EXAMPLE_ASM286_PRO
  5010.  OBJECT MODULE PLACED IN :F6:287EXP.OBJ
  5011.  ASSEMBLER INVOKED BY   ASM286 B6 :F6:287EXP.SRC XREF
  5012.  
  5013.  LOC  OBJ              LINE     SOURCE
  5014.  
  5015.                           1                 name    example_ASM286_program
  5016.                           2     ; Define intitialization routine
  5017.                           3                 extrn       init287:far
  5018.                           4
  5019.                           5     ;  Allocate space for date
  5020.  ----                     6     data        segment rw public
  5021.  0000 3E03                7     control_287     dw      033eh
  5022.  0002 ????                8     n_of_x          dw      ?
  5023.  0004 (000                9     x_array         dd      100 dwp (?)
  5024.       ????????
  5025.       )
  5026.  0194 ????????           10     sum_squares     dd      ?
  5027.  019B ????????           11     sum_indexes     dd      ?
  5028.  019C ????????           12     sum_x           dd      ?
  5029.  ----                    13     data     ends
  5030.                          14
  5031.                          15     ; Allocate CPU stack space
  5032.  ----                    16     stack       stackseg 400
  5033.                          17
  5034.                          18     ; Begin code
  5035.  ----                    19     code        segment or public
  5036.                          20                 assumes ds: data, ss: stack, es: n
  5037.  0000                    21     start:
  5038.  0000 BB----       R     22                 mov     ax,data
  5039.  0003 BED8               23                 mov     ds,ax
  5040.  0005 B8----       R     24                 mov     ax,stack
  5041.  0008 BED0               25                 mov     ss,ax
  5042.  000A BCFEFF       R     26                 mov     sp,stackstart stack
  5043.                          27
  5044.                          28     ; Assume x_array and n_of_x are initialized
  5045.                          29     ;           this pprogram zeroes n_of_x
  5046.                          30
  5047.                          31     ; Prepare the 80287 or its emulator
  5048.  000D 9A0000----   E     32                 call    init287
  5049.  0012 D92E0000     R     33                 fldcw   control_287
  5050.                          34
  5051.                          35     ; Clear three registers to hold running sums
  5052.  0016 D9EE               36                 fldz
  5053.  0018 D9EE               37                 fldz
  5054.  001A D9EE               38                 fldz
  5055.                          39
  5056.                          40     ; Setup CX as loop counter and
  5057.                          41     ; SI as index to x_array
  5058.  001C 8B0E0200     R     42                 mov     cx,n_of_x
  5059.  0020 F7E9               43                 imul    cx
  5060.  0022 8BF0               44                 mov     si,ax
  5061.                          45
  5062.                          46     ; SI now contains index of last element + 1
  5063.                          47     ; Loop thru x_array, accumulating sums
  5064.  0024                    48     sum_next:
  5065.  0024 8E3304             49                 sub     si,type x_array ;backup on
  5066.  0027 D9840400     R     50                 fld     x_array[si]     ;push it o
  5067.  002B DCC3               51                 fadd    st(3),st        ;add into
  5068.  002D D9C0               52                 fld     st              ;duplicate
  5069.  002F DCC8               53                 fmul    st,st           ;square it
  5070.  0031 DEC2               54                 faddp   st(2),st        ;add into
  5071.                          55                                         ;  and dis
  5072.  0033 FF0E0200     R     56                 dec     n_of_x          ;reduce in
  5073.  0037 E2EB               57                 loop    sum_next                ;c
  5074.                          58
  5075.                          59     ; Pop running sums into memory
  5076.  0039                    60     pop_results:
  5077.  0039 D91E9401     R     61                 fstp    sum_squares
  5078.  003D D91E9801     R     62                 fstp    sum_indexes
  5079.  0041 D91E9C01     R     63                 fstp    sum_x
  5080.  0045 9B                 64                 fwait
  5081.                          65
  5082.                          66     ;
  5083.                          67     ; Etc.
  5084.                          68     ;
  5085.  ----                    69     code        ends
  5086.                          70                 end     start
  5087.  
  5088.  iAPX286 MACRO ASSEMBLER     EXAMPLE_ASM286_PROGRAM
  5089.  XREF SYMBOL TABLE LISTING
  5090.  
  5091.  NAME          TYPE      VALUE   ATTRIBUTES, XREFS
  5092.  
  5093.  CODE          SEGMENT           SIZE=0046H ER PUBLIC  19# 69
  5094.  CONTROL_287   V WORD    0000H   DATA  7# 33
  5095.  DATA          SEGMENT           SIZE=01A0H RW PUBLIC   6# 13 20 22
  5096.  INIT287       L FAR     0000H   EXTR   3# 32
  5097.  N_OF_X        V WORD    0002H   DATA   8# 42 56
  5098.  POP_RESULTS   L NEAR    0039H   CODE   60#
  5099.  STACK         STACK             SIZE=0190H RW PUBLIC   16# 20 24 26
  5100.  START         L NEAR    0000H   CODE   21# 70
  5101.  SUM_INDEXES   V DWORD   0198H   DATA   11# 62
  5102.  SUM_NEXT      L NEAR    0024H   CODE   48# 57
  5103.  SUM_SQUARES   V DWORD   0194H   DATA   10# 61
  5104.  SUM_X         V DWORD   019CH   DATA   12# 63
  5105.  X_ARAY        V DWORD   0004H   (100) DATA   9# 49 50
  5106.  
  5107.  END OF SYMBOL TABLE LISTING
  5108.  
  5109.  ASSEMBLY COMPLETE,                  NO ERRORS
  5110.  
  5111.  
  5112.  Figure 2-8.  Instructions and Register Stack
  5113.  
  5114.            FLDZ,FLDZ,FLDZ                    FDL X_ARRAY[SI]
  5115.               ╔═════╗──────────────────────────╔═════╗
  5116.          ST(0)║ 0.0 ║ SUM_SQUARES          ST(0)║ 2.5 ║ X_ARRAY(19)
  5117.               ╟─────╢                           ╟─────╢
  5118.          ST(1)║ 0.0 ║ SUM_INDEXES          ST(1)║     ║ SUM_SQUARES
  5119.               ╟─────╢                           ╟─────╢
  5120.          ST(2)║ 0.0 ║ SUM_X                ST(2)║ 0.0 ║ SUM_INDEXES
  5121.               ╚═════╝                           ╟─────╢
  5122.                                            ST(3)║ 0.0 ║ SUM_X
  5123.                        ┌────────────────────────╚═════╝
  5124.                        │
  5125.           FADD ST(3),ST│                         FLD ST
  5126.               ╔═════╗─┘───────────────────────╔═════╗
  5127.          ST(0)║ 2.5 ║ X_ARRAY(19)          ST(0)║ 2.5 ║ X_ARRAY(19)
  5128.               ╟─────╢                           ╟─────╢
  5129.          ST(1)║ 0.0 ║ SUM_SQUARES          ST(1)║ 2.5 ║ X_ARRAY(19)
  5130.               ╟─────╢                           ╟─────╢
  5131.          ST(2)║ 0.0 ║ SUM_INDEXES          ST(2)║ 0.0 ║ SUM_SQUARES
  5132.               ╟─────╢                           ╟─────╢
  5133.          ST(3)║ 2.5 ║ SUM_X                ST(3)║ 0.0 ║ SUM_INDEXES
  5134.               ╚═════╝                           ╟─────╢
  5135.                                            ST(4)║ 2.5 ║ SUM_X
  5136.                        ┌────────────────────────╚═════╝
  5137.                        │
  5138.              FMUL ST,ST│                     FADDP ST(2),ST
  5139.               ╔═════╗─┘───────────────────────╔═════╗
  5140.          ST(0)║ 6.25║ X_ARRAY(19)^(2)      ST(0)║ 2.5 ║ X_ARRAY(19)
  5141.               ╟─────╢                           ╟─────╢
  5142.          ST(1)║ 2.5 ║ X_ARRAY(19)          ST(1)║ 6.25║ SUM_SQUARES
  5143.               ╟─────╢                           ╟─────╢
  5144.          ST(2)║ 0.0 ║ SUM_SQUARES          ST(2)║ 0.0 ║ SUM_INDEXES
  5145.               ╟─────╢                           ╟─────╢
  5146.          ST(3)║ 0.0 ║ SUM_INDEXES          ST(3)║ 2.5 ║ SUM_X
  5147.               ╟─────╢               ┌───────────╚═════╝
  5148.          ST(4)║ 2.5 ║ SUM_X         │
  5149.               ╚═════╝               │
  5150.                         ┌───────────┘
  5151.             FIMUL N_OF_X│                     FADDP ST(2),ST
  5152.               ╔═════╗──┘──────────────────────╔═════╗
  5153.          ST(0)║ 50.0║ X_ARRAY(19)*20       ST(0)║ 6.25║ SUM_SQUARES
  5154.               ╟─────╢                           ╟─────╢
  5155.          ST(1)║ 6.25║ SUM_SQUARES          ST(1)║ 50.0║ SUM_INDEXES
  5156.               ╟─────╢                           ╟─────╢
  5157.          ST(2)║ 0.0 ║ SUM_INDEXES          ST(2)║ 2.5 ║ SUM_X
  5158.               ╟─────╢                           ╚═════╝
  5159.          ST(3)║ 2.5 ║ SUM_X
  5160.               ╚═════╝
  5161.  
  5162.  
  5163.  80287 Emulation
  5164.  The programming of applications to execute on both 80286 and 80287 is made
  5165.  much easier by the existence of an 80287 emulator for 80286 systems. The
  5166.  Intel E80287 emulator offers a complete software counterpart to the 80287
  5167.  hardware; NPX instructions can be simply emulated in software rather than
  5168.  being executed in hardware. With software emulation, the distinction
  5169.  between 80286 and 80287 systems is reduced to a simple performance
  5170.  differential (see Table 1-2 for a performance comparison between an actual
  5171.  80287 and an emulator 80287).  Identical numeric programs will simply
  5172.  execute more slowly on 80286 systems (using software emulation of NPX
  5173.  instructions) than on executing NPX instructions directly.
  5174.  
  5175.  When incorporated into the systems software, the emulation of NPX
  5176.  instructions on the 80286 systems is completely transparent to the
  5177.  programmer. Applications software needs no special libraries, linking, or
  5178.  other activity to allow it to run on an 80286 with 80287 emulation.
  5179.  
  5180.  To the applications programmer, the development of programs for 80286
  5181.  systems is the same whether the 80287 NPX hardware is available or not. The
  5182.  full 80287 instruction set is available for use, with NPX instructions being
  5183.  either emulated or executed directly. Applications programmers need not be
  5184.  concerned with the hardware configuration of the computer systems on which
  5185.  their applications will eventually run.
  5186.  
  5187.  For systems programmers, details relating to 80287 emulators are described
  5188.  in a later section of this supplement. An E80287 software emulator for 80286
  5189.  systems is contained in the iMDX 364 8086 Software Toolbox, available from
  5190.  Intel and described in the 8086 Software Toolbox Manual.
  5191.  
  5192.  
  5193.  Concurrent Processing with the 80287
  5194.  Because the 80286 CPU and the 80287 NPX have separate execution units, it
  5195.  is possible for the NPX to execute numeric instructions in parallel with
  5196.  instructions executed by the CPU. This simultaneous execution of different
  5197.  instructions is called concurrency.
  5198.  
  5199.  No special programming techniques are required to gain the advantages of
  5200.  concurrent execution; numeric instructions for the NPX are simply placed in
  5201.  line with the instructions for the CPU. CPU and numeric instructions are
  5202.  initiated in the same order as they are encountered by the CPU in its
  5203.  instruction stream. However, because numeric operations performed by the NPX
  5204.  generally require more time than operations performed by the CPU, the CPU
  5205.  can often execute several of its instructions before the NPX completes a
  5206.  numeric instruction previously initiated.
  5207.  
  5208.  This concurrency offers obvious advantages in terms of execution
  5209.  performance, but concurrency also imposes several rules that must be
  5210.  observed in order to assure proper synchronization of the 80286 CPU and
  5211.  80287 NPX.
  5212.  
  5213.  All Intel high-level languages automatically provide for and manage
  5214.  concurrency in the NPX. Assembly-language programmers, however, must
  5215.  understand and manage some areas of concurrency in exchange for the
  5216.  flexibility and performance of programming in assembly language. This
  5217.  section is for the assembly-language programmer or well-informed
  5218.  high-level-language programmer.
  5219.  
  5220.  
  5221.  Managing Concurrency
  5222.  Concurrent execution of the host and 80287 is easy to establish and
  5223.  maintain. The activities of numeric programs can be split into two major
  5224.  areas: program control and arithmetic. The program control part performs
  5225.  activities such as deciding what functions to perform, calculating
  5226.  addresses of numeric operands, and loop control. The arithmetic part simply
  5227.  adds, subtracts, multiplies, and performs other operations on the numeric
  5228.  operands. The NPX and host are designed to handle these two parts
  5229.  separately and efficiently.
  5230.  
  5231.  Managing concurrency is necessary because both the arithmetic and control
  5232.  areas must converge to a well-defined state before starting another numeric
  5233.  operation. A well-defined state means all previous arithmetic and control
  5234.  operations are complete and valid.
  5235.  
  5236.  Normally, the host waits for the 80287 to finish the current numeric
  5237.  operation before starting another. This waiting is called synchronization.
  5238.  
  5239.  Managing concurrent execution of the 80287 involves three types of
  5240.  synchronization:
  5241.  
  5242.    1.  Instruction synchronization
  5243.    2.  Data synchronization
  5244.    3.  Error synchronization
  5245.  
  5246.  For programmers in higher-level languages, all three types of
  5247.  synchronization are automatically provided by the appropriate compiler. For
  5248.  assembly-language programmers, instruction synchronization is guaranteed by
  5249.  the NPX interface, but data and error synchronization are the
  5250.  responsibility of the assembly-language programmer.
  5251.  
  5252.  
  5253.  Instruction Synchronization
  5254.  Instruction synchronization is required because the 80287 can perform only
  5255.  one numeric operation at a time. Before any numeric operation is started,
  5256.  the 80287 must have completed all activity from its previous instruction.
  5257.  
  5258.  Instruction synchronization is guaranteed for most ESC instructions because
  5259.  the 80286 automatically checks the BUSY status line from the 80287
  5260.  before commencing execution of most ESC instructions. No explicit WAIT
  5261.  instructions are necessary to ensure proper instruction synchronization.
  5262.  
  5263.  
  5264.  Data Synchronization
  5265.  Data synchronization addresses the issue of both the CPU and the NPX
  5266.  referencing the same memory values within a given block of code.
  5267.  Synchronization ensures that these two processors access the memory operands
  5268.  in the proper sequence, just as they would be accessed by a single
  5269.  processor with no concurrency. Data synchronization is not a concern when
  5270.  the CPU and NPX are using different memory operands during the course of one
  5271.  numeric instruction.
  5272.  
  5273.  The two cases where data synchronization might be a concern are
  5274.  
  5275.    1.  The 80286 CPU reads or alters a memory operand first, then invokes
  5276.        the 80287 to load or alter the same operand.
  5277.  
  5278.    2.  The 80287 is invoked to load or alter a memory operand, after which
  5279.        the 80286 CPU reads or alters the same location.
  5280.  
  5281.  Due to the instruction synchronization of the NPX interface, data
  5282.  synchronization is automatically provided for the first case──the 80286 will
  5283.  always complete its operation before invoking the 80287.
  5284.  
  5285.  For the second case, data synchronization is not always automatic. In
  5286.  general, there is no guarantee that the 80287 will have finished its
  5287.  processing and accessed the memory operand before the 80286 accesses the
  5288.  same location.
  5289.  
  5290.  Figure 2-9 shows examples of the two possible cases of the CPU and NPX
  5291.  sharing a memory value. In the examples of the first case, the CPU will
  5292.  finish with the operand before the 80287 can reference it. The NPX interface
  5293.  guarantees this. In the examples of the second case, the CPU must wait for
  5294.  the 80287 to finish with the memory operand before proceeding to reuse it.
  5295.  The FWAIT instructions shown in these examples are required in order to
  5296.  ensure this data synchronization.
  5297.  
  5298.  There are several NPX control instructions where automatic data
  5299.  synchronization is provided; however, the FSTSW/FNSTSW, FSTCW/FNSTCW, FLDCW,
  5300.  FRSTOR, and FLDENV instructions are all guaranteed to finish their execution
  5301.  before the CPU can read or alter the referenced memory locations.
  5302.  
  5303.  The 80287 provides data synchronization for these instructions by making a
  5304.  request on the Processor Extension Data Channel before the CPU executes its
  5305.  next instruction. Since the NPX data transfers occur before the CPU regains
  5306.  control of the local bus, the CPU cannot change a memory value before the
  5307.  NPX has had a chance to reference it. In the case of the FSTSW AX
  5308.  instruction, the 80286 AX register is explicitly updated before the CPU
  5309.  continues execution of the next instruction.
  5310.  
  5311.  For the numeric instructions not listed above, the assembly-language
  5312.  programmer must remain aware of synchronization and recognize cases
  5313.  requiring explicit data synchronization. Data synchronization can be
  5314.  provided either by programming an explicit FWAIT instruction, or by
  5315.  initiating a subsequent numeric instruction before accessing the operands or
  5316.  results of a previous instruction. After the subsequent numeric instruction
  5317.  has started execution, all memory references in earlier numeric
  5318.  instructions are complete. Reaching the next host instruction after the
  5319.  synchronizing numeric instruction indicates that previous numeric operands
  5320.  in memory are available.
  5321.  
  5322.  The data-synchronization function of any FWAIT or numeric instruction must
  5323.  be well-documented, as shown in figure 2-10. Otherwise, a change to the
  5324.  program at a later time may remove the synchronizing numeric instruction and
  5325.  cause program failure.
  5326.  
  5327.  High-level languages automatically establish data synchronization and
  5328.  manage it, but there may be applications where a high-level language may not
  5329.  be appropriate.
  5330.  
  5331.  For assembly-language programmers, automatic data synchronization can be
  5332.  obtained using the assembler, although concurrency of execution is lost as a
  5333.  result. To perform automatic data synchronization, the assembler can be
  5334.  changed to always place a WAIT instruction after the ESCAPE instruction.
  5335.  Figure 2-11 shows an example of how to change the ASM286 Code Macro for the
  5336.  FIST instruction to automatically place a WAIT instruction after the ESCAPE
  5337.  instruction. This Code Macro is included in the ASM286 source module. The
  5338.  price paid for this automatic data synchronization is the lack of any
  5339.  possible concurrency between the CPU and NPX.
  5340.  
  5341.  
  5342.  Figure 2-9.  Synchronizing References to Shared Data
  5343.  
  5344.    Case 1:                Case 2:
  5345.         MOV     I,  1          FILD      I
  5346.         FILD    I              FWAIT
  5347.                                MOV       I, 5
  5348.  
  5349.         MOV     AX, I          FISTP     I
  5350.         FISTP   I              FWAIT
  5351.                                MOV       AX, I
  5352.  
  5353.  
  5354.  Figure 2-10.  Documenting Data Synchronization
  5355.  
  5356.    FISTP   I
  5357.    FMUL                ; I is updated before FMUL is executed
  5358.    MOV     AX, I       ; I is now safe to use
  5359.  
  5360.  
  5361.  Figure 2-11.  Nonconcurrent FIST Instruction Code Macro
  5362.  
  5363.    ;
  5364.    ; This is an ASM286 code macro to redefine the FIST
  5365.    ; instruction to prevent any concurrency
  5366.    ; while the instruction runs. A wait
  5367.    ; instruction is placed immediately after the
  5368.    ; escape to ensure the store is done
  5369.    ; before the program may continue.
  5370.    CodeMacro FIST memop: Mw
  5371.    RfixM 111B, memop
  5372.    ModRM 010B, memop
  5373.    RWfix
  5374.    EndM
  5375.  
  5376.  
  5377.  Error Synchronization
  5378.  Almost any numeric instruction can, under the wrong circumstances, produce
  5379.  a numeric error. Concurrent execution of the CPU and NPX requires
  5380.  synchronization for these errors just as it does for data references and
  5381.  numeric instructions. In fact, the synchronization required for data and
  5382.  instructions automatically provides error synchronization.
  5383.  
  5384.  However, incorrect data or instruction synchronization may not be
  5385.  discovered until a numeric error occurs. A further complication is that a
  5386.  programmer may not expect his numeric program to cause numeric errors, but
  5387.  in some systems, they may regularly happen. To better understand these
  5388.  points, let's look at what can happen when the NPX detects an error.
  5389.  
  5390.  The NPX can perform one of two things when a numeric exception occurs:
  5391.  
  5392.    ■  The NPX can provide a default fix-up for selected numeric errors.
  5393.       Programs can mask individual error types to indicate that the NPX
  5394.       should generate a safe, reasonable result whenever that error occurs.
  5395.       The default error fix-up activity is treated by the NPX as part of the
  5396.       instruction causing the error; no external indication of the error is
  5397.       given. When errors are detected, a flag is set in the numeric status
  5398.       register, but no information regarding where or when is available. If
  5399.       the NPX performs its default action for all errors, then error
  5400.       synchronization is never exercised. This is no reason to ignore error
  5401.       synchronization, however.
  5402.  
  5403.    ■  As an alternative to the NPX default fix-up of numeric errors, the
  5404.       80286 CPU can be notified whenever an exception occurs. The CPU can
  5405.       then implement any sort of recovery procedures desired, for any numeric
  5406.       error detectable by the NPX. When a numeric error is unmasked and the
  5407.       error occurs, the NPX stops further execution of the numeric
  5408.       instruction and signals this event to the CPU. On the next occurrence
  5409.       of an ESC or WAIT instruction, the CPU traps to a software exception
  5410.       handler. Some ESC instructions do not check for errors. These are the
  5411.       nonwaited forms FNINIT, FNSTENV, FNSAVE, FNSTSW, FNSTCW, and FNCLEX.
  5412.  
  5413.  When the NPX signals an unmasked exception condition, it is requesting
  5414.  help. The fact that the error was unmasked indicates that further numeric
  5415.  program execution under the arithmetic and programming rules of the NPX is
  5416.  unreasonable.
  5417.  
  5418.  If concurrent execution is allowed, the state of the CPU when it recognizes
  5419.  the exception is undefined. The CPU may have changed many of its internal
  5420.  registers and be executing a totally different program by the time the
  5421.  exception occurs. To handle this situation, the NPX has special registers
  5422.  updated at the start of each numeric instruction to describe the state of
  5423.  the numeric program when the failed instruction was attempted.
  5424.  
  5425.  Error synchronization ensures that the NPX is in a well-defined state after
  5426.  an unmasked numeric error occurs. Without a well-defined state, it would be
  5427.  impossible for exception recovery routines to figure out why the numeric
  5428.  error occurred, or to recover successfully from the error.
  5429.  
  5430.  
  5431.  Incorrect Error Synchronization
  5432.  An example of how some instructions written without error synchronization
  5433.  will work initially, but fail when moved into a new environment is shown in
  5434.  figure 2-12.
  5435.  
  5436.  In figure 2-12, three instructions are shown to load an integer, calculate
  5437.  its square root, then increment the integer. The NPX interface and
  5438.  synchronous execution of the NPX emulator will allow this program to execute
  5439.  correctly when no errors occur on the FILD instruction.
  5440.  
  5441.  This situation changes if the 80287 numeric register stack is extended to
  5442.  memory. To extend the NPX stack to memory, the invalid error is unmasked. A
  5443.  push to a full register or pop from an empty register will cause an invalid
  5444.  error. The recovery routine for the error must recognize this situation,
  5445.  fix up the stack, then perform the original operation.
  5446.  
  5447.  The recovery routine will not work correctly in the first example shown in
  5448.  the figure. The problem is that the value of COUNT is incremented before the
  5449.  NPX can signal the exception to the CPU. Because COUNT is incremented before
  5450.  the exception handler is invoked, the recovery routine will load an
  5451.  incorrect value of COUNT, causing the program to fail or behave unreliably.
  5452.  
  5453.  
  5454.  Figure 2-12. Error Synchronization Examples
  5455.  
  5456.                    INCORRECT ERROR SYNCHRONIZATION
  5457.  
  5458.  FILD   COUNT   ; NPX instruction
  5459.  INC    COUNT   ; CPU instruction alters operand
  5460.  FSQRT  COUNT   ; subsequent NPX instruction -- error from
  5461.                 ;    previous NPX instruction detected here
  5462.  
  5463.                      PROPER ERROR SYNCHRONIZATION
  5464.  
  5465.  FILD   COUNT   ; NPX instruction
  5466.  FSQRT  COUNT   ; subsequent NPX instruction - error from
  5467.                 ;    previous NPX instruction detected here
  5468.  INC    COUNT   ; CPU instruction alters operand
  5469.  
  5470.  
  5471.  Proper Error Synchronization
  5472.  Error Synchronization relies on the WAIT instructions required by
  5473.  instruction and data synchronization and the BUSY and ERROR signals of
  5474.  the 80287. When an unmasked error occurs in the 80287, it asserts the
  5475.  ERROR signal, signalling to the CPU that a numeric error has occurred.
  5476.  The next time the CPU encounters an error-checking ESC or WAIT instruction,
  5477.  the CPU acknowledges the ERROR signal by trapping automatically to
  5478.  Interrupt #16, the Processor Extension Error vector. If the following ESC
  5479.  or WAIT instruction is properly placed, the CPU will not yet have disturbed
  5480.  any information vital to recovery from the error.
  5481.  
  5482.  
  5483.  Chapter 3  System-Level Numeric Programming
  5484.  
  5485.  ───────────────────────────────────────────────────────────────────────────
  5486.  
  5487.  System programming for 80287 systems requires a more detailed understanding
  5488.  of the 80287 NPX than does application programming. Such things as
  5489.  emulation, initialization, exception handling, and data and error
  5490.  synchronization are all the responsibility of the systems programmer. These
  5491.  topics are covered in detail in the sections that follow.
  5492.  
  5493.  
  5494.  80287 Architecture
  5495.  On a software level, the 80287 NPX appears as an extension of the 80286
  5496.  CPU. On the hardware level, however, the mechanisms by which the 80286 and
  5497.  80287 interact are a bit more complex. This section describes how the 80287
  5498.  NPX and 80286 CPU interact and points out features of this interaction that
  5499.  are of interest to systems programmers.
  5500.  
  5501.  
  5502.  Processor Extension Data Channel
  5503.  All transfers of operands between the 80287 and system memory are performed
  5504.  by the 80286's internal Processor Extension Data Channel. This independent,
  5505.  DMA-like data channel permits all operand transfers of the 80287 to come
  5506.  under the supervision of the 80286 memory-management and protection
  5507.  mechanisms. The operation of this data channel is completely transparent to
  5508.  software.
  5509.  
  5510.  Because the 80286 actually performs all transfers between the 80287 and
  5511.  memory, no additional bus drivers, controllers, or other components are
  5512.  necessary to interface the 80287 NPX to the local bus. Any memory accessible
  5513.  to the 80286 CPU is accessible by the 80287. The Processor Extension Data
  5514.  Channel is described in more detail in Chapter Six of the 80286 Hardware
  5515.  Reference Manual.
  5516.  
  5517.  
  5518.  Real-Address Mode and Protected Virtual-Address Mode
  5519.  Like the 80286 CPU, the 80287 NPX can operate in both Real-Address mode and
  5520.  in Protected mode. Following a hardware RESET, the 80287 is initially
  5521.  activated in Real-Address mode. A single, privileged instruction (FSETPM) is
  5522.  necessary to set the 80287 into Protected mode.
  5523.  
  5524.  As an extension to the 80286 CPU, the 80287 can access any memory location
  5525.  accessible by the task currently executing on the 80286. When operating in
  5526.  Protected mode, all memory references by the 80287 are automatically
  5527.  verified by the 80286's memory management and protection mechanisms as for
  5528.  any other memory references by the currently-executing task. Protection
  5529.  violations associated with NPX instructions automatically cause the 80286 to
  5530.  trap to an appropriate exception handler.
  5531.  
  5532.  To the programmer, these two 80287 operating modes differ only in the
  5533.  manner in which the NPX instruction and data pointers are represented in
  5534.  memory following an FSAVE or FSTENV instruction. When the 80287 operates in
  5535.  Protected mode, its NPX instruction and data pointers are each represented
  5536.  in memory as a 16-bit segment selector and a 16-bit offset. When the 80287
  5537.  operates in Real-Address mode, these same instruction and data pointers are
  5538.  represented simply as the 20-bit physical addresses of the operands in
  5539.  question (see figure 1-7 in Chapter One).
  5540.  
  5541.  
  5542.  Dedicated and Reserved I/O Locations
  5543.  The 80287 NPX does not require that any memory addresses be set aside for
  5544.  special purposes. The 80287 does make use of I/O port addresses in the range
  5545.  00F8H through 00FFH, although these I/O operations are completely
  5546.  transparent to the 80286 software. 80286 programs must not reference these
  5547.  reserved I/O addresses directly.
  5548.  
  5549.  To prevent any accidental misuse or other tampering with numeric
  5550.  instructions in the 80287, the 80286's I/O Privilege Level (IOPL) should be
  5551.  used in multiuser reprogrammable environments to restrict application
  5552.  program access to the I/O address space and so guarantee the integrity of
  5553.  80287 computations. Chapter Eight of the 80286 Operating System Writer's
  5554.  Guide contains more details regarding the use of the I/O Privilege Level.
  5555.  
  5556.  
  5557.  Processor Initialization and Control
  5558.  One of the principal responsibilities of systems software is the
  5559.  initialization, monitoring, and control of the hardware and software
  5560.  resources of the system, including the 80287 NPX. In this section, issues
  5561.  related to system initialization and control are described, including
  5562.  recognition of the NPX, emulation of the 80287 NPX in software if the
  5563.  hardware is not available, and the handling of exceptions that may occur
  5564.  during the execution of the 80287.
  5565.  
  5566.  
  5567.  System Initialization
  5568.  During initialization of an 80286 system, systems software must
  5569.  
  5570.    ■  Recognize the presence or absence of the NPX
  5571.  
  5572.    ■  Set flags in the 80286 MSW to reflect the state of the numeric
  5573.       environment
  5574.  
  5575.  If an 80287 NPX is present in the system, the NPX must be
  5576.  
  5577.    ■  Initialized
  5578.  
  5579.    ■  Switched into Protected mode (if desired)
  5580.  
  5581.  All of these activities can be quickly and easily performed as part of the
  5582.  overall system initialization.
  5583.  
  5584.  
  5585.  Recognizing the 80287 NPX
  5586.  Figure 3-1 shows an example of a recognition routine that determines
  5587.  whether an NPX is present, and distinguishes between the 80387 and the
  5588.  8087/80287. This routine can be executed on any 80386, 80286, or 8086
  5589.  hardware configuration that has an NPX socket.
  5590.  
  5591.  The example guards against the possibility of accidentally reading an
  5592.  expected value from a floating data bus when no NPX is present. Data read
  5593.  from a floating bus is undefined. By expecting to read a specific bit
  5594.  pattern from the NPX, the routine protects itself from the indeterminate
  5595.  state of the bus. The example also avoids depending on any values in
  5596.  reserved bits, thereby maintaining compatibility with future numerics
  5597.  coprocessors.
  5598.  
  5599.  
  5600.  Figure 3-1.  Software Routine to Recognize the 80287
  5601.  
  5602.  ;  The following algorithm detects the presence of the 8087 as well as the
  5603.  ;  80287 in a system.  This will make it easier for ISVs to port their 8086-8
  5604.  ;  software to 286-287 systems.
  5605.  ;
  5606.              cc_cr               equ     0DH     ;  carriage return
  5607.              cc_lf               equ     0AH     ;  line feed
  5608.  
  5609.  assume      cz:code, ds:data
  5610.  ;
  5611.  code        segment             public
  5612.  start:
  5613.              mov     ax,data                 ;  set data segment
  5614.              mov     ds,ax
  5615.  ;
  5616.  ;  Test if 8087 is present in PC or PC/XT, or 80287 is in PC/AT
  5617.  ;
  5618.              fninit                          ;  initialize coprocessor
  5619.              xor     ah,ah                   ;  zero ah register and memory by
  5620.              mov     byte ptr control + 1,ah
  5621.              fnstcw  control                 ;  store coprocessor's control wo
  5622.                                              ;  memory
  5623.              mov     ah,byte ptr control+1
  5624.              cmp     ah,03h                  ;  upper byte of control work wil
  5625.                                              ;  03 if 8087 or 80287 coprocesso
  5626.                                              ;  is present
  5627.              jne     no_coproc
  5628.  ;
  5629.  coproc:
  5630.              mov     ah,09h                  ;  print string-coprocessor prese
  5631.              mov     dx,offset msg_yes
  5632.              int     21h
  5633.              jmp     done
  5634.  
  5635.  ;
  5636.  no_coproc:
  5637.              mov     ah,09h                  ; print string-coprocessor not
  5638.                                              ; present
  5639.              mov     dx,offset msg_no
  5640.              int     21h
  5641.  ;
  5642.  done:
  5643.              mov     ah,4CH                  ; terminate program
  5644.              int     21h
  5645.  code        ends
  5646.  
  5647.  data        segment         public
  5648.  control     dw              00
  5649.  msg_yes     db      cc_cr,cc_lf,
  5650.              db      'System has an 8087 or 80287',cc_cr, cc_lf, '$'
  5651.  msg_no      db      cc_cr,cc_lf,
  5652.              db      'System does not have an 8087 or 80287',cc_cr, cc_lf,
  5653.                       '$'
  5654.  data        ends
  5655.              end     start                   ; start is the entry point
  5656.  
  5657.  
  5658.  Configuring the Numerics Environment
  5659.  Once the 80286 CPU has determined the presence or absence of the 80287 NPX,
  5660.  the 80286 must set either the MP or the EM bit in its own machine status
  5661.  word accordingly. The initialization routine can either
  5662.  
  5663.    ■  Set the MP bit in the 80286 MSW to allow numeric instructions to be
  5664.       executed directly by the 80287 NPX component
  5665.  
  5666.    ■  Set the EM bit in the 80286 MSW to permit software emulation of the
  5667.       80287 numeric instructions
  5668.  
  5669.  The Math Present (MP) flag of the 80286 machine status word indicates to
  5670.  the CPU whether an 80287 NPX is physically available in the system. The MP
  5671.  flag controls the function of the WAIT instruction. When executing a WAIT
  5672.  instruction, the 80286 tests only the Task Switched (TS) bit if MP is set;
  5673.  if it finds TS set under these conditions, the CPU traps to exception #7.
  5674.  
  5675.  The Emulation Mode (EM) bit of the 80286 machine status word indicates to
  5676.  the CPU whether NPX functions are to be emulated. If the CPU finds EM set
  5677.  when it executes an ESC instruction, program control is automatically
  5678.  trapped to exception #7, giving the exception handler the opportunity to
  5679.  emulate the functions of an 80287. The 80286 EM flag can be changed only by
  5680.  using the LMSW (load machine status word) instruction (legal only at
  5681.  privilege level 0) and examined with the aid of the SMSW (store machine
  5682.  status word) instruction (legal at any privilege level).
  5683.  
  5684.  The EM bit also controls the function of the WAIT instruction. If the CPU
  5685.  finds EM set while executing a WAIT, the CPU does not check the ERROR
  5686.  pin for an error indication.
  5687.  
  5688.  For correct 80286 operation, the EM bit must never be set concurrently with
  5689.  MP. The EM and MP bits of the 80286 are described in more detail in the
  5690.  80286 Operating System Writer's Guide. More information on software
  5691.  emulation for the 80287 NPX is described in the "80287 Emulation" section
  5692.  later in this chapter.
  5693.  
  5694.  In any case, if ESC instructions are to be executed, either the MP or EM
  5695.  bit must be set, but not both.
  5696.  
  5697.  
  5698.  Initializing the 80287
  5699.  Initializing the 80287 NPX simply means placing the NPX in a known state
  5700.  unaffected by any activity performed earlier. The example software routine
  5701.  to recognize the 80287 (figure 3-1) performed this initialization using a
  5702.  single FNINIT instruction. This instruction causes the NPX to be
  5703.  initialized in the same way as that caused by the hardware RESET signal to
  5704.  the 80287. All the error masks are set, all registers are tagged empty, the
  5705.  ST is set to zero, and default rounding, precision, and infinity controls
  5706.  are set. Table 3-1 shows the state of the 80287 NPX following
  5707.  initialization.
  5708.  
  5709.  Following a hardware RESET signal, such as after initial power-up, the
  5710.  80287 is initialized in Real-Address mode. Once the 80287 has been switched
  5711.  to Protected mode (using the FSETPM instruction), only another hardware
  5712.  RESET can switch the 80287 back to Real-Address mode. The FNINIT instruction
  5713.  does not switch the operating state of the 80287.
  5714.  
  5715.  
  5716.  80287 Emulation
  5717.  If it is determined that no 80287 NPX is available in the system, systems
  5718.  software may decide to emulate ESC instructions in software. This emulation
  5719.  is easily supported by the 80286 hardware, because the 80286 can be
  5720.  configured to trap to a software emulation routine whenever it encounters
  5721.  an ESC instruction in its instruction stream.
  5722.  
  5723.  As described previously, whenever the 80286 CPU encounters an ESC
  5724.  instruction, and its MP and EM status bits are set appropriately (MP = 0,
  5725.  EM = 1), the 80286 will automatically trap to interrupt #7, the Processor
  5726.  Extension Not Available exception. The return link stored on the stack
  5727.  points to the first byte of the ESC instruction, including the prefix
  5728.  byte(s), if any. The exception handler can use this return link to examine
  5729.  the ESC instruction and proceed to emulate the numeric instruction in
  5730.  software.
  5731.  
  5732.  The emulator must step the return pointer so that, upon return from the
  5733.  exception handler, execution can resume at the first instruction following
  5734.  the ESC instruction.
  5735.  
  5736.  To an application program, execution on an 80286 system with 80287
  5737.  emulation is almost indistinguishable from execution on an 80287  system,
  5738.  except for the difference in execution speeds.
  5739.  
  5740.  There are several important considerations when using emulation on an 80286
  5741.  system:
  5742.  
  5743.    ■  When operating in Protected-Address mode, numeric applications using
  5744.       the emulator must be executed in execute-readable code segments.
  5745.       Numeric software cannot be emulated if it is executed in execute-only
  5746.       code segments. This is because the emulator must be able to examine
  5747.       the particular numeric instruction that caused the Emulation trap.
  5748.  
  5749.    ■  Only privileged tasks can place the 80286 in emulation mode. The
  5750.       instructions necessary to place the 80286 in Emulation mode are
  5751.       privileged instructions, and are not typically accessible to an
  5752.       application.
  5753.  
  5754.  An emulator package (E80287) that runs on 80286 systems is available from
  5755.  Intel in the 8086 Software Toolbox, Order Number 122203. This emulation
  5756.  package operates in both Real and Protected mode, providing a complete
  5757.  functional equivalent for the 80287 emulated in software.
  5758.  
  5759.  When using the E80287 emulator, writers of numeric exception handlers
  5760.  should be aware of one slight difference between the emulated 80287 and the
  5761.  80287 hardware:
  5762.  
  5763.    ■  On the 80287 hardware, exception handlers are invoked by the 80286 at
  5764.       the first WAIT or ESC instruction following the instruction causing the
  5765.       exception. The return link, stored on the 80286 stack, points to this
  5766.       second WAIT or ESC instruction where execution will resume following a
  5767.       return from the exception handler.
  5768.  
  5769.    ■  Using the E80287 emulator, numeric exception handlers are invoked from
  5770.       within the emulator itself. The return link stored on the stack when
  5771.       the exception handler is invoked will therefore point back to the
  5772.       E80287 emulator, rather than to the program code actually being
  5773.       executed (emulated). An IRET return from the exception handler returns
  5774.       to the emulator, which then returns immediately to the emulated
  5775.       program. This added layer of indirection should not cause confusion,
  5776.       however, because the instruction causing the exception can always be
  5777.       identified from the 80287's instruction and data pointers.
  5778.  
  5779.  
  5780.  Table 3-1. NPX Processor State Following Initialization
  5781.  
  5782. ╓┌────────────────────────┌─────────────┌────────────────────────────────────╖
  5783.  Field                    Value         Interpretation
  5784.  
  5785.  Control Word
  5786.   Infinity Control         0            Projective
  5787.   Rounding Control         00           Round to nearest
  5788.   Precision Control        11           64 bits
  5789.   Interrupt-Enable Mask    1            Interrupts disabled
  5790.   Exception Masks          111111       All exceptions masked
  5791.  
  5792.  Status Word
  5793.   Busy                     0            Not busy
  5794.   Condition Code           ????         (Indeterminate)
  5795.   Stack Top                000          Empty stack
  5796.   Interrupt Request        0            No interrupt
  5797.   Exception Flags          000000       No exceptions
  5798.  Field                    Value         Interpretation
  5799.  Exception Flags          000000       No exceptions
  5800.  
  5801.  Tag Word
  5802.   Tags                     11           Empty
  5803.  
  5804.  Registers                 N.C.         Not changed
  5805.  
  5806.  Exception Pointers
  5807.   Instruction Code         N.C.         Not changed
  5808.   Instruction Address      N.C.         Not changed
  5809.   Operand Address          N.C.         Not changed
  5810.  
  5811.  
  5812.  Handling Numeric Processing Exceptions
  5813.  Once the 80287 has been initialized and normal execution of applications
  5814.  has been commenced, the 80287 NPX may occasionally require attention in
  5815.  order to recover from numeric processing errors. This section provides
  5816.  details for writing software exception handlers for numeric exceptions.
  5817.  Numeric processing exceptions have already been introduced in previous
  5818.  sections of this manual.
  5819.  
  5820.  As discussed previously, the 80287 NPX can take one of two actions when it
  5821.  recognizes a numeric exception:
  5822.  
  5823.    ■  If the exception is masked, the NPX will automatically perform its own
  5824.       masked exception response, correcting the exception condition according
  5825.       to fixed rules, and then continuing with its instruction execution.
  5826.  
  5827.    ■  If the exception is unmasked, the NPX signals the exception to the
  5828.       80286 CPU using the ERROR status line between the two processors.
  5829.       Each time the 80286 encounters an ESC or WAIT instruction in its
  5830.       instruction stream, the CPU checks the condition of this ERROR
  5831.       status line. If ERROR is active, the CPU automatically traps to
  5832.       Interrupt vector #16, the Processor Extension Error trap.
  5833.  
  5834.  Interrupt vector #16 typically points to a software exception handler,
  5835.  which may or may not be a part of systems software. This exception handler
  5836.  takes the form of an 80286 interrupt procedure.
  5837.  
  5838.  When handling numeric errors, the CPU has two responsibilities:
  5839.  
  5840.    ■  The CPU must not disturb the numeric context when an error is
  5841.       detected.
  5842.  
  5843.    ■  The CPU must clear the error and attempt recovery from the error.
  5844.  
  5845.  Although the manner in which programmers may treat these responsibilities
  5846.  varies from one implementation to the next, most exception handlers will
  5847.  include these basic steps:
  5848.  
  5849.    ■  Store the NPX environment (control, status, and tag words, operand and
  5850.       instruction pointers) as it existed at the time of the exception.
  5851.  
  5852.    ■  Clear the exception bits in the status word.
  5853.  
  5854.    ■  Enable interrupts on the CPU.
  5855.  
  5856.    ■  Identify the exception by examining the status and control words in
  5857.       the save environment.
  5858.  
  5859.    ■  Take some system-dependent action to rectify the exception.
  5860.  
  5861.    ■  Return to the interrupted program and resume normal execution.
  5862.  
  5863.  It should be noted that the NPX exception pointers contained in the stored
  5864.  NPX environment will take different forms, depending on whether the NPX is
  5865.  operating in Real-Address mode or in Protected mode. The earlier discussion
  5866.  of Real versus Protected mode details how this information is presented in
  5867.  each of the two operating modes.
  5868.  
  5869.  
  5870.  Simultaneous Exception Response
  5871.  In cases where multiple exceptions arise simultaneously, the 80287 signals
  5872.  one exception according to the precedence sequence shown in table 3-2. This
  5873.  means, for example, that zero divided by zero will result in an invalid
  5874.  operation, and not a zero divide exception.
  5875.  
  5876.  
  5877.  Exception Recovery Examples
  5878.  Recovery routines for NPX exceptions can take a variety of forms. They can
  5879.  change the arithmetic and programming rules of the NPX. These changes may
  5880.  redefine the default fix-up for an error, change the appearance of the NPX
  5881.  to the programmer, or change how arithmetic is defined on the NPX.
  5882.  
  5883.  A change to an error response might be to automatically normalize all
  5884.  denormals loaded from memory. A change in appearance might be extending the
  5885.  register stack into memory to provide an "infinite" number of numeric
  5886.  registers. The arithmetic of the NPX can be changed to automatically extend
  5887.  the precision and range of variables when exceeded. All these functions can
  5888.  be implemented on the NPX via numeric errors and associated recovery
  5889.  routines in a manner transparent to the application programmer.
  5890.  
  5891.  Some other possible system-dependent actions, mentioned previously, may
  5892.  include:
  5893.  
  5894.    ■  Incrementing an exception counter for later display or printing
  5895.  
  5896.    ■  Printing or displaying diagnostic information (e.g., the 80287
  5897.       environment and registers)
  5898.  
  5899.    ■  Aborting further execution
  5900.  
  5901.    ■  Storing a diagnostic value (a NaN) in the result and continuing with
  5902.       the computation
  5903.  
  5904.  Notice that an exception may or may not constitute an error, depending on
  5905.  the implementation. Once the exception handler corrects the error condition
  5906.  causing the exception, the floating-point instruction that caused the
  5907.  exception can be restarted, if appropriate. This cannot be accomplished
  5908.  using the IRET instruction, however, because the trap occurs at the ESC or
  5909.  WAIT instruction following the offending ESC instruction. The exception
  5910.  handler must obtain from the NPX the address of the offending instruction in
  5911.  the task that initiated it, make a copy of it, execute the copy in the
  5912.  context of the offending task, and then return via IRET to the current CPU
  5913.  instruction stream.
  5914.  
  5915.  In order to correct the condition causing the numeric exception, exception
  5916.  handlers must recognize the precise state of the NPX at the time the
  5917.  exception handler was invoked, and be able to reconstruct the state of the
  5918.  NPX when the exception initially occurred. To reconstruct the state of the
  5919.  NPX, programmers must understand when, during the execution of an NPX
  5920.  instruction, exceptions are actually recognized.
  5921.  
  5922.  Invalid operation, zero divide, and denormalized exceptions are detected
  5923.  before an operation begins, whereas overflow, underflow, and precision
  5924.  exceptions are not raised until a true result has been computed. When a
  5925.  before exception is detected, the NPX register stack and memory have
  5926.  not yet been updated, and appear as if the offending instructions has not
  5927.  been executed.
  5928.  
  5929.  When an after exception is detected, the register stack and memory appear
  5930.  as if the instruction has run to completion; i.e., they may be updated.
  5931.  (However, in a store or store-and-pop operation, unmasked over/underflow is
  5932.  handled like a before exception; memory is not updated and the stack is not
  5933.  popped.) The programming examples contained in Chapter Four include an
  5934.  outline of several exception handlers to process numeric exceptions for the
  5935.  80287.
  5936.  
  5937.  
  5938.  Table 3-2. Precedence of NPX Exceptions
  5939.  
  5940.  Signaled First:       Denormalized operand (if unmasked)
  5941.                        Invalid operation
  5942.                        Zero divide
  5943.                        Denormalized (if masked)
  5944.                        Over/Underflow
  5945.  Signaled Last:        Precision
  5946.  
  5947.  
  5948.  Chapter 4  Numeric Programming Examples
  5949.  
  5950.  ───────────────────────────────────────────────────────────────────────────
  5951.  
  5952.  The following sections contain examples of numeric programs for the 80287
  5953.  NPX written in ASM286. These examples are intended to illustrate some of the
  5954.  techniques for programming the 80287 computing system for numeric
  5955.  applications.
  5956.  
  5957.  
  5958.  Conditional Branching Examples
  5959.  As discussed in Chapter Two, several numeric instructions post their
  5960.  results to the condition code bits of the 80287 status word. Although there
  5961.  are many ways to implement conditional branching following a comparison, the
  5962.  basic approach is as follows:
  5963.  
  5964.    ■  Execute the comparison.
  5965.  
  5966.    ■  Store the status word. (80287 allows storing status directly into AX
  5967.       register.)
  5968.  
  5969.    ■  Inspect the condition code bits.
  5970.  
  5971.    ■  Jump on the result.
  5972.  
  5973.  Figure 4-1 is a code fragment that illustrates how two memory-resident long
  5974.  real numbers might be compared (similar code could be used with the FTST
  5975.  instruction). The numbers are called A and B, and the comparison is A to B.
  5976.  
  5977.  The comparison itself requires loading A onto the top of the 80287 register
  5978.  stack and then comparing it to B, while popping the stack with the same
  5979.  instruction. The status word is then written into the 80286 AX register.
  5980.  
  5981.  A and B have four possible orderings, and bits C3, C2, and C0 of the
  5982.  condition code indicate which ordering holds. These bits are positioned in
  5983.  the upper byte of the NPX status word so as to correspond to the CPU's zero,
  5984.  parity, and carry flags (ZF, PF, and CF), when the byte is written into the
  5985.  flags. The code fragment sets ZF, PF, and CF of the CPU status word to the
  5986.  values of C3, C2, and C0 of the NPX status word, and then uses the CPU
  5987.  conditional jump instructions to test the flags. The resulting code is
  5988.  extremely compact, requiring only seven instructions.
  5989.  
  5990.  The FXAM instruction updates all four condition code bits. Figure 4-2 shows
  5991.  how a jump table can be used to determine the characteristics of the value
  5992.  examined. The jump table (FXAM_TBL) is initialized to contain the 16-bit
  5993.  displacement of 16 labels, one for each possible condition code setting.
  5994.  Note that four of the table entries contain the same value, because four
  5995.  condition code settings correspond to "empty."
  5996.  
  5997.  The program fragment performs the FXAM and stores the status word. It then
  5998.  manipulates the condition code bits to finally produce a number in register
  5999.  BX that equals the condition code times 2. This involves zeroing the unused
  6000.  bits in the byte that contains the code, shifting C3 to the right so that
  6001.  it is adjacent to C2, and then shifting the code to multiply it by 2. The
  6002.  resulting value is used as an index that selects one of the displacements
  6003.  from FXAM_TBL (the multiplication of the condition code is required because
  6004.  of the 2-byte length of each value in FXAM_TBL). The unconditional JMP
  6005.  instruction effectively vectors through the jump table to the labelled
  6006.  routine that contains code (not shown in the example) to process each
  6007.  possible result of the FXAM instruction.
  6008.  
  6009.  
  6010.  Figure 4-1.  Conditional Branching for Compares
  6011.  
  6012.              .
  6013.              .
  6014.              .
  6015.    A         DQ        ?
  6016.    B         DQ        ?
  6017.              .
  6018.              .
  6019.              .
  6020.              FLD       A         ; LOAD A ONTO TOP OF 287 STACK
  6021.              FCOMP     B         ; COMPARE A:B, POP A
  6022.              FSTSW     AX        ; STORE RESULT TO CPU AX REGISTER
  6023.              ;
  6024.              ; CPU AX REGISTER CONTAINS CONDITION CODES (RESULTS OF
  6025.              ; COMPARE)
  6026.              ;   LOAD CONDITION CODES INTO CPU FLAGS
  6027.              SAHF
  6028.              ;
  6029.              ; USE CONDITIONAL JUMPS TO DETERMINE ORDERING OF A TO B
  6030.              ;
  6031.              JP        A_B_UNORDERED       ; TEST C2 (PF)
  6032.              JB        A_LESS              ; TEST C0 (CF)
  6033.              JE        A_EQUAL             ; TEST C3 (ZF)
  6034.    A_GREATER:                    ; C0 (CF)  =  0, C3 (ZF) = 0
  6035.              .
  6036.              .
  6037.    A_EQUAL:                      ; C0 (CF)  =  0, C3 (ZF) = 1
  6038.              .
  6039.              .
  6040.    A_LESS:                       ; C0 (CF)  =  1, C3 (ZF) = 0
  6041.              .
  6042.              .
  6043.    A_B_UNORDERED:                ; C2 (PF) = 1
  6044.              .
  6045.              .
  6046.  
  6047.  
  6048.  Figure 4-2.  Conditional Branching for FXAM
  6049.  
  6050.              ; JUMP TABLE FOR EXAMINE ROUTINE
  6051.              ;
  6052.    FXAM_TBL  DW POS_UNNORM, POS_NAN, NEG_UNNORM, NEG_NAN,
  6053.    &             POS_NORM, POS_INFINITY, NEG_NORM,
  6054.    &             NEG_INFINITY, POS_ZERO, EMPTY, NEG_ZERO,
  6055.    &             EMPTY, POS_DENORM, EMPTY, NEG_DENORM, EMPTY
  6056.              .
  6057.              .
  6058.              ;  EXAMINE ST AND STORE RESULT (CONDITION CODES)
  6059.              FXAM
  6060.              FSTSW AX
  6061.              ;
  6062.              ;  CALCULATE OFFSET INTO JUMP TABLE
  6063.              MOV       BH,0      ; CLEAR UPPER HALF OF BX,
  6064.              MOV       BL,AH     ; LOAD CONDITION CODE INTO BL
  6065.              AND       BL,00000111B    ; CLEAR ALL BITS EXCEPT C2-C0
  6066.              AND       AH,01000000B    ; CLEAR ALL BITS EXCEPT C3
  6067.              SHR       AH,2      ;  SHIFT C3 TWO PLACES RIGHT
  6068.              SAL       BX,1      ;  SHIFT C2-C0 1 PLACE LEFT (MULTIPLY
  6069.                                  ;  BY 2)
  6070.              OR        BL,AH     ;  DROP C3 BACK IN ADJACENT TO C2
  6071.                                  ;  (000XXXX0)
  6072.              ;
  6073.              ;  JUMP TO THE ROUTINE `ADDRESSED' BY CONDITION CODE
  6074.              JMP       FXAM_TBL[BX]
  6075.              ;
  6076.              ;  HERE ARE THE JUMP TARGETS, ONE TO HANDLE
  6077.              ;    EACH POSSIBLE RESULT OF FXAM
  6078.    POS_UNNORM:
  6079.              .
  6080.    POS_NAN:
  6081.              .
  6082.    NEG_UNNORM:
  6083.              .
  6084.    NEG_NAN:
  6085.              .
  6086.    POS_NORM:
  6087.              .
  6088.    POS_INFINITY:
  6089.              .
  6090.    NEG_NORM:
  6091.              .
  6092.    NEG_INFINITY:
  6093.              .
  6094.    POS_ZERO:
  6095.              .
  6096.    EMPTY:
  6097.              .
  6098.    NEG_ZERO:
  6099.              .
  6100.    POS_DENORM:
  6101.              .
  6102.    NEG_DENORM:
  6103.  
  6104.  
  6105.  Exception Handling Examples
  6106.  There are many approaches to writing exception handlers. One useful
  6107.  technique is to consider the exception handler procedure as consisting of
  6108.  "prologue," "body," and "epilogue" sections of code. (For compatibility with
  6109.  the 80287 emulators, this procedure should be invoked by interrupt pointer
  6110.  (vector) number 16.)
  6111.  
  6112.  At the beginning of the prologue, CPU interrupts have been disabled. The
  6113.  prologue performs all functions that must be protected from possible
  6114.  interruption by higher-priority sources. Typically, this will involve saving
  6115.  CPU registers and transferring diagnostic information from the 80287 to
  6116.  memory. When the critical processing has been completed, the prologue may
  6117.  enable CPU interrupts to allow higher-priority interrupt handlers to preempt
  6118.  the exception handler.
  6119.  
  6120.  The exception handler body examines the diagnostic information and makes a
  6121.  response that is necessarily application-dependent. This response may range
  6122.  from halting execution, to displaying a message, to attempting to repair the
  6123.  problem and proceed with normal execution.
  6124.  
  6125.  The epilogue essentially reverses the actions of the prologue, restoring
  6126.  the CPU and the NPX so that normal execution can be resumed. The epilogue
  6127.  must not load an unmasked exception flag into the 80287 or another exception
  6128.  will be requested immediately.
  6129.  
  6130.  Figures 4-3, 4-4 and 4-5 show the ASM286 coding of three skeleton
  6131.  exception handlers. They show how prologues and epilogues can be written for
  6132.  various situations, but provide comments indicating only where the
  6133.  application-dependent exception handling body should be placed.
  6134.  
  6135.  Figure 4-3 and 4-4 are very similar; their only substantial difference is
  6136.  their choice of instructions to save and restore the 80287. The tradeoff
  6137.  here is between the increased diagnostic information provided by FNSAVE and
  6138.  the faster execution of FNSTENV. For applications that are sensitive to
  6139.  interrupt latency or that do not need to examine register contents, FNSTENV
  6140.  reduces the duration of the "critical region," during which the CPU will
  6141.  not recognize another interrupt request (unless it is a nonmaskable
  6142.  interrupt).
  6143.  
  6144.  After the exception handler body, the epilogues prepare the CPU and the NPX
  6145.  to resume execution from the point of interruption (i.e., the instruction
  6146.  following the one that generated the unmasked exception). Notice that the
  6147.  exception flags in the memory image that is loaded into the 80287 are
  6148.  cleared to zero prior to reloading (in fact, in these examples, the entire
  6149.  status word image is cleared).
  6150.  
  6151.  The examples in figures 4-3 and 4-4 assume that the exception handler
  6152.  itself will not cause an unmasked exception. Where this is a possibility,
  6153.  the general approach shown in figure 4-5 can be employed. The basic
  6154.  technique is to save the full 80287 state and then to load a new control
  6155.  word in the prologue. Note that considerable care should be taken when
  6156.  designing an exception handler of this type to prevent the handler from
  6157.  being reentered endlessly.
  6158.  
  6159.  
  6160.  Figure 4-3.  Full-State Exception Handler
  6161.  
  6162.    SAVE_ALL            PROC
  6163.    ;
  6164.    ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 STATE IMAGE
  6165.              PUSH      BP
  6166.              MOV       BP,SP
  6167.              SUB       SP,94
  6168.    ; SAVE FULL 80287 STATE, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
  6169.              FNSAVE    [BP-94]
  6170.              FWAIT
  6171.              STI
  6172.    ;
  6173.    ; APPLICATION-DEPENDENT EXCEPTION HANDLING CODE GOES HERE
  6174.    ;
  6175.    ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
  6176.              MOV       BYTE PTR [BP-92], 0H
  6177.              FRSTOR    [BP-94]
  6178.    ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
  6179.              MOV       SP,BP
  6180.              .
  6181.              .
  6182.              POP       BP
  6183.    ;
  6184.    ; RETURN TO INTERRUPTED CALCULATION
  6185.              IRET
  6186.    SAVE_ALL            ENDP
  6187.  
  6188.  
  6189.  Figure 4-4.  Reduced-Latency Exception Handler
  6190.  
  6191.    SAVE_ENVIRONMENT PROC
  6192.    ;
  6193.    ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 ENVIRONMENT
  6194.              PUSH      BP
  6195.              .
  6196.              MOV       BP,SP
  6197.              SUB       SP,14
  6198.    ; SAVE ENVIRONMENT, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
  6199.              FNSTENV   [BP-14]
  6200.              FWAIT
  6201.              STI
  6202.    ;
  6203.    ; APPLICATION EXCEPTION-HANDLING CODE GOES HERE
  6204.    ;
  6205.    ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED
  6206.    ; ENVIRONMENT IMAGE
  6207.              MOV       BYTE PTR [BP-12], 0H
  6208.              FLDENV    [BP-14]
  6209.    ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
  6210.              MOV       SP,BP
  6211.              POP       BP
  6212.    ;
  6213.    ; RETURN TO INTERRUPTED CALCULATION
  6214.              IRET
  6215.    SAVE_ENVIRONMENT ENDP
  6216.  
  6217.  
  6218.  Figure 4-5.  Reentrant Exception Handler
  6219.  
  6220.              .
  6221.              .
  6222.              .
  6223.           LOCAL_CONTROL  DW  ?  ; ASSUME INITIALIZED
  6224.              .
  6225.              .
  6226.              .
  6227.    REENTRANT           PROC
  6228.    ;
  6229.    ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR
  6230.    ; 80287 STATE IMAGE
  6231.           PUSH     BP
  6232.              .
  6233.              .
  6234.              .
  6235.          MOV       BP,SP
  6236.          SUB       SP,94
  6237.    ; SAVE STATE, LOAD NEW CONTROL WORD, FOR COMPLETION, ENABLE CPU
  6238.    ; INTERRUPTS
  6239.          FNSAVE    [BP-94]
  6240.          FLDCW     LOCAL_CONTROL
  6241.          STI
  6242.              .
  6243.              .
  6244.              .
  6245.    ; APPLICATION EXCEPTION HANDLING CODE GOES HERE.
  6246.    ; AN UNMASKED EXCEPTION GENERATED HERE WILL CAUSE THE EXCEPTION
  6247.    ; HANDLER TO BE REENTERED.
  6248.    ; IF LOCAL STORAGE IS NEEDED, IT MUST BE ALLOCATED ON THE CPU STACK.
  6249.              .
  6250.              .
  6251.              .
  6252.    ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
  6253.          MOV       BYTE PTR [BP-92], 0H
  6254.          FRSTOR    [BP-94]
  6255.    ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
  6256.          MOV       SP,BP
  6257.              .
  6258.              .
  6259.              .
  6260.          POP       BP
  6261.    ; RETURN TO POINT OF INTERRUPTION
  6262.          IRET
  6263.    REENTRANT           ENDP
  6264.  
  6265.  
  6266.  Floating-Point to ASCII Conversion Examples
  6267.  Numeric programs must typically format their results at some point for
  6268.  presentation and inspection by the program user. In many cases, numeric
  6269.  results are formatted as ASCII strings for printing or display. This example
  6270.  shows how floating-point values can be converted to decimal ASCII character
  6271.  strings. The function shown in figure 4-6 can be invoked from PL/M-286,
  6272.  Pascal-286, FORTRAN-286, or ASM286 routines.
  6273.  
  6274.  Shortness, speed, and accuracy were chosen rather than providing the
  6275.  maximum number of significant digits possible. An attempt is made to keep
  6276.  integers in their own domain to avoid unnecessary conversion errors.
  6277.  
  6278.  Using the extended precision real number format, this routine achieves a
  6279.  worst case accuracy of three units in the 16th decimal position for a
  6280.  noninteger value or integers greater than 10^(18). This is double precision
  6281.  accuracy. With values having decimal exponents less than 100 in magnitude,
  6282.  the accuracy is one unit in the 17th decimal position.
  6283.  
  6284.  Higher precision can be achieved with greater care in programming, larger
  6285.  program size, and lower performance.
  6286.  
  6287.  
  6288.  Figure 4-6.  Floating-Point to ASCII Conversion Routine
  6289.  
  6290.  iAPX286 MACRO ASSEMBLER   80287 Floating-Point to 18-Digit ASCII Conversion
  6291.  
  6292.  SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE FLOATING_TO_ASCII
  6293.  OBJECT MODULE PLACED IN :F3:FPASC.OBJ
  6294.  ASSEMBLER INVOKED BY:  ASM286.86 :F3:FPASC.AP2
  6295.  
  6296.  LOC  OBJ           LINE       SOURCE
  6297.  
  6298.                        1  +1   $title("80287 Floating-Point to 18-Digit ASCII
  6299.                        2
  6300.                        3                       name    floating_to_ascii
  6301.                        4
  6302.                        5                       public  floating_to_ascii
  6303.                        6                       extrn   get_power_IO near.tos_s
  6304.                        7       ;
  6305.                        8       ;        This subroutine will convert the float
  6306.                        9       ;        top of the 80287 stack to an ASCII str
  6307.                       10       ;        scaling value (in binary).  The maximu
  6308.                       11       ;        formed is controlled by a parameter wh
  6309.                       12       ;        denormal values, and psuedo zeroes wil
  6310.                       13       ;        A returned value will indicate how man
  6311.                       14       ;        precision were lost in an unnormal or
  6312.                       15       ;        (in terms of binary power) of a psuedo
  6313.                       16       ;        Integers less than 10**18 in magnitude
  6314.                       17       ;        destination ASCII string field is wide
  6315.                       18       ;        digits.  Otherwise the value is conver
  6316.                       19       ;
  6317.                       20       ;          The status of the conversion is iden
  6318.                       21       ;        it can be:
  6319.                       22       ;
  6320.                       23       ;                0       conversion complete, s
  6321.                       24       ;                1       invalid arguments
  6322.                       25       ;                2       exact integer conversi
  6323.                       26       ;                3       indefinite
  6324.                       27       ;                4       + NAN (Not A Number)
  6325.                       28       ;                5       - NAN
  6326.                       29       ;                6       + Infinity
  6327.                       30       ;                7       - Infinity
  6328.                       31       ;                8       psuedo zero found, str
  6329.                       32       ;
  6330.                       33       ;            The PLM/286 calling convention is
  6331.                       34       ;
  6332.                       35       ;floating_to_ascii:
  6333.                       36       ;        procedure (number,denormal ptr, string
  6334.                       37       ;                power_ptr) word external.
  6335.                       38       ;        declare (denormal_ptr, string ptr, pow
  6336.                       39       ;        declare field_size word, string_size b
  6337.                       40       ;        delcare number real;
  6338.                       41       ;        declare denormal integer based denorma
  6339.                       42       ;        declare power integer based power_ptr,
  6340.                       43       ;        and floating_to_ascii,
  6341.                       44       ;
  6342.                       45       ;          The floating point value is expected
  6343.                       46       ;        stack.  This subroutine expects 3 free
  6344.                       47       ;        will pop the passed value off when don
  6345.                       48       ;        will have a leading character either '
  6346.                       49       ;        of the value.  The ASCII decimal digit
  6347.                       50       ;        The numeric value of the ASCII string
  6348.                       51       ;        If the given number was zero, the ASCI
  6349.                       52       ;        and a single zero character.  The valu
  6350.                       53       ;        length of the ASCII string including t
  6351.                       54       ;        always hold the sign.  It is possible
  6352.                       55       ;        field_size.  This occurs for zeroes or
  6353.                       56       ;        will return a special return code.  Th
  6354.                       57       ;        the power of the two originally associ
  6355.                       58       ;        ten and ASCII string will be as if the
  6356.                       59       ;
  6357.                       60       ;          The subroutine is accurate up to a m
  6358.                       61       ;        integers.  Integer values will have a
  6359.                       62       ;        with them.  For non-integers, the resu
  6360.                       63       ;        decimal digits of the 16th decimal pla
  6361.                       64       ;        exponentiate instruction is also used
  6362.                       65       ;        range acceptable for the BCD data type
  6363.                       66       ;        on entry to the subroutine is used for
  6364.                       67       ;
  6365.                       68       ;          The following registers are not tran
  6366.                       69       ;
  6367.                       70       ;                ax bx cx dx si di flags
  6368.                       71       ;
  6369.                       72  +1  $eject
  6370.                       73       ;
  6371.                       74       ;           Define the stack layout
  6372.                       75       ;
  6373.   0000[]              76       bp_save     equ     word ptr [bp]
  6374.   0002[]              77       es_save     equ     bp_save + size bp_save
  6375.   0004[]              78       return_ptr  equ     es_save + size es_save
  6376.   0006[]              79       power_ptr   equ     return_ptr _ size return_pt
  6377.   0008[]              80       field_size  equ     power_ptr + size power_ptr
  6378.   000A[]              81       size_ptr    equ     field_size + size field_siz
  6379.   000C[]              82       string_ptr  equ     size_ptr + size size_ptr
  6380.   000E[]              83       denormal_ptr    equ     string_ptr + size strin
  6381.                       84
  6382.                       85       parms_size  equ     size power_ptr + size field
  6383.   000A                86       &                   size string_ptr + size deno
  6384.                       87
  6385.                       88                   Define constants used
  6386.                       89
  6387.   0012                90       BCD_DIGIIS  equ     18          ; Number of dig
  6388.   0002                91       WORD-SIZE   equ     2
  6389.   000A                92       BCD_SIZE    equ     10
  6390.   0001                93       MINUS       equ     1           ; Define return
  6391.   0004                94       NAN         equ     4           ; The exact val
  6392.   0006                95       INFINITY    equ     6           ; important.  T
  6393.   0003                96       INDEFINITE  equ     3           ; the possible
  6394.   0008                97       PSUEDO_ZERO equ     8           ; the same nume
  6395.  -0002                98       INVALID     equ     -2          ; the program.
  6396.  -0004                99       ZERO        equ     -4
  6397.  -0006               100       DENORMAL    equ     -6
  6398.   0008               101       UNNORMAL    equ     -8
  6399.   0000               102       NORMAL      equ     0
  6400.   0002               103       EXACT       equ     2
  6401.                      104       ;
  6402.                      105       ;           Define layout of temporary storage
  6403.                      106       ;
  6404.  -0002[]             107       status      equ     word ptr [bp-WORD_SIZE]
  6405.  -0004[]             108       power_two   equ     status - WORD_SIZE
  6406.  -0006[]             109       power_ten   equ     power_two - WORD_SIZE
  6407.  -0010[]             110       bcd_value   equ     tbyte ptr power_ten - BCD_S
  6408.  -0010[]             111       bcd_byte    equ     byte ptr bcd_value
  6409.  -0010[]             112       fraction    equ     bcd_value
  6410.                      113
  6411.                      114       local_size  equ     size status + size pwer_two
  6412.   0010               115       &                   + size bcd_value
  6413.                      116
  6414.  ----                117       stack       stackseg (local_size+6) ; Allocate
  6415.                      118   +1  $eject
  6416.  ----                119       code        segment or public
  6417.                      120                   extrn   power_table:qword
  6418.                      121       ;
  6419.                      122       ;           Constants used by this function
  6420.                      123       ;
  6421.                      124                       even                ; Optimize
  6422.  0000 0A00           125       const10         dw      10          ; Adjustmen
  6423.                      126       ;
  6424.                      127       ;         Convert the C3,C2,C1,C0 encoding from
  6425.                      128       ;       flags and values.
  6426.                      129       ;
  6427.  0002 F8             130       status_table    db  UNNORMAL, NAN, UNNORMAL + M
  6428.  0003 04
  6429.  0004 F9
  6430.  0005 05
  6431.  0006 00             131       &                   NORMAL, INFINITY, NORMAL +
  6432.  0007 06
  6433.  0008 01
  6434.  0009 07
  6435.  000A FC             132       &                   ZERO, INVALID, ZERO + MINUS
  6436.  000B FE
  6437.  000C FD
  6438.  000D FE
  6439.  000E FA             133       &                   DENORMAL, INVALID, DENORMAL
  6440.  000F FE
  6441.  0010 FB
  6442.  0011 FE
  6443.                      134
  6444.  0012                135       floating_to_ascii proc
  6445.                      136
  6446.  0012 E80000         137               call    tos_status              ; look
  6447.  0015 8BD8           138               mov     bx,ax                   ; Get d
  6448.  0017 2E8A870200     139               mov     al,status_table[bx]
  6449.  001C 3CFE           140               cmp     al,INVALID              ; Look
  6450.  001E 752B           141               jne     not_empty
  6451.                      142       ;
  6452.                      143       ;        ST(0) is empty!  Return the status val
  6453.                      144       ;
  6454.  0020 C20A00         145               ret     parms_size
  6455.                      146       ;
  6456.                      147       ;         Remove infinity from stack and exit
  6457.                      148       ;
  6458.  0023                149       found_infinity
  6459.                      150
  6460.  0023 DDD8           151               fstp    st(0)                   ; OR to
  6461.  0025 EB02           152               jmp     short exit_proc
  6462.                      153       ;
  6463.                      154       ;         String space is too small!  Return in
  6464.                      155       ;
  6465.  0027                156       small_string
  6466.                      157
  6467.  0027 B0FE           158               mov     al,INVALID
  6468.                      159
  6469.  0029                160       exit_proc:
  6470.                      161
  6471.  0029 C9             162               leave                           ; Resto
  6472.  002A 07             163               pop     es
  6473.  002B C20A00         164               ret     parms_size
  6474.                      165       ;
  6475.                      166       ;         ST(0) is NAN or indefinite.  Store th
  6476.                      167       ;       at the fraction field to separate indef
  6477.                      168       ;
  6478.  002E                169       NAN_or_indefinite:
  6479.  002E DB7EF0         170
  6480.  0031 A801           171               fstp    fraction                ; Remov
  6481.  0033 9B             172               test    al,MINUS                ; Look
  6482.  0034 74F3           173               fwait                           ; Insur
  6483.                      174               jz      exit_proc               ; Can't
  6484.  0036 BB00C0         175
  6485.  0039 2B5EF6         176               mov     bx,0C000H               ; Match
  6486.  003C 0B5EF4         177               sub     bx,word ptr fraction+6  ; Compa
  6487.  003F 0B5EF2         178               or      bx,word ptr fraction+4  ; Bits
  6488.  0042 0B5EF0         179               or      bx,word ptr fraction+2  ; Bits
  6489.  0045 75E2           180               or      bx,word ptr fraction    ; Bits
  6490.                      181               jnz     exit_proc
  6491.  0047 B003           182
  6492.  0049 EBDE           183               mov     al,INDEFINITE           ; Set r
  6493.                      184               jmp     exit_proc
  6494.                      185       ;
  6495.                      186       ;         Allocate stack space for local variab
  6496.                      187       ;       addressibility.
  6497.                      188       ;
  6498.  004B                189       not_empty:
  6499.                      190
  6500.  004B 06             191               push    es                      ; Save
  6501.  004C C8100000       192               enter   local_size,0            ; Forma
  6502.                      193
  6503.  0050 8B4E08         194               mov     cx,field_ize            ; Check
  6504.  0053 83F902         195               cmp     cx,2
  6505.  0056 7CCF           196               jl      sjall_string
  6506.                      197
  6507.  005B 49             198               dec     cx                      ; Adjus
  6508.  0059 83F912         199               cmp     cx,BCD_DIGITS           ; See i
  6509.  005C 7603           200               jbe     size_ok
  6510.                      201
  6511.  005E B91200         202               mov     cx,BCD_DIGITS           ; Else
  6512.                      203
  6513.  0061                204       size_ok:
  6514.                      205
  6515.  0061 3C06           206               cmp     al,INFINITY             ; Look
  6516.  0063 7DBE           207               jge     found_infinity          ; Retur
  6517.                      208
  6518.  0065 3C04           209               cmp     al,NAN                  ; Look
  6519.  0067 7DC5           210               jge     NAN_or_indefinite
  6520.                      211       ;
  6521.                      212       ;         Set default return values and check t
  6522.                      213       ;
  6523.  0069 D9E1           214               fabs                            ; Use p
  6524.                      215                                               ; sign
  6525.  006B 8BD0           216               mov     dx,ax                   ; Save
  6526.  006D 33C0           217               xor     ax,ax                   ; Form
  6527.  006F 8B7E0E         218               mov     di,denormal_ptr         ; Zero
  6528.  0072 8905           219               mov     word ptr [di],ax
  6529.  0074 8B5E06         220               mov     bx,power_ptr            ; Zero
  6530.  0077 B907           221               mov     word ptr [bx],ax
  6531.  0079 80FAFC         222               cmp     dl,ZERO                 ; Test
  6532.  007C 732B           223               jae     real_zero               ; Skip
  6533.                      224
  6534.  007E 80FAFA         225               cmp     dl,DENORMAL             ; Look
  6535.  008A 732C           226               jae     found_denormal          ; Handl
  6536.                      227
  6537.  0083 D9F4           228               fxtract                         ; Separ
  6538.  0085 80FAF8         229               cmp     dl,UNNORMAL             ; Test
  6539.  0088 7240           230               jb      normal_value
  6540.                      231
  6541.  008A 80EAF8         232               sub     dl,UNNORMAL-NORMAL      ; Retur
  6542.                      233       ;
  6543.                      234       ;         Normalize the fraction, adjust the po
  6544.                      235       ;       the denormal count value
  6545.                      236       ;
  6546.                      237       ;       Assert 0 <= ST(0) < 1.0
  6547.                      238       ;
  6548.  008D D9E8           239               fld1                            ; Load
  6549.                      240
  6550.  008F                241       normalize_fraction
  6551.                      242
  6552.  008F DCC1           243               fadd    st(1),st                ; Set i
  6553.  0091 DEE9           244               fsub                            ; Form
  6554.  0093 D9F4           245               fxtract                         ; Power
  6555.                      246                                               ; of de
  6556.  0095 D9C9           247               fxch                            ; Put d
  6557.  0097 DF15           248               fist    word ptr [di]           ; Put n
  6558.  0099 DEC2           249               faddp   st(2),st                ; Form
  6559.                      250                                               ; OK to
  6560.  009B F71D           251               neg     word ptr [di]           ; Form
  6561.  009D 752B           252               jnz     not_psuedo_zero
  6562.                      253       ;
  6563.                      254       ;         A psuedo zero will appear as an unnor
  6564.                      255       ;       to normalize it, the resultant fraction
  6565.                      256       ;       an fxtract on zero will yield a zero ex
  6566.                      257       ;
  6567.  009F D9C9           258               fxch                        ; Put power
  6568.  00A1 DF1D           259               fistp   wrd ptr [di]        ; Set denor
  6569.                      260                                           ; Word ptr
  6570.                      261                                           ; integer,
  6571.  00A3 B0EAF8         262               sub     dl,NORMAL-PSUEDO_ZERO ; Set ret
  6572.  00A6 E9A400         263               jmp     convert_integer     ; Put zero
  6573.                      264       ;
  6574.                      265       ;         The number is a real zero, set the re
  6575.                      266       ;       conversion to BCD.
  6576.                      267       ;
  6577.  00A9                268       real_zero
  6578.                      269
  6579.  00A9 80EAF0         270               sub     dl,ZERO-NORMAL          ; Conve
  6580.  00AC E99E00         271               jmp     convert_integer         ; Treat
  6581.                      272       ;
  6582.                      273       ;         The number is a denormal.  FXTRACT wi
  6583.                      274       ;       case.  To correctly separate the expone
  6584.                      275       ;       constant to the exponent to guarantee t
  6585.                      276       ;
  6586.  00AF                277       found_denormal:
  6587.                      278
  6588.  00AF D9E8           279               fld1                            ; Prepa
  6589.  00B1 D9C9           280               fxch
  6590.  00B3 D9F8           281               fprem                           ; Force
  6591.                      282                                               ; exten
  6592.  00B5 D9F4           283               fxtract                         ; This
  6593.                      284       ;
  6594.                      285       ;         The power of the original enormal val
  6595.                      286       ;       Check if the fraction value is an unnor
  6596.                      287       ;
  6597.  00B7 D9E5           288               fxam                            ; See i
  6598.  00B9 9BDFE0         289               fstsw   ax                      ; Save
  6599.  00BC D9C9           290               fxch                            ; Put e
  6600.  00BE D9CA           291               fxch    st(2)                   ; Put 1
  6601.  00C0 80EAFA         292               sub     dl,DENORMAL-NORMAL      ; Retur
  6602.  00C3 A90044         293               test    ax,4400H                ; See i
  6603.  00C6 74C7           294               jz      normalize_fraction      ; Jump
  6604.                      295
  6605.  00C8 DDD8           296               fstp    st(0)                   ; Remov
  6606.                      297       ;
  6607.                      298       ;         Calculate the decimal magnitude assoc
  6608.                      299       ;       within one order.  This error will alwa
  6609.                      300       ;       rounding and lost precision.  As a resu
  6610.                      301       ;       to consider the LOQ10 of the fraction v
  6611.                      302       ;       Since the fraction will always be 1 <=
  6612.                      303       ;       the basic accuracy of the function.  To
  6613.                      304       ;       simply multiply the power of two by LOQ
  6614.                      305       ;       an integer.
  6615.                      306       ;
  6616.  00CA                307       normal_value:
  6617.  00CA                308       not_pseudo_zero:
  6618.                      309
  6619.  00CA DB7EF0         310               fstp    fraction                ; Save
  6620.  00CD DF56FC         311               fist    power_two               ; Save
  6621.  00D0 D9EC           312               fldlg2                          ; Get L
  6622.                      313                                               ; Power
  6623.  00D2 DEC9           314               fmul                            ; Form
  6624.  00D4 DF5EFA         315               fistp   power_ten               ; Any r
  6625.                      316       ;
  6626.                      317       ;         Check if the magnitude of the number
  6627.                      318       ;       an integer.
  6628.                      319       ;
  6629.                      320       ;       CX has the maximum number of decimal di
  6630.                      321       ;
  6631.  00D7 7B             322               fwait                           ; Wait
  6632.  00D8 3B46FA         323               mov     ax,power_ten            ; Get p
  6633.  00DB 2BC1           324               sub     ax,cx                   ; Form
  6634.  00DD 7722           325               ja      adjust_result           ; Jump
  6635.                      326       ;
  6636.                      327       ;         The number is between 1 and 10**(fiel
  6637.                      328       ;       Test if it is an integer.
  6638.                      329       ;
  6639.  00DF 0F46FC         330               fild    power_two               ; Resto
  6640.  00E2 8BF2           331               mov     si,dx                   ; Save
  6641.  00E4 80EAFE         332               sub     dl,NORMAL-EXACT         ; Conve
  6642.  00E7 0B6EF0         333               fld     fraction
  6643.  00EA 09FD           334               fscale                          ; Form
  6644.  00EC DDD1           335               fst     st(1)                   ; Copy
  6645.  00EE 09FC           336               frndint                         ; Test
  6646.  00F0 08D9           337               fcomp                           ; Compa
  6647.  00F2 7BDD7EFE       338               fstsw   status                  ; Save
  6648.  00F6 F746FE0040     339               test    status,4000H            ; C3=1
  6649.  00FB 7550           340               jnz     convert_integer
  6650.                      341
  6651.  00FD DDD8           342               fstp    st(0)                   ; Remov
  6652.  00FF 8BD6           343               mov     dx,si                   ; Resto
  6653.                      344       ;
  6654.                      345       ;         Scale the number to within the range
  6655.                      346       ;       The scaling operation should produce a
  6656.                      347       ;       of magnitude of the largest decimal num
  6657.                      348       ;       given string width.
  6658.                      349       ;
  6659.                      350       ;         The scaling power of ten value is in
  6660.                      351       ;
  6661.  0101                352       adjust_result:
  6662.                      353
  6663.  0101 8907           354               mov     word ptr [bx],ax        ; Set i
  6664.  0103 F7D8           355               neg     ax                      ; Subst
  6665.                      356                                               ; of ma
  6666.  0105 E80000     E   357               call    get_power_10            ; Scali
  6667.                      358                                               ; and f
  6668.  0108 DB6EF0         359               fld     fraction                ; Get f
  6669.  010B DEC9           360               fmul                            ; Combi
  6670.  010D 8BF1           361               mov     si,cx                   ; Form
  6671.  010F D1E6           362               shl     si,1                    ; BCD v
  6672.  0111 D1E6           363               shl     si,1                    ; Index
  6673.  0113 D1E6           364               shl     si,1
  6674.  0115 DF46FC         365               fild    power_two               ; Combi
  6675.  0118 DEC2           366               faddp   st(2),st
  6676.  011A D9FD           367               fscale                          ; Form
  6677.  011C DDD9           368               fstp    st(1)                   ; Remov
  6678.                      369       ;
  6679.                      370       ;         Test the adjusted value against a tab
  6680.                      371       ;       The combined errors of the magnitude es
  6681.                      372       ;       result in a value one order of magnitud
  6682.                      373       ;       correctly in the BCD field.  To handle
  6683.                      374       ;       adjusted value, if it is too small or l
  6684.                      375       ;       adjust the power of ten value.
  6685.                      376       ;
  6686.  011E                377       test_power:
  6687.  011E 2EDC940800  E  378
  6688.                      379               fcom    power_table[si]_type power_tabl
  6689.                      380                                               ; entry
  6690.                      381                                               ; has b
  6691.  0123 9BDFE0         382               fstsw   ax                      ; No wa
  6692.  0126 690041         383               test    ax,4100H                ; If C3
  6693.  0129 750C           384               jnz     text_for_small
  6694.                      385
  6695.  012B 2EDE360000  R  386               fidiv   const10                 ; Else
  6696.  0130 80E2FD         387               and     dl,not EXACT            ; Remov
  6697.  0133 FF07           388               inc     word ptr [bx]           ; Adjus
  6698.  0135 EB14           389               jmp     short in_range          ; Conve
  6699.                      390
  6700.  0137                391       test_for_small
  6701.                      392
  6702.  0137 2EDC940000  E  393               fcom    power_table[si]         ; Test
  6703.  013C 9BDFE0         394               fstsw   ax                      ; No wa
  6704.  013F A90001         395               test    ax,100H                 ; If C0
  6705.  0142 7407           396               jz      in_range                ; Conve
  6706.                      397
  6707.  0144 2EDE0E0000  R  398               fimul   const10                 ; Adjus
  6708.  0149 FF0F           399               dec     word ptr [bx]           ; Adjus
  6709.                      400
  6710.  014B                401       in_range:
  6711.                      402
  6712.  014B D9FC           403               frndint                         ; Form
  6713.                      404       ;
  6714.                      405       ;       Assert: 0 <= TOS <= 999,999,999,999,999
  6715.                      406       ;       The TOS number will be exactly represen
  6716.                      407       ;
  6717.  014D                408       convert_integer:
  6718.                      409
  6719.  014D DF76F0         410               fbstp   bcd_value               ; Store
  6720.                      411       ;
  6721.                      412       ;         While the store BCD runs, setup regis
  6722.                      413       ;       ASCII.
  6723.                      414       ;
  6724.  0150 BE0800         415               mov     si,BCD_SIZE-2           ; Initi
  6725.  0153 B9040F         416               mov     cx,0f04h                ; Set s
  6726.  0156 BB0100         417               mov     bx,1                    ; Set i
  6727.  0159 8B730C         418               mov     di,string_ptr           ; Get a
  6728.  015C BCD8           419               mov     ax,ds                   ; Copy
  6729.  015E BEC0           420               mov     es,ax
  6730.  0160 FC             421               cld                             ; Set a
  6731.  0161 B02B           422               mov     al,'+'                  ; Clear
  6732.  0163 F6C201         423               text    dl,MINUS                ; Look
  6733.  0166 7402           424               jr      positive_result
  6734.                      425
  6735.  0168 B02D           426               mov     al,'-'
  6736.                      427
  6737.  016A                428       positive_result:
  6738.                      429
  6739.  016A AA             430               stash                           ; Bump
  6740.  016B 809E2FE        431               and     dl,not MINUS            ; Turn
  6741.  016E 9B             432               fwait                           ; Wait
  6742.                      433       ;
  6743.                      434       ;         Register usage:
  6744.                      435       ;                               ah:     BCD byt
  6745.                      436       ;                               al:     ASCII c
  6746.                      437       ;                               dx:     Return
  6747.                      438       ;                               ch:     BCD mas
  6748.                      439       ;                               cl      BCD shi
  6749.                      440       ;                               bx:     ASCII s
  6750.                      441       ;                               si:     BCD fie
  6751.                      442       ;                               di:     ASCII s
  6752.                      443       ;                               ds,es:  ASCII s
  6753.                      444       ;
  6754.                      445       ;         Remove leading zeroes from the number
  6755.                      446       ;
  6756.  016F                447       skip_leading_zeroes
  6757.                      448
  6758.  016F 8A62F0         449               move    ah,bcd_byte[si]         ; Get B
  6759.  0172 BAC4           450               move    al,ah                   ; Copy
  6760.  0174 D2E8           451               shr     al,cl                   ; Get h
  6761.  0176 22C5           452               and     al,ch                   ; Set z
  6762.  0178 7516           453               jnz     enter_odd               ; Enter
  6763.                      454
  6764.  017A 8AC4           455               mov     al,ah                   ; Get B
  6765.  017C 22C5           456               and     al,ch                   ; Get l
  6766.  017E 7518           457               jnz     enter_even
  6767.                      458
  6768.  0180 4E             459               dec     si                      ; Decre
  6769.  0181 79EC           460               jns     skip_leading_zeroes
  6770.                      461       ;
  6771.                      462       ;         The significand was all zeroes
  6772.                      463       ;
  6773.  0183 B030           464               mov     al,'0'                  ; Set i
  6774.  0185 AA             465               stosb
  6775.  0186 43             466               inc     bx                      ; Bump
  6776.  0187 EB16           467               jmp     short exit_with_value
  6777.                      468       ;
  6778.                      469       ;         Now expand the BCD string into digit
  6779.                      470       ;
  6780.  0189                471       digit_loop
  6781.                      472
  6782.  0189 8A62F0         473               mov     ah,bcd_byte[si]         ; Get B
  6783.  018C 8AC4           474               mov     al,ah
  6784.  018E D2E8           475               shr     al,cl                   ; Get h
  6785.                      476
  6786.  0190                477       enter_odd
  6787.                      478
  6788.  0190 0430           479               add     al,'0'                  ; Conve
  6789.  0192 AA             480               stosb                           ; Put d
  6790.  0193 8AC4           481               mov     al,ah                   ; Get l
  6791.  0195 22C5           482               and     al,ch
  6792.  0197 43             483               inc     bx                      ; Bump
  6793.                      484
  6794.  0198 0430           485       enter_even
  6795.  019A AA             486
  6796.  019B 43             487               add     al,'0'                  ; Conve
  6797.  019C 4E             488               stosb                           ; Put d
  6798.  019D 79EA           489               inc     bx                      ; Bump
  6799.                      490               dec     si                      ; Go to
  6800.                      491               jns     digit_loop
  6801.                      492       ;
  6802.                      493       ;         Conversion complete.  Set the string
  6803.                      494       ;
  6804.  019F                495       exit_with_value:
  6805.                      496
  6806.  019F 8B7E0A         497               move    di,size_ptr
  6807.  01A2 891D           498               mov     word ptr [di],bx
  6808.  01A4 8BC2           499               mov     ax,x                    ; Set r
  6809.  01A6 E980FE         500               jmp     exit_proc
  6810.                      501
  6811.                      502       floating_to_ascii       endp
  6812.  ----                503       code                    ends
  6813.                      504                               end
  6814.  ASSEMBLY COMPLETE,          NO WARNINGS,    NO ERRORS
  6815.  
  6816.  
  6817.  iAPX286 MACRO ASSEMBLER     Calculate the value of 10**ax            12:11:08
  6818.  
  6819.  SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE GET_POWER_10
  6820.  OBJECT MODULE PLACED IN :F3:POW10.OBJ
  6821.  ASSEMBLER INVOKED BY:  ASM286.86 :F3:POW10.AP2
  6822.  
  6823.  LOC  OBJ           LINE       SOURCE
  6824.  
  6825.                        1  +1   $title("Calculate the value of 10**ax")
  6826.                        2       ;
  6827.                        3       ;         This subroutine will calculate the va
  6828.                        4       ;       For values of 0 <= ax <19, the result w
  6829.                        5       ;       All 80286 registers are transparent and
  6830.                        6       ;       the TOS as two numbers, exponent in ST(
  6831.                        7       ;       The exponent value can be larger than t
  6832.                        8       ;       extended real format number.  Three sta
  6833.                        9       ;
  6834.                       10                       name    get_power_10
  6835.                       11
  6836.                       12                       public  get_power_10,power_tabl
  6837.                       13
  6838.  ----                 14       stack           stackseg 8
  6839.                       15
  6840.  ----                 16       code            segment or public
  6841.                       17       ;
  6842.                       18       ;         Use exact values from 1:0 to 1e18
  6843.                       19       ;
  6844.                       20                       even                        ; O
  6845.  0000 000000000000F0  21       power_table     dq      1.0,1e1,1e2,1e3
  6846.       3F
  6847.  0008 00000000000024
  6848.       40
  6849.  0010 00000000000059
  6850.       40
  6851.  0018 0000000000408F
  6852.       40
  6853.  0020 000000000088C3  22                       dq      1e4,1e5,1e6,1e7
  6854.       40
  6855.  0028 00000000006AF8
  6856.       40
  6857.  0030 0000000080842E
  6858.       41
  6859.  0038 00000000D01263
  6860.       41
  6861.  0040 0000000084D797  23                       dq      1e8,1e9,1e10,1e11
  6862.       41
  6863.  0048 0000000065CDCD
  6864.       41
  6865.  0050 000000205FA002
  6866.       42
  6867.  0058 000000E8764837
  6868.       42
  6869.  0060 000000A2941A6D  24                       dq      1e12,1e13,1e14,1e15
  6870.       42
  6871.  0068 000040E59C30A2
  6872.       42
  6873.  0070 0000901EC4BCD6
  6874.       42
  6875.  0078 00003426F56B0C
  6876.       43
  6877.  0080 0080E03779C341  25                       dq      1e16,1e17,1e18
  6878.       43
  6879.  0088 00A0D885573476
  6880.       43
  6881.  0090 00C84E676DC1AB
  6882.       43
  6883.  0098                 26
  6884.                       27       get_power_10    proc
  6885.  0098 3D1200          28
  6886.  009B 770F            29               cmp     ax,18                       ; T
  6887.                       30               ja      out_of_range
  6888.  009D 53              31
  6889.  009E 8BD8            32               push    bx                          ; G
  6890.  00A0 C1E303          33               mov     bx,ax                       ; F
  6891.  00A3 2EDD870000    R 34               shl     bx,3
  6892.  00A8 5B              35               fld     power_table[bx]             ; G
  6893.  00A9 D9F4            36               pop     bx                          ; R
  6894.  00AB C3              37               fxtract                             ; S
  6895.                       38               ret                                 ; O
  6896.                       39       ;
  6897.                       40       ;         Calculate the value using the exponen
  6898.                       41       ;       The following relations are used:
  6899.                       42       ;               10**x = 2**(log2(10)*x)
  6900.                       43       ;               2**(I+F) = 2**I * 2**F
  6901.                       44       ;               if st(1) = I and st(0) = 2**F t
  6902.                       45       ;
  6903.  00AC                 46       out_of_range:
  6904.                       47
  6905.  00AC D9E9            48               fld12t                              ; T
  6906.  00AE C8040000        49               enter   4.0                         ; F
  6907.  00B2 8946FE          50               mov     [bp-2],ax                   ; S
  6908.  00B5 DE4EFE          51               fimul   word ptr [bp-1]             ; T
  6909.  00B8 9BD97EFC        52               fstcw   word ptr [bp-4]             ; G
  6910.  00BC 8B46FC          53               mov     ax,word ptr [bp-4]          ; G
  6911.  00BF 25FFF3          54               and     ax,not OCOOH                ; M
  6912.  00C2 0D0004          55               or      ax,0400H                    ; S
  6913.  00C5 6746FC          56               xchg    ax,word ptr [bp-4]          ; P
  6914.                       57                                                   ; o
  6915.  00C8 D9E8            58               fld1                                ; S
  6916.  00CA D9E0            59               fchs
  6917.  00CC D9C1            60               fld     st(1)
  6918.  00CE D96EFC          61               fldcw   word ptr [bp-4]
  6919.  00D1 D9FC            62               frndint
  6920.  00D3 8946FC          63               mov     word ptr [bp-4],ax
  6921.  00D6 D96EFC          64               fldcw   word ptr [bp-4]
  6922.  00D9 D9CA            65               fxch    st(2)
  6923.  00DB DBE2            66               fsub    st,st(2)
  6924.  00DD 8B46FE          67               mov     ax,[bp-2]
  6925.  00E0 D9FD            68               fscale
  6926.  00E2 D9F0            69               f2xm1
  6927.  00E4 C9              70               leave
  6928.  00E5 DEE1            71               fsubr
  6929.  00E7 DCC8            72               fmul    st,st(0)
  6930.  00E9 C3              73               ret
  6931.                       74
  6932.                       75       get_power_10    endp
  6933.                       76
  6934.  ----                 77       code            ends
  6935.                       78                       end
  6936.  ASSEMBLY COMPLETE,        NO WARNINGS,   NO ERRORS
  6937.  
  6938.  
  6939.  iAPX286 MACRO ASSEMBLER   Determine TOS register contents          12:12:13 0
  6940.  
  6941.  SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TOS_STATUS
  6942.  OBJECT MODULE PLACED IN :F3:T0SST.OBJ
  6943.  ASSEMBLER INVOKED BY:  ASM286.86 :F3:TOSST.AP2
  6944.  
  6945.  LOC  OBJ           LINE      SOURCE
  6946.  
  6947.                        1   +1  $title("Determine TOS register contents")
  6948.                        2       ;
  6949.                        3       ;         This subroutine will return a value f
  6950.                        4       ;       to the contents of 80287 TOS.  All regi
  6951.                        5       ;       errors are possible.  The return value
  6952.                        6       ;       of FXAM instruction.
  6953.                        7       ;
  6954.                        8               name    tos_status
  6955.                        9
  6956.                       10               public  tos_status
  6957.                       11
  6958.  ----                 12       stack           stackseg 6              ; Alloc
  6959.                       13
  6960.  ----                 14       code            segment er public
  6961.                       15
  6962.  0000                 16       tos_status      proc
  6963.                       17
  6964.  0000 D9E5            18               fxam                            ; Get r
  6965.  0002 9BDFE0          19               fstsw   ax                      ; Get s
  6966.  0005 8AC4            20               mov     al,ah                   ; Put b
  6967.  0007 250740          21               and     ax,4007h                ; Mask
  6968.  000A C0EC03          22               shr     ah,3                    ; Put b
  6969.  000D 0AC4            23               or      al,ah                   ; Put c
  6970.  000F B400            24               mov     ah,0                    ; Clear
  6971.  0011 C3              25               ret
  6972.                       26
  6973.                       27       tos_status      endp
  6974.                       28
  6975.  ----                 29       code            ends
  6976.                       30                       end
  6977.  ASSEMBLY COMPLETE,       NO WARNINGS,   NO ERRORS
  6978.  
  6979.  
  6980.  Function Partitioning
  6981.  Three separate modules implement the conversion. Most of the work of the
  6982.  conversion is done in the module FLOATING_TO_ASCII. The other modules are
  6983.  provided separately, because they have a more general use. One of them,
  6984.  GET_POWER_10, is also used by the ASCII to floating-point conversion
  6985.  routine. The other small module, TOS_STATUS, will identify what, if
  6986.  anything, is in the top of the numeric register stack.
  6987.  
  6988.  
  6989.  Exception Considerations
  6990.  Care is taken inside the function to avoid generating exceptions. Any
  6991.  possible numeric value will be accepted. The only exceptions possible would
  6992.  occur if insufficient space exists on the numeric register stack.
  6993.  
  6994.  The value passed in the numeric stack is checked for existence, type (NaN
  6995.  or infinity), and status (unnormal, denormal, zero, sign). The string size
  6996.  is tested for a minimum and maximum value. If the top of the register stack
  6997.  is empty, or the string size is too small, the function will return with an
  6998.  error code.
  6999.  
  7000.  Overflow and underflow is avoided inside the function for very large or
  7001.  very small numbers.
  7002.  
  7003.  
  7004.  Special Instructions
  7005.  The functions demonstrate the operation of several numeric instructions,
  7006.  different data types, and precision control. Shown are instructions for
  7007.  automatic conversion to BCD, calculating the value of 10 raised to an
  7008.  integer value, establishing and maintaining concurrency, data
  7009.  synchronization, and use of directed rounding on the NPX.
  7010.  
  7011.  Without the extended precision data type and built-in exponential function,
  7012.  the double precision accuracy of this function could not be attained with
  7013.  the size and speed of the shown example.
  7014.  
  7015.  The function relies on the numeric BCD data type for conversion from binary
  7016.  floating-point to decimal. It is not difficult to unpack the BCD digits into
  7017.  separate ASCII decimal digits. The major work involves scaling the
  7018.  floating-point value to the comparatively limited range of BCD values. To
  7019.  print a 9-digit result requires accurately scaling the given value to an
  7020.  integer between 10^(8) and 10^(9). For example, the number +0.123456789
  7021.  requires a scaling factor of 10^(9) to produce the value +123456789.0,
  7022.  which can be stored in 9 BCD digits. The scale factor must be an exact
  7023.  power of 10 to avoid to changing any of the printed digit values.
  7024.  
  7025.  These routines should exactly convert all values exactly representable in
  7026.  decimal in the field size given. Integer values that fit in the given string
  7027.  size will not be scaled, but directly stored into the BCD form. Noninteger
  7028.  values exactly representable in decimal within the string size limits will
  7029.  also be exactly converted. For example, 0.125 is exactly representable in
  7030.  binary or decimal. To convert this floating-point value to decimal, the
  7031.  scaling factor will be 1000, resulting in 125. When scaling a value, the
  7032.  function must keep track of where the decimal point lies in the final
  7033.  decimal value.
  7034.  
  7035.  
  7036.  Description of Operation
  7037.  Converting a floating-point number to decimal ASCII takes three major
  7038.  steps: identifying the magnitude of the number, scaling it for the BCD data
  7039.  type, and converting the BCD data type to a decimal ASCII string.
  7040.  
  7041.  Identifying the magnitude of the result requires finding the value X such
  7042.  that the number is represented by I*10^(X), where 1.0 <= I < 10.0. Scaling
  7043.  the number requires multiplying it by a scaling factor 10^(S), so that the
  7044.  result is an integer requiring no more decimal digits than provided for in
  7045.  the ASCII string.
  7046.  
  7047.  Once scaled, the numeric rounding modes and BCD conversion put the number
  7048.  in a form easy to convert to decimal ASCII by host software.
  7049.  
  7050.  Implementing each of these three steps requires attention to detail. To
  7051.  begin with, not all floating-point values have a numeric meaning. Values
  7052.  such as infinity, indefinite, or Not a Number (NaN) may be encountered by
  7053.  the conversion routine. The conversion routine should recognize these
  7054.  values and identify them uniquely.
  7055.  
  7056.  Special cases of numeric values also exist. Denormals, unnormals, and
  7057.  pseudo zero all have a numeric value but should be recognized, because all
  7058.  of them indicate that precision was lost during some earlier calculations.
  7059.  
  7060.  Once it has been determined that the number has a numeric value, and it is
  7061.  normalized setting appropriate unnormal flags, the value must be scaled to
  7062.  the BCD range.
  7063.  
  7064.  
  7065.  Scaling the Value
  7066.  To scale the number, its magnitude must be determined. It is sufficient to
  7067.  calculate the magnitude to an accuracy of 1 unit, or within a factor of 10
  7068.  of the given value. After scaling the number, a check will be made to see if
  7069.  the result falls in the range expected. If not, the result can be adjusted
  7070.  one decimal order of magnitude up or down. The adjustment test after the
  7071.  scaling is necessary due to inevitable inaccuracies in the scaling value.
  7072.  
  7073.  Because the magnitude estimate need only be close, a fast technique is
  7074.  used. The magnitude is estimated by multiplying the power of 2, the unbiased
  7075.  floating-point exponent, associated with the number by log{10}2. Rounding
  7076.  the result to an integer will produce an estimate of sufficient accuracy.
  7077.  Ignoring the fraction value can introduce a maximum error of 0.32 in the
  7078.  result.
  7079.  
  7080.  Using the magnitude of the value and size of the number string, the scaling
  7081.  factor can be calculated. Calculating the scaling factor is the most
  7082.  inaccurate operation of the conversion process. The relation
  7083.  10^(X)=2**(X * log{2}10) is used for this function. The exponentiate
  7084.  instruction (F2XM1) will be used.
  7085.  
  7086.  Due to restrictions on the range of values allowed by the F2XM1
  7087.  instruction, the power of 2 value will be split into integer and fraction
  7088.  components. The relation 2**(I + F) = 2**I * 2**F allows using the FSCALE
  7089.  instruction to recombine the 2**F value, calculated through F2XM1, and the
  7090.  2**I part.
  7091.  
  7092.  
  7093.  Inaccuracy in Scaling
  7094.  The inaccuracy of these operations arises because of the trailing zeros
  7095.  placed into the fraction value when stripping off the integer valued bits.
  7096.  For each integer valued bit in the power of 2 value separated from the
  7097.  fraction bits, one bit of precision is lost in the fraction field due to
  7098.  the zero fill occurring in the least significant bits.
  7099.  
  7100.  Up to 14 bits may be lost in the fraction because the largest allowed
  7101.  floating point exponent value is 2^(14) - 1.
  7102.  
  7103.  
  7104.  Avoiding Underflow and Overflow
  7105.  The fraction and exponent fields of the number are separated to avoid
  7106.  underflow and overflow in calculating the scaling values. For example, to
  7107.  scale 10^(4932) to 10^(8) requires a scaling factor of 10^(4950), which
  7108.  cannot be represented by the NPX.
  7109.  
  7110.  By separating the exponent and fraction, the scaling operation involves
  7111.  adding the exponents separate from multiplying the fractions. The exponent
  7112.  arithmetic will involve small integers, all easily represented by the NPX.
  7113.  
  7114.  
  7115.  Final Adjustments
  7116.  It is possible that the power function (Get_Power_10) could produce a
  7117.  scaling value such that it forms a scaled result larger than the ASCII field
  7118.  could allow. For example, scaling 9.9999999999999999 * 10^(4900) by
  7119.  1.00000000000000010 * 10^(-4883) would produce 1.00000000000000009 *
  7120.  10^(18). The scale factor is within the accuracy of the NPX and the result
  7121.  is within the conversion accuracy, but it cannot be represented in BCD
  7122.  format. This is why there is a post-scaling test on the magnitude of the
  7123.  result. The result can be multiplied or divided by 10, depending on whether
  7124.  the result was too small or too large, respectively.
  7125.  
  7126.  
  7127.  Output Format
  7128.  For maximum flexibility in output formats, the position of the decimal
  7129.  point is indicated by a binary integer called the power value. If the power
  7130.  value is zero, then the decimal point is assumed to be at the right of the
  7131.  rightmost digit. Power values greater than zero indicate how many trailing
  7132.  zeros are not shown. For each unit below zero, move the decimal point to the
  7133.  left in the string.
  7134.  
  7135.  The last step of the conversion is storing the result in BCD and indicating
  7136.  where the decimal point lies. The BCD string is then unpacked into ASCII
  7137.  decimal characters. The ASCII sign is set corresponding to the sign of the
  7138.  original value.
  7139.  
  7140.  
  7141.  Trigonometric Calculation Examples
  7142.  The 80287 instruction set does not provide a complete set of trigonometric
  7143.  functions that can be used directly in calculations. Rather, the basic
  7144.  building blocks for implementing trigonometric functions are provided by the
  7145.  FPTAN and FPREM instructions. The example in figure 4-7 shows how three
  7146.  trigonometric functions (sine, cosine, and tangent) can be implementing
  7147.  using the 80287. All three functions accept a valid angle argument between
  7148.  -2^(62) and +2^(62). These functions may be called from PL/M-286,
  7149.  Pascal-286, FORTRAN-286, or ASM286 routines.
  7150.  
  7151.  These trigonometric functions use the partial tangent instruction together
  7152.  with trigonometric identities to calculate the result. They are accurate to
  7153.  within 16 units of the low 4 bits of an extended precision value. The
  7154.  functions are coded for speed and small size, with tradeoffs available for
  7155.  greater accuracy.
  7156.  
  7157.  Figure 4-7. Calculating Trigonometric Functions
  7158.  
  7159.  
  7160.  iAPX286 MACRO ASSEMBLER   80287 Trigonometric functions           10:13:51 09
  7161.  
  7162.  SERIES-888 iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TRIG_FUNCTIONS
  7163.  OBJECT MODULE PLACED IN :F3:TRIG.OBJ
  7164.  ASSEMBLER INVOKED BY:  ASM286.86 :F3:TRIG.AP2
  7165.  
  7166.  LOC  OBJ           LINE     SOURCE
  7167.  
  7168.                        1  +1   $title("80287 Trigonometric Functions")
  7169.                        2
  7170.                        3                       name    trig_functions
  7171.                        4                       public  sine,cosine,tangent
  7172.                        5
  7173.  ----                  6       stack           stackseg        6           ; R
  7174.                        7
  7175.     #                  8       sw_287          record  res1:1,cond3:1,top:3,co
  7176.                        9                               res2:8
  7177.                       10
  7178.  ----                 11       code            segment er public
  7179.                       12       ;
  7180.                       13       ;         Define local constants
  7181.                       14       ;
  7182.                       15                       even
  7183.  0000 35C26821A2DA0F  16       pi_quarter      dt      3FFEC90FDAA22168C235R ;
  7184.       C9FE3F
  7185.  000A 0000C0FF        17       indefinite      dd      0FFC000000R         ; I
  7186.                       18  +1   $eject
  7187.                       19       ;
  7188.                       20       ;         This subroutine calculates the sine o
  7189.                       21       ;       radians.  The angle is in ST(0), the re
  7190.                       22       ;       The result is accurate to within 7 unit
  7191.                       23       ;       bits of the NPX extended real format.
  7192.                       24       ;
  7193.                       25       ;       sine:   procedure (angle) real external
  7194.                       26       ;               declare angle real;
  7195.                       27       ;               and sine;
  7196.                       28       ;
  7197.                       29       ;       cosine: procedure (angle) real external
  7198.                       30       ;               declare angle real;
  7199.                       31       ;               and cosine;
  7200.                       32       ;
  7201.                       33       ;         Three stack registers are required.
  7202.                       34       ;       defined as follows for the following ar
  7203.                       35       ;
  7204.                       36       ;                       angle
  7205.                       37       ;
  7206.                       38       ;               valid or unnormal less than 2**
  7207.                       39       ;               zero
  7208.                       40       ;               denormal
  7209.                       41       ;               valid or unnormal greater than
  7210.                       42       ;               infinity
  7211.                       43       ;               NAN
  7212.                       44       ;               empty
  7213.                       45 +1    $eject
  7214.                       46       ;
  7215.                       47       ;         This function is based on the NPX fpt
  7216.                       48       ;       instruction will only work with an angl
  7217.                       49       ;       instruction, the sine or cisone of angl
  7218.                       50       ;       calculated.  The technique used by this
  7219.                       51       ;       sine or cosine by using one of four pos
  7220.                       52       ;
  7221.                       53       ;                   Let R = |angle mod PI/4|
  7222.                       54       ;                       S = -1 or 1, according
  7223.                       55       ;
  7224.                       56       ;       1) sin(R)   2) cos(R)   3) sin(PI/4-R)
  7225.                       57       ;
  7226.                       58       ;         The choice of the relation and the si
  7227.                       59       ;       decision table shown below based on the
  7228.                       60       ;
  7229.                       61       ;               octant          sine
  7230.                       62       ;
  7231.                       63       ;                 0              s*1
  7232.                       64       ;                 1              s*4
  7233.                       65       ;                 2              s*2
  7234.                       66       ;                 3              s*3
  7235.                       67       ;                 4             -s*1
  7236.                       68       ;                 5             -s*4
  7237.                       69       ;                 6             -s*2
  7238.                       70       ;                 7             -s*3
  7239.                       71       ;
  7240.                       72 +1    $eject
  7241.                       73       ;
  7242.                       74       ;         Angle to sine function is a zero or u
  7243.                       75       ;
  7244.  000E                 76       sine_zero_unnormal:
  7245.                       77
  7246.  000E DDD9            78               fstp    st(1)
  7247.  0010 7501            79               jnz     enter_sine_normalize
  7248.                       80       ;
  7249.                       81       ;         Angle is a zero.
  7250.                       82       ;
  7251.  0012 C3              83               ret
  7252.                       84       ;
  7253.                       85       ;         Angle is an unnormal
  7254.                       86       ;
  7255.  0013                 87       enter_sine_normalize:
  7256.                       88
  7257.  0013 E80901          89               call    normalize_value
  7258.  0016 EB2F            90               jmp     short enter_sine
  7259.                       91
  7260.  0018                 92       cosine  proc
  7261.                       93
  7262.  0018 D9E5            94               fxam
  7263.  00A1 9BDF30          95               fstsw   ax
  7264.  001D 2EDB2E0000   R  96               fld     pi_quarter
  7265.  0022 B101            97               mov     c1,1
  7266.  0024 9E              98               sahf
  7267.  0025 7263            99               jc      funny_parameter
  7268.                      100
  7269.                      101       ;
  7270.                      102       ;         Angle is unnormal, normal, zero, deno
  7271.                      103       ;
  7272.  0027 D9C9           104               fxch
  7273.  0029 7A1C           105               jpe     enter_sine
  7274.                      106       ;
  7275.                      107       ;         Angle is an unnormal or zero
  7276.                      108       ;
  7277.  002B DDD9           109               fstp    st(1)
  7278.  002D 75E4           110               jnz     enter_sine_normalize
  7279.                      111       ;
  7280.                      112       ;         Angle is a zero, cos(0) = 1.0
  7281.                      113       ;
  7282.  002F DDD8           114               fstp    st(0)                       ; R
  7283.  0031 D9E8           115               fldl                                ; R
  7284.  0033 C3             116               ret
  7285.                      117       ;
  7286.                      118       ;         All work is done as a sine function.
  7287.                      119       ;       a cosine is converted to a sine.  Of co
  7288.                      120       ;       done to the argument but rather to the
  7289.                      121       ;
  7290.  0034                122       sine                                        ; E
  7291.                      123
  7292.  0034 D9E5           124               fxam                                ; L
  7293.  0036 9BDFE0         125               fstsw   ax                          ; L
  7294.  0039 2EDB2E0000   R 126               fld     pi_quarter                  ; G
  7295.  003E 9E             127               sahf                                ; C
  7296.  003F 7249           128               jc      funny_parameter             ; J
  7297.                      129       ;
  7298.                      130       ;         Angle is unnormal, normal, zero, or d
  7299.                      131       ;
  7300.  0041 D9C9           132               fxch                                ; S
  7301.  0043 B100           133               mov     c1,0                        ; S
  7302.  0045 7BC7           134               jpo     sine_zero_unnormal          ; J
  7303.                      135       ;
  7304.                      136       ;         ST(0) is either a normal or denormal
  7305.                      137       ;       Use the fprem instruction to accurately
  7306.                      138       ;       angle to within 0 and PI/4 in magnitude
  7307.                      139       ;       angle in one shot, the angle is too big
  7308.                      140       ;       radians.  Any roundoff error in the cal
  7309.                      141       ;       could completely change the result of t
  7310.                      142       ;       call this very rare case an error.
  7311.                      143       ;
  7312.  0047                144       enter_sine
  7313.  0047 D9F8           145               fprem                               ; R
  7314.                      146                                                   ; N
  7315.                      147                                                   ; d
  7316.                      148                                                   ; F
  7317.                      149                                                   ; w
  7318.                      150                                                   ; u
  7319.  0049 93             151               xchg    ax,bx                       ; S
  7320.  004A 9BDFE0         152               fstsw   ax                          ; C
  7321.                      153                                                   ; Q
  7322.  004D 93             154               xchg    ax,bx                       ; P
  7323.  004E F6C704         155               test    bh,high(mask cond2)         ; s
  7324.  0051 7544           156               jnz     angle_too_big
  7325.                      157       ;
  7326.                      158       ;         Set sign flags and test for which eig
  7327.                      159       ;       angle fell intl.
  7328.                      160       ;
  7329.                      161       ;       Assert -PI/4 < st(0) < PI/4
  7330.                      162       ;
  7331.  0053 D9E1           163               fabs                                ; F
  7332.                      164                                                   ; c
  7333.  0055 0AC9           165               or      c1,c1                       ; T
  7334.  0057 740F           166               jz      sine_select                 ; J
  7335.                      167       ;
  7336.                      168       ;         This is a cosine function.  Ignore th
  7337.                      169       ;       and add a quarter revolution to the oct
  7338.                      170       ;       cos(A) = sin(A+PI/2) and cos(|A|) = cos
  7339.                      171       ;
  7340.  0059 B0E4FD         172               and     ah,not high(mask cond1)     ; T
  7341.  005C B0CF80         173               or      by,80H                      ; P
  7342.                      174                                                   ; s
  7343.                      175                                                   ; S
  7344.  005F 80C740         176               add     bh,high(mask cond3)         ; C
  7345.  0062 B000           177               mov     al,0                        ; E
  7346.  0064 D0D0           178               rcl     al,1                        ; P
  7347.  0066 32FB           179               xor     bh,al                       ; A
  7348.                      180                                                   ; C
  7349.                      181       ;
  7350.                      182       ;         See if the argument should be reverse
  7351.                      183       ;       which the argument fell during fprem.
  7352.                      184       ;
  7353.  0068                185       sine_select:
  7354.                      186
  7355.  0068 F6C702         187               test    bh,high(mask cond1)         ; R
  7356.  006B 7404           188               jz      no_sine_reverse
  7357.                      189       ;
  7358.                      190       ;         Angle was in octants 1,3,5,7.
  7359.                      191       ;
  7360.  006D DEE9           192               fsub                                ; I
  7361.  006F EB0E           193               jmp     short do_sine_fptan         ; 0
  7362.                      194       ;
  7363.                      195       ;         Angle was in octants 0,2,4,6
  7364.                      196       ;       Test for a zero argument since fptan wi
  7365.                      197       ;
  7366.  0071                198       no_sine_reverse:
  7367.                      199
  7368.  0071 D9E4           200               ftst                                ; T
  7369.  0073 91             201               xchg    ax,cx
  7370.  0074 9BDFE0         202               fstsw   ax                          ; c
  7371.  0077 91             203               xchg    ax,cx
  7372.  0078 DDD9           204               fstp    st(1)                       ; R
  7373.  007A F6C540         205               test    ch,high(mask cond3)         ; I
  7374.  007D 7514           206               jnz     sine_argument_zero
  7375.                      207       ;
  7376.                      208       ;       Assert: 0 < st(0) <= PI/4
  7377.                      209       ;
  7378.  007F                210       do_sine_fptan:
  7379.                      211
  7380.  007F D9F2           212               fptan
  7381.                      213
  7382.  0081                214       after_sine_fptan:
  7383.                      215
  7384.  0081 F6C742         216               test    bh,high(mask cond3 + mask cond1
  7385.  0084 7B1A           217               jpo     x_numerator
  7386.                      218
  7387.                      219       ;
  7388.                      220       ;         Calculate the sine of the argument
  7389.                      221       ;       sine(A) = tan(A)/sqrt(1+tan(A)**2)
  7390.                      222       ;       sin(A) = Y/sqrt(X*X + Y*Y)
  7391.                      223       ;
  7392.  0086 D9C1           224               fld     st(1)
  7393.  0088 EB1A           225               jmp     short finish_sine
  7394.                      226       ;
  7395.                      227       ;         The top of the stack is either NAN, i
  7396.                      228       ;
  7397.  008A                229       funny_parameter:
  7398.                      230
  7399.  008A DDD8           231               fstp    st(0)
  7400.  008C 7404           232               jz      return_empty
  7401.                      233
  7402.  008E 7B02           234               jpo     return_NAN
  7403.                      235       ;
  7404.                      236       ;         st(0) is infinity.  Return an indefin
  7405.                      237       ;
  7406.  0090 D9F8           238               fprem
  7407.                      239
  7408.  0092                240       return_NAN:
  7409.  0092                241       return_empty:
  7410.                      242
  7411.  0092 C3             243               ret
  7412.                      244       ;
  7413.                      245       ;       Simulate fptan with st(0) = 0
  7414.                      246       ;
  7415.  0093                247       sine_argument_zero:
  7416.                      248
  7417.  0093 D9EB           249               fld1
  7418.  0095 EBEA           250               jmp     after_sine_fptan
  7419.                      251       ;
  7420.                      252       ;         The angle was too large.  Remove the
  7421.                      253       ;       stack and return an indefinite result.
  7422.                      254       ;
  7423.  0097                255       angle_too_big:
  7424.                      256
  7425.  0097 DED9           257               fcompp
  7426.  0099 2ED9060A00   R 258               fld     indefinite
  7427.  009E 9B             259               fwait
  7428.  009F C3             260               ret
  7429.                      261       ;
  7430.                      262       ;         Calculate the cosine of the argument
  7431.                      263       ;       cos(A) = 1/sqrt(1+tan(A)**2)    if tan(
  7432.                      264       ;       cos(A) = X/sqrt(X*X + Y*Y)
  7433.                      265       ;
  7434.  00A0                266       X_numerator:
  7435.                      267
  7436.  00A0 D9C0           268               fld     st(0)
  7437.  00A2 D9CA           269               fxch    st(2)
  7438.                      270
  7439.  00A4                271       finish_sine:
  7440.                      272
  7441.  00A4 DCCB           273               fmul    st,st(0)
  7442.  
  7443.  00A6 D9C9           274               fxch
  7444.  00AB DCC8           275               fmul    st,st(0)
  7445.  00AA DEC1           276               fadd
  7446.  00AC D9FA           277               fsqrt
  7447.                      278
  7448.                      279
  7449.                      280       ;         Form the sign of th result.  The two
  7450.                      281       ;       FXAM in bh and the CO flag from fprem i
  7451.                      282       ;
  7452.  00AE 80E701         283               and     bh,high(mask cond0)
  7453.  00B1 80E402         284               and     ah,high(mask cond1)
  7454.  00B4 0AFC           285               or      bh,ah
  7455.  00B6 7A02           286               jpe     positive_sine
  7456.                      287
  7457.  00B8 D9E0           288               fchs
  7458.                      289
  7459.  00BA                290       positive_sine:
  7460.                      291
  7461.  00BA DEF9           292               fdiv
  7462.  00BC C3             293               ret
  7463.                      294
  7464.                      295       cosine endp
  7465.                      296   +1  $eject
  7466.                      297       ;
  7467.                      298       ;         This function will calculate the tang
  7468.                      299       ;       The angle, in radians is passed in ST(0
  7469.                      300       ;       in ST(0).  The tangent is calculated to
  7470.                      301       ;       least three significant bits of an exte
  7471.                      302       ;       PLM/86 calling format is:
  7472.                      303       ;
  7473.                      304       ;     tangent   procedure (angle) real external
  7474.                      305       ;               declare angle real;
  7475.                      306       ;               end tangent;
  7476.                      307       ;
  7477.                      308       ;         Two stack registers are used.  The re
  7478.                      309       ;       defined for the following cases:
  7479.                      310       ;
  7480.                      311       ;                               angle
  7481.                      312       ;
  7482.                      313       ;               valid or unnormal < 2**62 in ma
  7483.                      314       ;               0
  7484.                      315       ;               denormal
  7485.                      316       ;               valid or unnormal > 2**62 in ma
  7486.                      317       ;               NAN
  7487.                      318       ;               infinity
  7488.                      319       ;               empty
  7489.                      320       ;
  7490.                      321       ;         The tangent instruction uses the fpta
  7491.                      322       ;       relations are used:
  7492.                      323       ;
  7493.                      324       ;         Let R = |angle MOD PI/4|
  7494.                      325       ;             S = -1 or 1 depending on the sign
  7495.                      326       ;
  7496.                      327       ;       1) tan(R)   2) tan(PI/4-R)  3) 1/tan(R)
  7497.                      328       ;
  7498.                      329       ;         The following table is used to decide
  7499.                      330       ;       on in which octant the angle fell.
  7500.                      331       ;
  7501.                      332       ;       octant          relation
  7502.                      333       ;
  7503.                      334       ;         0              s*1
  7504.                      335       ;         1              s*4
  7505.                      336       ;         2             -s*3
  7506.                      337       ;         3             -s*2
  7507.                      338       ;         4              s*1
  7508.                      339       ;         5              s*4
  7509.                      340       ;         6             -s*3
  7510.                      341       ;         7             -s*2
  7511.                      342       ;
  7512.  00BD                343       tangent proc
  7513.                      344
  7514.  00BD D9E5           345               fram
  7515.  00BF 9BDFE0         346               fstw    ax
  7516.  00C2 2EDB2E0000  R  347               fld     pi_quarter
  7517.  00C7 9E             348               sahf
  7518.  00C8 72C0           349               jc      funny_parameter
  7519.                      350       ;
  7520.                      351       ;         Angle is unnormal, normal, zero, or d
  7521.                      352       ;
  7522.  00CA D9C9           353               fxch
  7523.  00CC 7A17           354               jpe     tan_zero_unnormal
  7524.                      355       ;
  7525.                      356       ;         Angle is either an normal or denormal
  7526.                      357       ;       Reduc the angle to the range -PI/4 < re
  7527.                      358       ;       If fprem cannot perform this operation
  7528.                      359       ;       angle must be > 2**62.  Such an angle i
  7529.                      360       ;       errors could make a very large differen
  7530.                      361       ;       It is safest to call this very rare cas
  7531.                      362       ;
  7532.  00CE                363       tan_normal
  7533.                      364
  7534.  00CE D9F8           365               fprem
  7535.                      366
  7536.  00D0 93             367               xchg    ax,bx
  7537.  00D1 9BDFE0         368               fstsw   ax
  7538.                      369
  7539.  00D4 93             370               xchg    ax,bx
  7540.  00D5 F6C704         371               test    bh,high(mask cond2)
  7541.  00D8 7BD            372               jnz     angle_too_big
  7542.                      373       ;
  7543.                      374       ;         See if the angle must be reversed.
  7544.                      375       ;
  7545.                      376       ;       Assert -PI/4 < st(0) < PI/4
  7546.                      377       ;
  7547.  00DA D9E1           378               fabs
  7548.                      379
  7549.  00DC F6C702         380               test    bh,high(mask cond1)
  7550.  00DF 740E           381               jz      no_tan_reverse
  7551.                      382       ;
  7552.                      383       ;         Angle fell in octants 1,3,5,7.  Rever
  7553.                      384       ;
  7554.  00E1 DEE9           385               fsub
  7555.  00E3 EB18           386               jmp     short do_tangent
  7556.                      387       ;
  7557.                      388       ;         Angle is either zero or an unnormal
  7558.                      389       ;
  7559.  00E5                390       tan_zero_unnormal:
  7560.                      391
  7561.  00E5 DDD9           392               fstp    st(1)
  7562.  00E7 7405           393               jz      tan_angle_zero
  7563.                      394       ;
  7564.                      395       ;       Angle is an unnormal.
  7565.                      396       ;
  7566.  00E9 E83300         397               call    normalize_value
  7567.  00EC EBE0           398               jmp     tan_normal
  7568.                      399
  7569.  00EE                400       tan_angle_zero:
  7570.                      401
  7571.  00EE C3             402               ret
  7572.                      403       ;
  7573.                      404                 Angle fell in octants 0,2,4,6. Test f
  7574.                      405       ;
  7575.  00EF                406       no_tan_reverse:
  7576.                      407
  7577.  00EF D9E4           408               ftst
  7578.  00F1 91             409               xchg    ax,cx
  7579.  00F2 9BDFE0         410               fstsw   ax
  7580.  00F5 91             411               fstp    st(1)
  7581.  00F6 DDD9           412               test    ch,high(mask cond3)
  7582.  00F8 F6C540         413               jnz     tan_zero
  7583.  00FB 7515           414
  7584.                      415       do_tangent:
  7585.  00FD                416
  7586.                      417               fptan
  7587.  00FD D9F2           418
  7588.                      419       after_tangent:
  7589.  00FF                420       ;
  7590.                      421       ;         Decide on the order of the operands a
  7591.                      422       ;       operation while the fptan instruction i
  7592.                      423       ;
  7593.                      424               mov     al,bh
  7594.  00FF 8AC7           425               and     ax,mask cond1 + high(mask cond3
  7595.  0101 254002         426
  7596.                      427               test    bh,high(mask cond1 + mask cond3
  7597.  0104 F6C742         428
  7598.                      429               jpo     reverse_divide
  7599.  0107 7B0D           430
  7600.                      431       ;
  7601.                      432       ;         Angle was in octants 0,3,4,7
  7602.                      433       ;       Test for the sign of the result.  Two n
  7603.                      434       ;
  7604.                      435               or      al,ah
  7605.  0109 0AC4           436               jpe     positive_divide
  7606.  010B 7A02           437
  7607.                      438               fchs
  7608.  010D D9E0           439
  7609.                      440       positive_divide:
  7610.  010F                441
  7611.                      442               fdiv
  7612.  010F DEF9           443               ret
  7613.  0111 C3             444
  7614.                      445       tan_zero:
  7615.  0112                446
  7616.                      447               fld1
  7617.  0112 D9E8           448       ;
  7618.  0114 EBE9           449       ;         Angle was in octants 1,2,5,6
  7619.                      450       ;       Set the correct sign of the result
  7620.                      451       ;
  7621.                      452       reverse_divide:
  7622.                      453
  7623.  0116                454               or      al,ah
  7624.                      455               jpe     positive_r_divide
  7625.  0116 0AC4           456
  7626.  0118 7A02           457               fchs
  7627.                      458
  7628.  011A D9E0           459       positive_r_divide:
  7629.                      460
  7630.  011C                461               fdivr
  7631.                      462               ret
  7632.  011C DEF1           463
  7633.  011E C3F1           464       tangent endp
  7634.                      465       ;
  7635.                      466       ;         This function will normalize the valu
  7636.                      467       ;       Then PI/4 is placed into st(1).
  7637.                      468       ;
  7638.                      469       normalize_value:
  7639.                      470
  7640.  011F                471               fabs
  7641.                      472               fxtract
  7642.  011F D9E1           473               fld1
  7643.  0121 D9F4           474               fadd    st(1),st
  7644.  0123 D9E8           475               fsub
  7645.  0125 DCC1           476               fscale
  7646.  0127 DEE9           477               fstp    st(1)
  7647.  0129 D9FD           478               fld     pi_quarter
  7648.  012B DDD9           479               fxch
  7649.  012D 2EDB2E0000  R  480               ret
  7650.  0132 D9C9           481
  7651.  0134 C3             482       code    ends
  7652.                      483
  7653.  ----                484
  7654.                      485
  7655.  
  7656.  ASSEMBLY COMPLETE,            NO WARNINGS,   NO ERRORS
  7657.  
  7658.  
  7659.  FPTAN and FPREM
  7660.  These trigonometric functions use the FPTAN instruction of the NPX. FPTAN
  7661.  requires that the angle argument be between 0 and π/4 radians, 0 to 45
  7662.  degrees. The FPREM instruction is used to reduce the argument down to this
  7663.  range. The low three quotient bits set by FPREM identify which octant the
  7664.  original angle was in.
  7665.  
  7666.  One FPREM instruction iteration can reduce angles of 10^(18) radians or less
  7667.  in magnitude to π/4! Larger values can be reduced, but the meaning of the
  7668.  result is questionable, because any errors in the least significant bits of
  7669.  that value represent changes of 45 degrees or more in the reduced angle.
  7670.  
  7671.  
  7672.  Cosine Uses Sine Code
  7673.  To save code space, the cosine function uses most of the sine function
  7674.  code. The relation sin (│A│ + π/2) = cos(A) is used to convert the
  7675.  cosine argument into a sine argument. Adding π/2 to the angle is performed
  7676.  by adding 010{2} to the FPREM quotient bits identifying the argument's
  7677.  octant.
  7678.  
  7679.  It would be very inaccurate to add π/2 to the cosine argument if it was
  7680.  very much differentfrom π/2.
  7681.  
  7682.  Depending on which octant the argument falls in, a different relation will
  7683.  be used in the sine and tangent functions. The program listings show which
  7684.  relations are used.
  7685.  
  7686.  For the tangent function, the ratio produced by FPTAN will be directly
  7687.  evaluated. The sine function will use either a sine or cosine relation
  7688.  depending on which octant the angle fell into. On exit, these functions will
  7689.  normally leave a divide instruction in progress to maintain concurrency.
  7690.  
  7691.  If the input angles are of a restricted range, such as from 0 to 45
  7692.  degrees, then considerable optimization is possible since full angle
  7693.  reduction and octant identification is not necessary.
  7694.  
  7695.  All three functions begin by looking at the value given to them. Not a
  7696.  Number (NaN), infinity, or empty registers must be specially treated.
  7697.  Unnormals need to be converted to normal values before the FPTAN instruction
  7698.  will work correctly. Denormals will be converted to very small unnormals
  7699.  that do work correctly for the FPTAN instruction. The sign of the angle is
  7700.  saved to control the sign of the result.
  7701.  
  7702.  Within the functions, close attention was paid to maintain concurrent
  7703.  execution of the 80287 and host. The concurrent execution will effectively
  7704.  hide the execution time of the decision logic used in the program.
  7705.  
  7706.  
  7707.  Appendix A  Machine Instruction Encoding and Decoding
  7708.  
  7709.  ───────────────────────────────────────────────────────────────────────────
  7710.  
  7711.  Machine instructions for the 80287 come in one of five different forms as
  7712.  shown in table A-1. In all cases, the instructions are at least two bytes
  7713.  long and begin with the bit pattern 11011B, which identifies the ESCAPE
  7714.  class of instructions. Instructions that reference memory operands are
  7715.  encoded much like similar CPU instructions, because all of the CPU
  7716.  memory-addressing modes may be used with ESCAPE instructions.
  7717.  
  7718.  Note that several of the processor control instructions (see table 2-11 in
  7719.  Chapter Two) may be preceded by an assembler-generated CPU WAIT instruction
  7720.  (encoding: 10011011B) if they are programmed using the WAIT form of their
  7721.  mnemonics. The ASM286 assembler inserts a WAIT instruction only before these
  7722.  specific processor control instructions──all of the numeric instructions are
  7723.  automatically synchronized by the 80286 CPU and an explicit WAIT
  7724.  instruction, though allowed, is not necessary.
  7725.  
  7726.  Table A-2 lists all 80287 machine instructions in binary sequence. This
  7727.  table may be used to "disassemble" instructions in unformatted memory dumps
  7728.  or instructions monitored from the data bus. Users writing exception
  7729.  handlers may also find this information useful to identify the offending
  7730.  instruction.
  7731.  
  7732.  
  7733.  Table A-1. 80287 Instruction Encoding
  7734.  
  7735.    ┌───────────────────────┬─────────────────────────────┬───────────────────┐
  7736.    │ Lower-Addressed Byte  │     Higher-Addressed Byte   │  0, 1, or 2 bytes │
  7737.    ├───────────────┬───────┼───┬───────┬───┬─────┬───────┼───────────────────┤
  7738.  1│ 1  1  0  1  1 │ OP-A  │ 1 │  MOD  │ 1 │OP-B │  R/M  │   DISPLACEMENT    │
  7739.    ├───────────────┼───────┼───┼───────┼───┴─────┼───────┼───────────────────┤
  7740.  2│ 1  1  0  1  1 │FORMAT │OP-A  MOD  │  OP-B   │  R/M  │   DISPLACEMENT    │
  7741.    ├───────────────┼───┬───┼───┼───┬───┼─────────┼───────┼───────────────────┘
  7742.  3│ 1  1  0  1  1 │ R │ P │OP-A 1 │ 1 │  OP-B   │  REG  │
  7743.    ├───────────────┼───┼───┼───┼───┼───┼───┬─────┴───────┤
  7744.  4│ 1  1  0  1  1 │ 0 │ 0 │ 1 │ 1 │ 1 │ 1 │     OP      │
  7745.    ├───────────────┼───┼───┼───┼───┼───┼───┼─────────────┤
  7746.  5│ 1  1  0  1  1 │ 0 │ 1 │ 1 │ 1 │ 1 │ 1 │     OP      │
  7747.    └───────────────┴───┴───┴───┴───┴───┴───┴─────────────┘
  7748.      7  6  5  4  3   2   1   0   7   6   5   4  3  2  1  0
  7749.  
  7750.  ───────────────────────────────────────────────────────────────────────────
  7751.  NOTES
  7752.  
  7753.    OP, OP-A, OP-B: Instruction opcode, possibly split into two fields.
  7754.  
  7755.    MOD: Same as 80286 CPU mode field.
  7756.  
  7757.    R/M: Same as 80286 CPU register/memory field.
  7758.  
  7759.    FORMAT: Defines memory operand
  7760.      00 = short real
  7761.      01 = short integer
  7762.      10 = long real
  7763.      11 = word integer
  7764.  
  7765.    R: 0 = return result to stack top
  7766.       1 = return result to other register
  7767.  
  7768.    P: 0 = do not pop stack
  7769.       1 = pop stack after operation
  7770.  
  7771.    REG: register stack element
  7772.     000 = stack top
  7773.     001 = next on stack
  7774.     010 = third stack element, etc.
  7775.  ───────────────────────────────────────────────────────────────────────────
  7776.  
  7777.  
  7778.  Table A-2. Machine Instruction Decoding Guide
  7779.  
  7780. ╓┌─────────────────┌────────────┌──────────────────────┌─────────────────────
  7781.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7782.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7783.  
  7784.  D8   1101  1000   MOD00  0R/M  (disp-lo),(disp-hi)    FADD     short-real
  7785.  D8   1101  1000   MOD00  1R/M  (disp-lo),(disp-hi)    FMUL     short-real
  7786.  D8   1101  1000   MOD01  0R/M  (disp-lo),(disp-hi)    FCOM     short-real
  7787.  D8   1101  1000   MOD01  1R/M  (disp-lo),(disp-hi)    FCOMP    short-real
  7788.  D8   1101  1000   MOD10  0R/M  (disp-lo),(disp-hi)    FSUB     short-real
  7789.  D8   1101  1000   MOD10  1R/M  (disp-lo),(disp-hi)    FSUBR    short-real
  7790.  D8   1101  1000   MOD11  0R/M  (disp-lo),(disp-hi)    FDIV     short-real
  7791.  D8   1101  1000   MOD11  1R/M  (disp-lo),(disp-hi)    FDIVR    short-real
  7792.  D8   1101  1000   1100   0REG                         FADD     ST,ST(i)
  7793.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7794.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7795. D8   1101  1000   1100   0REG                         FADD     ST,ST(i)
  7796.  D8   1101  1000   1100   1REG                         FMUL     ST,ST(i)
  7797.  D8   1101  1000   1101   0REG                         FCOM     ST(i)
  7798.  D8   1101  1000   1101   1REG                         FCOMP    ST(i)
  7799.  D8   1101  1000   1110   0REG                         FSUB     ST,ST(i)
  7800.  D8   1101  1000   1110   1REG                         FSUBR    ST,ST(i)
  7801.  D8   1101  1000   1111   0REG                         FDIV     ST,ST(i)
  7802.  D8   1101  1000   1111   1REG                         FDIVR    ST,ST(i)
  7803.  D9   1101  1001   MOD00  0R/M  (disp-lo),(disp-hi)    FLD      short-real
  7804.  D9   1101  1001   MOD00  1R/M                         reserved
  7805.  D9   1101  1001   MOD01  0R/M  (disp-lo),(disp-hi)    FST      short-real
  7806.  D9   1101  1001   MOD01  1R/M  (disp-lo),(disp-hi)    FSTP     short-real
  7807.  D9   1101  1001   MOD10  0R/M  (disp-lo),(disp-hi)    FLDENV   14-bytes
  7808.  D9   1101  1001   MOD10  1R/M  (disp-lo),(disp-hi)    FLDCW    2-bytes
  7809.  D9   1101  1001   MOD11  0R/M  (disp-lo),(disp-hi)    FSTENV   14-bytes
  7810.  D9   1101  1001   MOD11  1R/M  (disp-lo),(disp-hi)    FSTCW    2-bytes
  7811.  D9   1101  1001   1100   0REG                         FLD      ST(i)
  7812.  D9   1101  1001   1100   1REG                         FXCH     ST(i)
  7813.  D9   1101  1001   1101   0000                         FNOP
  7814.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7815.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7816. D9   1101  1001   1101   0000                         FNOP
  7817.  D9   1101  1001   1101   0001                         reserved
  7818.  D9   1101  1001   1101   001-                         reserved
  7819.  D9   1101  1001   1101   01--                         reserved
  7820.  D9   1101  1001   1101   1REG                         (1)
  7821.  
  7822.  
  7823.  D9   1101  1001   1110   0000                         FCHS
  7824.  D9   1101  1001   1110   0001                         FABS
  7825.  D9   1101  1001   1110   001-                         reserved
  7826.  D9   1101  1001   1110   0100                         FTST
  7827.  D9   1101  1001   1110   0101                         FXAM
  7828.  D9   1101  1001   1110   011-                         reserved
  7829.  D9   1101  1001   1110   1000                         FLD1
  7830.  D9   1101  1001   1110   1001                         FLDL2T
  7831.  D9   1101  1001   1110   1010                         FLDL2E
  7832.  D9   1101  1001   1110   1011                         FLDPI
  7833.  D9   1101  1001   1110   1100                         FLDLG2
  7834.  D9   1101  1001   1110   1101                         FLDLN2
  7835.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7836.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7837. D9   1101  1001   1110   1101                         FLDLN2
  7838.  D9   1101  1001   1110   1110                         FLDZ
  7839.  D9   1101  1001   1110   1111                         reserved
  7840.  D9   1101  1001   1111   0000                         F2XM1
  7841.  D9   1101  1001   1111   0001                         FYL2X
  7842.  D9   1101  1001   1111   0010                         FPTAN
  7843.  D9   1101  1001   1111   0011                         FPATAN
  7844.  D9   1101  1001   1111   0100                         FXTRACT
  7845.  D9   1101  1001   1111   0101                         reserved
  7846.  D9   1101  1001   1111   0110                         FDECSTP
  7847.  D9   1101  1001   1111   0111                         FINCSTP
  7848.  D9   1101  1001   1111   1000                         FPREM
  7849.  D9   1101  1001   1111   1001                         FYL2XP1
  7850.  D9   1101  1001   1111   1010                         FSQRT
  7851.  D9   1101  1001   1111   1011                         reserved
  7852.  D9   1101  1001   1111   1100                         FRNDINT
  7853.  D9   1101  1001   1111   1101                         FSCALE
  7854.  D9   1101  1001   1111   111-                         reserved
  7855.  DA   1101  1010   MOD00  0R/M  (disp-lo),(disp-hi)    FIADD    short-integer
  7856.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7857.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7858. DA   1101  1010   MOD00  0R/M  (disp-lo),(disp-hi)    FIADD    short-integer
  7859.  DA   1101  1010   MOD00  1R/M  (disp-lo),(disp-hi)    FIMUL    short-integer
  7860.  DA   1101  1010   MOD01  0R/M  (disp-lo),(disp-hi)    FICOM    short-integer
  7861.  DA   1101  1010   MOD01  1R/M  (disp-lo),(disp-hi)    FICOMP   short-integer
  7862.  DA   1101  1010   MOD10  0R/M  (disp-lo),(disp-hi)    FISUB    short-integer
  7863.  DA   1101  1010   MOD10  1R/M  (disp-lo),(disp-hi)    FISUBR   short-integer
  7864.  DA   1101  1010   MOD11  0R/M  (disp-lo),(disp-hi)    FIDIV    short-integer
  7865.  DA   1101  1010   MOD11  1R/M  (disp-lo),(disp-hi)    FIDIVR   short-integer
  7866.  DA   1101  1010   11--  ----                          reserved
  7867.  DB   1101  1011   MOD00  0R/M  (disp-lo),(disp-hi)    FILD     short-integer
  7868.  DB   1101  1011   MOD00  1R/M  (disp-lo),(disp-hi)    reserved
  7869.  DB   1101  1011   MOD01  0R/M  (disp-lo),(disp-hi)    FIST     short-integer
  7870.  DB   1101  1011   MOD01  1R/M  (disp-lo),(disp-hi)    FISTP    short-integer
  7871.  DB   1101  1011   MOD10  0R/M  (disp-lo),(disp-hi)    reserved
  7872.  DB   1101  1011   MOD10  1R/M  (disp-lo),(disp-hi)    FLD      temp-real
  7873.  DB   1101  1011   MOD11  0R/M  (disp-lo),(disp-hi)    reserved
  7874.  DB   1101  1011   MOD11  1R/M  (disp-lo),(disp-hi)    FSTP     temp-real
  7875.  DB   1101  1011   110-   ----                         reserved
  7876.  DB   1101  1011   1110   0000                         reserved (8087 FENI)
  7877.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7878.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7879. DB   1101  1011   1110   0000                         reserved (8087 FENI)
  7880.  DB   1101  1011   1110   0001                         reserved (8087 FDISI)
  7881.  DB   1101  1011   1110   0010                         FCLEX
  7882.  DB   1101  1011   1110   0011                         FINIT
  7883.  DB   1101  1011   1110   0100                         FSETPM
  7884.  DB   1101  1011   1110   1---                         reserved
  7885.  DB   1101  1011   1111   ----                         reserved
  7886.  DC   1101  1100   MOD00  0R/M  (disp-lo),(disp-hi)    FADD     long-real
  7887.  DC   1101  1100   MOD00  1R/M  (disp-lo),(disp-hi)    FMUL     long-real
  7888.  DC   1101  1100   MOD01  0R/M  (disp-lo),(disp-hi)    FCOM     long-real
  7889.  DC   1101  1100   MOD01  1R/M  (disp-lo),(disp-hi)    FCOMP    long-real
  7890.  DC   1101  1100   MOD10  0R/M  (disp-lo),(disp-hi)    FSUB     long-real
  7891.  DC   1101  1100   MOD10  1R/M  (disp-lo),(disp-hi)    FSUBR    long-real
  7892.  DC   1101  1100   MOD11  0R/M  (disp-lo),(disp-hi)    FDIV     long-real
  7893.  DC   1101  1100   MOD11  1R/M  (disp-lo),(disp-hi)    FDIVR    long-real
  7894.  DC   1101  1100   1100   0REG                         FADD     ST(i),ST
  7895.  DC   1101  1100   1100   1REG                         FMUL     ST(i),ST
  7896.  DC   1101  1100   1101   0REG                         (2)
  7897.  
  7898.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7899.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7900. 
  7901.  
  7902.  DC   1101  1100   1101   1REG                         (3)
  7903.  
  7904.  
  7905.  DC   1101  1100   1110   0REG                         FSUB     ST(i),ST
  7906.  DC   1101  1100   1110   1REG                         FSUBR    ST(i),ST
  7907.  DC   1101  1100   1111   0REG                         FDIV     ST(i),ST
  7908.  DC   1101  1100   1111   1REG                         FDIVR    ST(i),ST
  7909.  DD   1101  1101   MOD00  0R/M  (disp-lo),(disp-hi)    FLD      long-real
  7910.  DD   1101  1101   MOD00  1R/M                         reserved
  7911.  DD   1101  1101   MOD01  0R/M  (disp-lo),(disp-hi)    FST      long-real
  7912.  DD   1101  1101   MOD01  1R/M  (disp-lo),(disp-hi)    FSTP     long-real
  7913.  DD   1101  1101   MOD10  0R/M  (disp-lo),(disp-hi)    FRSTOR   94-bytes
  7914.  DD   1101  1101   MOD10  1R/M  (disp-lo),(disp-hi)    reserved
  7915.  DD   1101  1101   MOD11  0R/M  (disp-lo),(disp-hi)    FSAVE    94-bytes
  7916.  DD   1101  1101   MOD11  1R/M  (disp-lo),(disp-hi)    FSTSW    2-bytes
  7917.  DD   1101  1101   1100   0REG                         FFREE    ST(i)
  7918.  DD   1101  1101   1100   1REG                         (4)
  7919.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7920.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7921. DD   1101  1101   1100   1REG                         (4)
  7922.  
  7923.  
  7924.  DD   1101  1101   1101   0REG                         FST      ST(i)
  7925.  DD   1101  1101   1101   1REG                         FSTP     ST(i)
  7926.  DD   1101  1101   111-   ----                         reserved
  7927.  DE   1101  1110   MOD00  0R/M  (disp-lo),(disp-hi)    FIADD    word-integer
  7928.  DE   1101  1110   MOD00  1R/M  (disp-lo),(disp-hi)    FIMUL    word-integer
  7929.  DE   1101  1110   MOD01  0R/M  (disp-lo),(disp-hi)    FICOM    word-integer
  7930.  DE   1101  1110   MOD01  1R/M  (disp-lo),(disp-hi)    FICOMP   word-integer
  7931.  DE   1101  1110   MOD10  0R/M  (disp-lo),(disp-hi)    FISUB    word-integer
  7932.  DE   1101  1110   MOD10  1R/M  (disp-lo),(disp-hi)    FISUBR   word-integer
  7933.  DE   1101  1110   MOD11  0R/M  (disp-lo),(disp-hi)    FIDIV    word-integer
  7934.  DE   1101  1110   MOD11  1R/M  (disp-lo),(disp-hi)    FIDIVR   word-integer
  7935.  DE   1101  1110   1100   0REG                         FADDP    ST(i),ST
  7936.  DE   1101  1110   1100   1REG                         FMULP    ST(i),ST
  7937.  DE   1101  1110   1101   0---                         (5)
  7938.  
  7939.  
  7940.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7941.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7942. 
  7943.  DE   1101  1110   1101   1000                         reserved
  7944.  DE   1101  1110   1101   1001                         FCOMPP
  7945.  DE   1101  1110   1101   101-                         reserved
  7946.  DE   1101  1110   1101   11--                         reserved
  7947.  DE   1101  1110   1110   0REG                         FSUBP    ST(i),ST
  7948.  DE   1101  1110   1110   1REG                         FSUBRP   ST(i),ST
  7949.  DE   1101  1110   1111   0REG                         FDIVP    ST(i),ST
  7950.  DE   1101  1110   1111   1REG                         FDIVRP   ST(i),ST
  7951.  DF   1101  1111   MOD00  0R/M  (disp-lo),(disp-hi)    FILD     word-integer
  7952.  DF   1101  1111   MOD00  1R/M  (disp-lo),(disp-hi)    reserved
  7953.  DF   1101  1111   MOD01  0R/M  (disp-lo),(disp-hi)    FIST     word-integer
  7954.  DE   1101  1110   MOD01  1R/M  (disp-lo),(disp-hi)    FISTP    word-integer
  7955.  DF   1101  1111   MOD10  0R/M  (disp-lo),(disp-hi)    FBLD     packed-decimal
  7956.  DF   1101  1111   MOD10  1R/M  (disp-lo),(disp-hi)    FILD     long-integer
  7957.  DF   1101  1111   MOD11  0R/M  (disp-lo),(disp-hi)    FBSTP    packed-decimal
  7958.  DF   1101  1111   MOD11  1R/M  (disp-lo),(disp-hi)    FISTP    long-integer
  7959.  DF   1101  1111   1100   0REG                         (6)
  7960.  
  7961.  ┌─1st  Byte──┐                                        ASM286 Instruction
  7962.  Hex     Binary     2nd Byte        Bytes 3, 4               Format
  7963. 
  7964.  
  7965.  DF   1101  1111   1100   1REG                         (7)
  7966.  
  7967.  
  7968.  DF   1101  1111   1101   0REG                         (8)
  7969.  
  7970.  
  7971.  DF   1101  1111   1101   1REG                         (9)
  7972.  
  7973.  
  7974.  DF   1101  1111   1110   000                          FSTSW AX
  7975.  DF   1101  1111   1111   XXX                          reserved
  7976.  
  7977.  
  7978.  Appendix B  Compatibility Between the 80287 NPX and the 8087
  7979.  
  7980.  ───────────────────────────────────────────────────────────────────────────
  7981.  
  7982.  The 80286/80287 operating in Real-Address mode will execute 8087 programs
  7983.  without major modification. However, because of differences in the handling
  7984.  of numeric exceptions by the 80287 NPX and the 8087 NPX, exception-handling
  7985.  routines may need to be changed.
  7986.  
  7987.  This appendix summarizes the differences between the 80287 NPX and the 8087
  7988.  NPX, and provides details showing how 8087 programs can be ported to the
  7989.  80287.
  7990.  
  7991.    1.  The 80287 signals exceptions through a dedicated ERROR line to the
  7992.        80286. The 80287 error signal does not pass through an interrupt
  7993.        controller (the 8087 INT signal does). Therefore, any
  7994.        interrupt-controller-oriented instructions in numeric exception
  7995.        handlers for the 8087 should be deleted.
  7996.  
  7997.    2.  The 8087 instructions FENI/FNENI and FDISI/FNDISI perform no useful
  7998.        function in the 80287. If the 80287 encounters one of these opcodes in
  7999.        its instruction stream, the instruction will effectively be ignored──
  8000.        none of the 80287 internal states will be updated. While 8087 code
  8001.        containing these instructions may be executed on the 80287, it is
  8002.        unlikely that the exception-handling routines containing these
  8003.        instructions will be completely portable to the 80287.
  8004.  
  8005.    3.  Interrupt vector 16 must point to the numeric exception handling
  8006.        routine.
  8007.  
  8008.    4.  The ESC instruction address saved in the 80287 includes any leading
  8009.        prefixes before the ESC opcode. The corresponding address saved in the
  8010.        8087 does not include leading prefixes.
  8011.  
  8012.    5.  In Protected-Address mode, the format of the 80287's saved
  8013.        instruction and address pointers is different than for the 8087. The
  8014.        instruction opcode is not saved in Protected mode──exception handlers
  8015.        will have to retrieve the opcode from memory if needed.
  8016.  
  8017.    6.  Interrupt 7 will occur in the 80286 when executing ESC instructions
  8018.        with either TS (task switched) or EM (emulation) of the 80286 MSW set
  8019.        (TS = 1 or EM = 1). If TS is set, then a WAIT instruction will also
  8020.        cause interrupt 7. An exception handler should be included in 80287
  8021.        code to handle these situations.
  8022.  
  8023.    7.  Interrupt 9 will occur if the second or subsequent words of a
  8024.        floating-point operand fall outside a segment's size. Interrupt 13
  8025.        will occur if the starting address of a numeric operand falls outside
  8026.        a segment's size. An exception handler should be included in 80287
  8027.        code to report these programming errors.
  8028.  
  8029.    8.  Except for the processor control instructions, all of the 80287
  8030.        numeric instructions are automatically synchronized by the 80286 CPU──
  8031.        the 80286 automatically tests the BUSY line from the 80287 to ensure
  8032.        that the 80287 has completed its previous instruction before executing
  8033.        the next ESC instruction. No explicit WAIT instructions are required
  8034.        to assure this synchronization. For the 8087 used with 8086 and 8088
  8035.        processors, explicit WAITs are required before each numeric
  8036.        instruction to ensure synchronization. Although 8087 programs having
  8037.        explicit WAIT instructions will execute perfectly on the 80287 without
  8038.        reassembly, these WAIT instructions are unnecessary.
  8039.  
  8040.    9.  Since the 80287 does not require WAIT instructions before each
  8041.        numeric instruction, the ASM286 assembler does not automatically
  8042.        generate these WAIT instructions. The ASM86 assembler, however,
  8043.        automatically precedes every ESC instruction with a WAIT instruction.
  8044.        Although numeric routines generated using the ASM86 assembler will
  8045.        generally execute correctly on the 80286/20, reassembly using ASM286
  8046.        may result in a more compact code image.
  8047.  
  8048.        The processor control instructions for the 80287 may be coded using
  8049.        either a WAIT or No-WAIT form of mnemonic. The WAIT forms of these
  8050.        instructions cause ASM286 to precede the ESC instruction with a
  8051.        CPU WAIT instruction, in the identical manner as does ASM86.
  8052.  
  8053.    10. A recommended way to detect the presence of an 80287 in an 80286
  8054.        system (or an 8087 in an 8086 system) is shown below. It assumes that
  8055.        the sytem hardware causes the data bus to be high if no 80287 is
  8056.        present to drive the data lines during the FSTSW (Store 80287 Status
  8057.        Word) instruction.
  8058.  
  8059.        FND_287: FNINIT            ; initialize numeric processor.
  8060.                 FSTSTW  STAT      ; store status word into location
  8061.                                   ; STAT.
  8062.                 MOV     AX,STAT
  8063.                 OR      AL,AL     ; Zero Flag reflects result of OR.
  8064.                 JZ      GOT_287   ; Zero in AL means 80287 is present.
  8065.        ;
  8066.        ;    No 80287 Present
  8067.        ;
  8068.                 SMSW    AX
  8069.                 OR      AX,0004H  ; set EM bit in Machine Status Word.
  8070.                 LMSW    AX        ; to enable software emulation of 287.
  8071.                 JMP     CONTINUE
  8072.        ;
  8073.        ;    80287 is present in system
  8074.        ;
  8075.        GOT_287: SMSW    AX
  8076.                 OR      AX,0002H  ; set MP bit in Machine Status Word
  8077.                 LMSW    AX        ; to permit normal 80287 operation
  8078.        ;
  8079.        ;    Continue . . .
  8080.        ;
  8081.        CONTINUE:                  ; and off we go
  8082.  
  8083.        An 80286/80287 design must place a pullup resistor on one of the low
  8084.        eight data bus bits of the 80286 to be sure it is read as a high when
  8085.        no 80287 is present.
  8086.  
  8087.  
  8088.  Appencix C  Implementing the IEEE P754 Standard
  8089.  
  8090.  ───────────────────────────────────────────────────────────────────────────
  8091.  
  8092.  The 80287 NPX and standard support library software, provides an
  8093.  implementation of the IEEE "A Proposed Standard for Binary Floating-Point
  8094.  Arithmetic," Draft 10.0, Task P754, of December 2, 1982. The 80287 Support
  8095.  Library, described in 80287 Support Library Reference Manual, Order Number
  8096.  122129, is an example of such a support library.
  8097.  
  8098.  This appendix describes the relationship between the 80287 NPX and the IEEE
  8099.  Standard. Where the Standard has options, Intel's choices in implementing
  8100.  the 80287 are described. Where portions of the Standard are implemented
  8101.  through software, this appendix indicates which modules of the 80287 Support
  8102.  Library implement the Standard. Where special software in addition to the
  8103.  Support Library may be required by your application, this appendix indicates
  8104.  how to write this software.
  8105.  
  8106.  This appendix contains many terms with precise technical meanings,
  8107.  specified in the 754 Standard. Where these terms are used, they have been
  8108.  capitalized to emphasize the precision of their meanings. The Glossary
  8109.  provides the definitions for all capitalized phrases in this appendix.
  8110.  
  8111.  
  8112.  Options Implemented in the 80287
  8113.  The 80287 SHORT_REAL and LONG_REAL formats conform precisely to the
  8114.  Standard's Single and Double Floating-Point Numbers, respectively. The 80287
  8115.  TEMP_REAL format is the same as the Standard's Double Extended format. The
  8116.  Standard allows a choice of Bias in representing the exponent; the 80287
  8117.  uses the Bias 16383 decimal.
  8118.  
  8119.  For the Double Extended format, the Standard contains an option for the
  8120.  meaning of the minimum exponent combined with a nonzero significand. The
  8121.  Bias for this special case can be either 16383, as in all the other cases,
  8122.  or 16382, making the smallest exponent equivalent to the second-smallest
  8123.  exponent. The 80287 uses the Bias 16382 for this case. This allows the 80287
  8124.  to distinguish between Denormal numbers (integer part is zero, fraction is
  8125.  nonzero, Biased exponent is 0) and Unnormal numbers of the same value (same
  8126.  as the denormal except the Biased Exponent is 1).
  8127.  
  8128.  The Standard allows flexibility in specifying which NaNs are trapping and
  8129.  which are nontrapping. The EH287.LIB module of the 80287 Support Library
  8130.  provides a software implementation of nontrapping NaNs, and defines one
  8131.  distinction between trapping and nontrapping NaNs: If the most significant
  8132.  bit of the fractional part of a NaN is 1, the NaN is nontrapping. If it is
  8133.  0, the NaN is trapping.
  8134.  
  8135.  When a masked Invalid Operation error involves two NaN inputs, the Standard
  8136.  allows flexibility in choosing which NaN is output. The 80287 selects the
  8137.  NaN whose absolute value is greatest.
  8138.  
  8139.  
  8140.  Areas of the Standard Implemented in Software
  8141.  There are five areas of the Standard that are not implemented directly in
  8142.  the 80287 hardware; these areas are instead implemented in software as part
  8143.  of the 80287 Support Library.
  8144.  
  8145.    1.  The Standard requires that a Normalizing Mode be provided, in which
  8146.        any nonnormal operands to functions are automatically normalized
  8147.        before the function is performed. The NPX provides a "Denormal
  8148.        operand" exception for this case, allowing the exception handler
  8149.        the opportunity to perform the normalization specified by the
  8150.        Standard. The Denormal operand exception handler provided by
  8151.        EH287.LIB implements the Standard's Normalizing Mode completely for
  8152.        Single- and Double-precision arguments. Normalizing mode for Double
  8153.        Extended operands is implemented in EH287.LIB with one non-Standard
  8154.        feature, discussed in the next section.
  8155.  
  8156.    2.  The Standard specifies that in comparing two operands whose
  8157.        relationship is "unordered," the equality test yield an answer of
  8158.        FALSE, with no errors or exceptions. The 80287 FCOM and FTST
  8159.        instructions themselves issue an Invalid Operation exception in this
  8160.        case. The error handler EH287.LIB filters out this Invalid Operation
  8161.        error using the following convention: Whenever an FCOM or FTST
  8162.        instruction is followed by a MOV AX,AX instruction (8BC0 Hex), and
  8163.        neither argument is a trapping NaN, the error handler will assume that
  8164.        a Standard equality comparison was intended, and return the correct
  8165.        answer with the Invalid Operation exception flag erased. Note that the
  8166.        Invalid Operation exception must be unmasked for this action to
  8167.        occur.
  8168.  
  8169.    3.  The Standard requires that two kinds of NaN's be provided: trapping
  8170.        and nontrapping. Nontrapping NaNs will not cause further Invalid
  8171.        Operation errors when they occur as operands to calculations. The NPX
  8172.        hardware directly supports only trapping NaN's; the EH287.LIB
  8173.        software implements nontrapping NaNs by returning the correct answer
  8174.        with the Invalid Operation exception flag erased. Note that the
  8175.        Invalid Operation exception must be unmasked for this action to occur.
  8176.  
  8177.    4.  The Standard requires that all functions that convert real numbers to
  8178.        integer formats automatically normalize the inputs if necessary. The
  8179.        integer conversion functions contained in CEL287.LIB fully meet the
  8180.        Standard in this respect; the 80287 FIST instruction alone does not
  8181.        perform this normalization.
  8182.  
  8183.    5.  The Standard specifies the remainder function which is provided by
  8184.        mqerRMD in CEL287.LIB. The 80287 FPREM instruction returns answers
  8185.        within a different range.
  8186.  
  8187.  
  8188.  Additional Software to Meet the Standard
  8189.  There are two cases in which additional software is required in conjunction
  8190.  with the 80287 Support Library in order to meet the standard. The 80287
  8191.  Support Library does not provide this software in the interest of saving
  8192.  space and because the vast majority of applications will never encounter
  8193.  these cases.
  8194.  
  8195.    1.  When the Invalid Operation exception is masked, Nontrapping NaNs are
  8196.        not implemented fully. Likewise, the Standard's equality test for
  8197.        "unordered" operands is not implemented when the Invalid Operation
  8198.        exception is masked. Programmers can simulate the Standard notion of
  8199.        a masked Invalid Operation exception by unmasking the 80287 Invalid
  8200.        Operation exception, and providing an Invalid Operation exception
  8201.        handler that supports nontrapping NaNs and the equality test, but
  8202.        otherwise acts just as if the Invalid Operation exception were
  8203.        masked. The 80287 Support Library Reference Manual contains examples
  8204.        for programming this handler in both ASM286 andPL/M-286.
  8205.  
  8206.    2.  In Normalizing Mode, Denormal operands in the TEMP_REAL format are
  8207.        converted to 0 by EH287.LIB, giving sharp Underflow to 0. The Standard
  8208.        specifies that the operation be performed on the real numbers
  8209.        represented by the denormals, giving gradual underflow. To correctly
  8210.        perform such arithmetic while in Normalizing Mode, programmers would
  8211.        have to normalize the operands into a format identical to TEMP_REAL
  8212.        except for two extra exponent bits, then perform the operation on
  8213.        those numbers. Thus, software must be written to handle the 17-bit
  8214.        exponent explicitly.
  8215.  
  8216.  In designing the EH287.LIB, it was felt that it would be a disadvantage to
  8217.  most users to increase the size of the Normalizing routine by the amount
  8218.  necessary to provide this expanded arithmetic. Because the TEMP_REAL
  8219.  exponent field is so much larger than the LONG_REAL exponent field, it is
  8220.  extremely unlikely that TEMP_REAL underflow will be encountered in most
  8221.  applications.
  8222.  
  8223.  If meeting the Standard is a more important criterion for your application
  8224.  than the choice between Normalizing and warning modes, then you can select
  8225.  warning mode (Denormal operand exceptions masked), which fully meets the
  8226.  Standard.
  8227.  
  8228.  If you do wish to implement the Normalization of denormal operands in
  8229.  TEMP_REAL format using extra exponent bits, the list below indicates some
  8230.  useful pointers about handling Denormal operand exceptions:
  8231.  
  8232.    1.  TEMP_REAL numbers are considered Denormal by the NPX whenever the
  8233.        Biased Exponent is 0 (minimum exponent). This is true even if the
  8234.        explicit integer bit of the significand is 1. Such numbers can occur
  8235.        as the result of Underflow.
  8236.  
  8237.    2.  The 80287 FLD instruction can cause a Denormal Operand error if a
  8238.        number is being loaded from memory. It will not cause this exception
  8239.        if the number is being loaded from elsewhere in the 80287 stack.
  8240.  
  8241.    3.  The 80287 FCOM and FTST instructions will cause a Denormal Operand
  8242.        exception for unnormal operands as well as for denormal operands.
  8243.  
  8244.    4.  In cases where both the Denormal Operand and Invalid Operation
  8245.        exceptions occur, you will want to know which is signalled first. When
  8246.        a comparison instruction operates between a nonexistent stack element
  8247.        and a denormal number in 80286 memory, the D and I exceptions are
  8248.        issued simultaneously. In all other situations, a Denormal Operand
  8249.        exception takes precedence over a nonstack Invalid operation
  8250.        exception, while a stack Invalid Operation exception takes precedence
  8251.        over a Denormal Operand exception.
  8252.  
  8253.  
  8254.  Glossary of 80287 and Floating-Point Terminology
  8255.  
  8256.  ───────────────────────────────────────────────────────────────────────────
  8257.  
  8258.  This glossary defines many terms that have precise technical meanings as
  8259.  specified in the IEEE 754 Standard. Where these terms are used, they have
  8260.  been capitalized to emphasize the precision of their meanings.
  8261.  
  8262.  Affine Mode:
  8263.    a state of the 80287, selected in the 80287 Control Word, in which
  8264.    infinities are treated as having a sign. Thus, the values +INFINITY and
  8265.    -INFINITY are considered different; they can be compared with finite
  8266.    numbers and with each other.
  8267.  
  8268.  Base:
  8269.    (1) a term used in logarithms and exponentials. In both contexts, it is
  8270.    a number that is being raised to a power. The two equations (y = log
  8271.    base b of x) and (b^(y) = x) are the same.
  8272.  
  8273.  Base:
  8274.    (2) a number that defines the representation being used for a string of
  8275.    digits. Base 2 is the binary representation; Base 10 is the decimal
  8276.    representation; Base 16 is the hexadecimal representation. In each case,
  8277.    the Base is the factor of increased significance for each succeeding
  8278.    digit (working up from the bottom).
  8279.  
  8280.  Bias:
  8281.    the difference between the unsigned Integer that appears in the Exponent
  8282.    field of a Floating-Point Number and the true Exponent that it
  8283.    represents. To obtain the true Exponent, you must subtract the Bias from
  8284.    the given Exponent. For example, the Short Real format has a Bias of 127
  8285.    whenever the given Exponent is nonzero. If the 8-bit Exponent field
  8286.    contains 10000011, which is 131, the true Exponent is 131-127, or +4.
  8287.  
  8288.  Biased Exponent:
  8289.    the Exponent as it appears in a Floating-Point Number, interpreted as an
  8290.    unsigned, positive number. In the above example, 131 is the Biased
  8291.    Exponent.
  8292.  
  8293.  Binary Coded Decimal:
  8294.    a method of storing numbers that retains a base 10 representation. Each
  8295.    decimal digit occupies 4 full bits (one hexadecimal digit). The hex
  8296.    values A through F (1010 through 1111) are not used. The 80287 supports
  8297.    a Packed Decimal format that consists of 9 bytes of Binary Coded Decimal
  8298.    (18 decimal digits) and one sign byte.
  8299.  
  8300.  Binary Point:
  8301.    an entity just like a decimal point, except that it exists in binary
  8302.    numbers. Each binary digit to the right of the Binary Point is
  8303.    multiplied by an increasing negative power of two.
  8304.  
  8305.  C3──C0:
  8306.    the four "condition code" bits of the 80287 Status Word. These bits are
  8307.    set to certain values by the compare, test, examine, and remainder
  8308.    functions of the 80287.
  8309.  
  8310.  Characteristic:
  8311.    a term used for some non-Intel computers, meaning the Exponent field of
  8312.    a Floating-Point Number.
  8313.  
  8314.  Chop:
  8315.    to set the fractional part of a real number to zero, yielding the
  8316.    nearest integer in the direction of zero.
  8317.  
  8318.  Control Word:
  8319.    a 16-bit 80287 register that the user can set, to determine the modes of
  8320.    computation the 80287 will use, and the error interrupts that will be
  8321.    enabled.
  8322.  
  8323.  Denormal:
  8324.    a special form of Floating-Point Number, produced when an Underflow
  8325.    occurs. On the 80287, a Denormal is defined as a number with a Biased
  8326.    Exponent that is zero. By providing a Significand with leading zeros,
  8327.    the range of possible negative Exponents can be extended by the number
  8328.    of bits in the Significand. Each leading zero is a bit of lost accuracy,
  8329.    so the extended Exponent range is obtained by reducing significance.
  8330.  
  8331.  Double Extended:
  8332.    the Standard's term for the 80287 Temporary Real format, with more
  8333.    Exponent and Significand bits than the Double (Long Real) format, and an
  8334.    explicit Integer bit in the Significand.
  8335.  
  8336.  Double Floating Point Number:
  8337.    the Standard's term for the 80287's 64-bit Long Real format.
  8338.  
  8339.  Environment:
  8340.    the 14 bytes of 80287 registers affected by the FSTENV and FLDENV
  8341.    instructions. It encompasses the entire state of the 80287, except for
  8342.    the 8 Temporary Real numbers of the 80287 stack. Included are the
  8343.    Control Word, Status Word, Tag Word, and the instruction, opcode, and
  8344.    operand information provided by interrupts.
  8345.  
  8346.  Exception:
  8347.    any of the six error conditions (I, D, O, U, Z, P) signalled by the
  8348.    80287.
  8349.  
  8350.  Exponent:
  8351.    (1) any power that is raised by an exponential function. For example,
  8352.    the operand to the function mqerEXP is an Exponent. The Integer operand
  8353.    to mqerYI2 is an Exponent.
  8354.  
  8355.  Exponent:
  8356.    (2) the field of a Floating-Point Number that indicates the magnitude of
  8357.    the number. This would fall under the above more general definition (1),
  8358.    except that a Bias sometimes needs to be subtracted to obtain the
  8359.    correct power.
  8360.  
  8361.  Floating-Point Number:
  8362.    a sequence of data bytes that, when interpreted in a standardized way,
  8363.    represents a Real number. Floating-Point Numbers are more versatile than
  8364.    Integer representations in two ways. First, they include fractions.
  8365.    Second, their Exponent parts allow a much wider range of magnitude than
  8366.    possible with fixed-length Integer representations.
  8367.  
  8368.  Gradual Underflow:
  8369.    a method of handling the Underflow error condition that minimizes the
  8370.    loss of accuracy in the result. If there is a Denormal number that
  8371.    represents the correct result, that Denormal is returned. Thus, digits
  8372.    are lost only to the extent of denormalization. Most computers return
  8373.    zero when Underflow occurs, losing all significant digits.
  8374.  
  8375.  Implicit Integer Bit:
  8376.    a part of the Significand in the Short Real and Long Real formats that
  8377.    is not explicitly given. In these formats, the entire given Significand
  8378.    is considered to be to the right of the Binary Point. A single Implicit
  8379.    Integer Bit to the left of the Binary Point is always 1, except in one
  8380.    case. When the Exponent is the minimum (Biased Exponent is 0), the
  8381.    Implicit Integer Bit is 0.
  8382.  
  8383.  Indefinite:
  8384.    a special value that is returned by functions when the inputs are such
  8385.    that no other sensible answer is possible. For each Floating-Point
  8386.    format there exists one Nontrapping NaN that is designated as the
  8387.    Indefinite value. For binary Integer formats, the negative number
  8388.    furthest from zero is often considered the Indefinite value. For the
  8389.    80287 Packed Decimal format, the Indefinite value contains all 1's in
  8390.    the sign byte and the uppermost digits byte.
  8391.  
  8392.  Infinity:
  8393.    a value that has greater magnitude than any Integer or any Real number.
  8394.    The existence of Infinity is subject to heated philosophical debate.
  8395.    However, it is often useful to consider Infinity as another number,
  8396.    subject to special rules of arithmetic. All three Intel Floating-Point
  8397.    formats provide representations for +INFINITY and -INFINITY. They
  8398.    support two ways of dealing with Infinity: Projective (unsigned) and
  8399.    Affine (signed).
  8400.  
  8401.  Integer:
  8402.    a number (positive, negative, or zero) that is finite and has no
  8403.    fractional part. Integer can also mean the computer representation for
  8404.    such a number: a sequence of data bytes, interpreted in a standard way.
  8405.    It is perfectly reasonable for Integers to be represented in a
  8406.    Floating-Point format; this is what the 80287 does whenever an Integer is
  8407.    pushed onto the 80287 stack.
  8408.  
  8409.  Invalid Operation:
  8410.    the error condition for the 80287 that covers all cases not covered by
  8411.    other errors. Included are 80287 stack overflow and underflow, NaN
  8412.    inputs, illegal infinite inputs, out-of-range inputs, and illegal
  8413.    unnormal inputs.
  8414.  
  8415.  Long Integer:
  8416.    an Integer format supported by the 80287 that consists of a 64-bit Two's
  8417.    Complement quantity.
  8418.  
  8419.  Long Real:
  8420.    a Floating-Point Format supported by the 80287 that consists of a sign,
  8421.    an 11-bit Biased Exponent, an Implicit Integer Bit, and a 52-bit
  8422.    Significand──a total of 64 explicit bits.
  8423.  
  8424.  Mantissa:
  8425.    a term used for some non-Intel computers, meaning the Significand of a
  8426.    Floating-Point Number.
  8427.  
  8428.  Masked:
  8429.    a term that applies to each of the six 80287 Exceptions I,D,Z,O,U,P. An
  8430.    exception is Masked if a corresponding bit in the 80287 Control Word is
  8431.    set to 1. If an exception is Masked, the 80287 will not generate an
  8432.    interrupt when the error condition occurs; it will instead provide its
  8433.    own error recovery.
  8434.  
  8435.  NaN:
  8436.    an abbreviation for Not a Number; a Floating-Point quantity that does
  8437.    not represent any numeric or infinite quantity. NaNs should be returned
  8438.    by functions that encounter serious errors. If created during a sequence
  8439.    of calculations, they are transmitted to the final answer and can
  8440.    contain information about where the error occurred.
  8441.  
  8442.  Nontrapping NaN:
  8443.    a NaN in which the most significant bit of the fractional part of the
  8444.    Significand is 1. By convention, these NaNs can undergo certain
  8445.    operations without visible error. Nontrapping NaNs are implemented for
  8446.    the 80287 via the software in EH87.LIB.
  8447.  
  8448.  Normal:
  8449.    the representation of a number in a Floating-Point format in which the
  8450.    Significand has an Integer bit 1 (either explicit or Implicit).
  8451.  
  8452.  Normalizing Mode:
  8453.    a state in which nonnormal inputs are automatically converted to normal
  8454.    inputs whenever they are used in arithmetic. Normalizing Mode is
  8455.    implemented for the 80287 via the software in EH87.LIB.
  8456.  
  8457.  NPX:
  8458.    Numeric Processor Extension. This is the 80287.
  8459.  
  8460.  Overflow:
  8461.    an error condition in which the correct answer is finite, but has
  8462.    magnitude too great to be represented in the destination format.
  8463.  
  8464.  Packed Decimal:
  8465.    an Integer format supported by the 80287. A Packed Decimal number is a
  8466.    10-byte quantity, with nine bytes of 18 Binary Coded Decimal digits, and
  8467.    one byte for the sign.
  8468.  
  8469.  Pop:
  8470.    to remove from a stack the last item that was placed on the stack.
  8471.  
  8472.  Precision Control:
  8473.    an option, programmed through the 80287 Control Word, that allows all
  8474.    80287 arithmetic to be performed with reduced precision. Because no
  8475.    speed advantage results from this option, its only use is for strict
  8476.    compatibility with the IEEE Standard, and with other computer
  8477.    systems.
  8478.  
  8479.  Precision Exception:
  8480.    an 80287 error condition that results when a calculation does not return
  8481.    an exact answer. This exception is usually Masked and ignored; it is
  8482.    used only in extremely critical applications, when the user must know if
  8483.    the results are exact.
  8484.  
  8485.  Projective Mode:
  8486.    a state of the 80287, selected in the 80287 Control Word, in which
  8487.    infinities are treated as not having a sign. Thus the values +INFINITY
  8488.    and -INFINITY are considered the same. Certain operations, such as
  8489.    comparison to finite numbers, are illegal in Projective Mode but legal
  8490.    in Affine Mode. Thus Projective Mode gives you a greater degree of error
  8491.    control over infinite inputs.
  8492.  
  8493.  Pseudo Zero:
  8494.    a special value of the Temporary Real format. It is a number with a zero
  8495.    significand and an Exponent that is neither all zeros or all ones.
  8496.    Pseudo zeros can come about as the result of multiplication of two
  8497.    Unnormal numbers; but they are very rare.
  8498.  
  8499.  Real:
  8500.    any finite value (negative, positive, or zero) that can be represented
  8501.    by a decimal expansion. The fractional part of the decimal expansion can
  8502.    contain an infinite number of digits. Reals can be represented as the
  8503.    points of a line marked off like a ruler. The term Real can also refer
  8504.    to a Floating-Point Number that represents a Real value.
  8505.  
  8506.  Short Integer:
  8507.    an Integer format supported by the 80287 that consists of a 32-bit Two's
  8508.    Complement quantity. Short Integer is not the shortest 80287 Integer
  8509.    format──the 16-bit Word Integer is.
  8510.  
  8511.  Short Real:
  8512.    a Floating-Point Format supported by the 80287, which consists of a
  8513.    sign, an 8-bit Biased Exponent, an Implicit Integer Bit, and a 23-bit
  8514.    Significand──a total of 32 explicit bits.
  8515.  
  8516.  Significand:
  8517.    the part of a Floating-Point Number that consists of the most
  8518.    significant nonzero bits of the number, if the number were written out
  8519.    in an unlimited binary format. The Significand alone is considered to
  8520.    have a Binary Point after the first (possibly Implicit) bit; the Binary
  8521.    Point is then moved according to the value of the Exponent.
  8522.  
  8523.  Single Extended:
  8524.    a Floating-Point format, required by the Standard, that provides greater
  8525.    precision than Single; it also provides an explicit Integer Significand
  8526.    bit. The 80287's Temporary Real format meets the Single Extended
  8527.    requirement as well as the Double Extended requirement.
  8528.  
  8529.  Single Floating-Point Number:
  8530.    the Standard's term for the 80287's 32-bit Short Real format.
  8531.  
  8532.  Standard:
  8533.    "a Proposed Standard for Binary Floating-Point Arithmetic," Draft 10.0
  8534.    of IEEE Task P754, December 2, 1982.
  8535.  
  8536.  Status Word:
  8537.    A 16-bit 80287 register that can be manually set, but which is usually
  8538.    controlled by side effects to 80287 instructions. It contains condition
  8539.    codes, the 80287 stack pointer, busy and interrupt bits, and error
  8540.    flags.
  8541.  
  8542.  Tag Word:
  8543.    a 16-bit 80287 register that is automatically maintained by the 80287.
  8544.    For each space in the 80287 stack, it tells if the space is occupied by
  8545.    a number; if so, it gives information about what kind of number.
  8546.  
  8547.  Temporary Real:
  8548.    the main Floating-Point Format used by the 80287. It consists of a sign,
  8549.    a 15-bit Biased Exponent, and a Significand with an explicit Integer bit
  8550.    and 63 fractional-part bits.
  8551.  
  8552.  Transcendental:
  8553.    one of a class of functions for which polynomial formulas are always
  8554.    approximate, never exact for more than isolated values. The 80287
  8555.    supports trigonometric, exponential, and logarithmic functions; all are
  8556.    Transcendental.
  8557.  
  8558.  Trapping NaN:
  8559.    a NaN that causes an I error whenever it enters into a calculation or
  8560.    comparison, even a nonordered comparison.
  8561.  
  8562.  Two's Complement:
  8563.    a method of representing Integers. If the uppermost bit is 0, the number
  8564.    is considered positive, with the value given by the rest of the bits. If
  8565.    the uppermost bit is 1, the number is negative, with the value obtained
  8566.    by subtracting (2^(bit count)) from all the given bits. For example, the
  8567.    8-bit number 11111100 is -4, obtained by subtracting 2^(8) from 252.
  8568.  
  8569.  Unbiased Exponent:
  8570.    the true value that tells how far and in which direction to move the
  8571.    Binary Point of the Significand of a Floating-Point Number. For example,
  8572.    if a Short Real Exponent is 131, we subtract the Bias 127 to obtain the
  8573.    Unbiased Exponent +4. Thus, the Real number being represented is the
  8574.    Significand with the Binary Point shifted 4 bits to the right.
  8575.  
  8576.  Underflow:
  8577.    an error condition in which the correct answer is nonzero, but has a
  8578.    magnitude too small to be represented as a Normal number in the
  8579.    destination Floating-Point format. The Standard specifies that an
  8580.    attempt be made to represent the number as a Denormal.
  8581.  
  8582.  Unmasked:
  8583.    a term that applies to each of the six 80287 Exceptions: I,D,Z,O,U,P. An
  8584.    exception is Unmasked if a corresponding bit in the 80287 Control Word
  8585.    is set to 0. If an exception is Unmasked, the 80287 will generate an
  8586.    interrupt when the error condition occurs. You can provide an interrupt
  8587.    routine that customizes your error recovery.
  8588.  
  8589.  Unnormal:
  8590.    a Temporary Real representation in which the explicit Integer bit of the
  8591.    Significand is zero, and the exponent is nonzero. We consider Unnormal
  8592.    numbers distinct from Denormal numbers.
  8593.  
  8594.  Word Integer:
  8595.    an Integer format supported by both the 80286 and the 80287 that
  8596.    consists of a 16-bit Two's Complement quantity.
  8597.  
  8598.  Zero divide:
  8599.    an error condition in which the inputs are finite, but the correct
  8600.    answer, even with an unlimited exponent, has infinite magnitude.
  8601.  
  8602.  
  8603.  Index
  8604.  ───────────────────────────────────────────────────────────────────────────
  8605.  
  8606.  
  8607.  A
  8608.  ───────────────────────────────────────────────────────────────────────────
  8609.  Address Modes
  8610.  Architecture
  8611.  Arithmetic Instructions
  8612.  ASM 286
  8613.  Automatic Exception Handling
  8614.  
  8615.  
  8616.  B
  8617.  ───────────────────────────────────────────────────────────────────────────
  8618.  Binary Integers
  8619.  
  8620.  
  8621.  C
  8622.  ───────────────────────────────────────────────────────────────────────────
  8623.  Comparison Instructions
  8624.  Compatibility Between the 80287 and 8087
  8625.  Computation Fundamentals
  8626.  Concurrent (80286 and 80287) Processing
  8627.  Condition Codes Interpretation
  8628.  Constant Instructions
  8629.  Control Word
  8630.  
  8631.  
  8632.  D
  8633.  ───────────────────────────────────────────────────────────────────────────
  8634.  Data Synchronization
  8635.  Data Transfer Instructions
  8636.  Data Types and Formats
  8637.   Binary Integers
  8638.   Decimal Integers
  8639.   Encoding of Data Type
  8640.   Infinity Control
  8641.   Precision Control
  8642.   Real Numbers
  8643.   Rounding Control
  8644.  Decimal Integers
  8645.  Denormalization
  8646.  Denormalized Operand
  8647.  Denormals
  8648.  Destination Operands
  8649.  
  8650.  
  8651.  E
  8652.  ───────────────────────────────────────────────────────────────────────────
  8653.  EM (Emulation Mode) Bit in 80286
  8654.  Emulation of 80287
  8655.  Encoding of Data Types
  8656.  Error Synchronization
  8657.  Exception Handling Examples
  8658.  Exception Handling, Numeric Processing
  8659.  Exceptions, Numeric
  8660.   Automatic Exception Handling
  8661.   Handling Numeric Errors
  8662.   Inexact Result
  8663.   Invalid Operation
  8664.   Masked Response
  8665.   Numeric Overflow and Underflow
  8666.   Software Exception Handling
  8667.   Zero Divisor
  8668.  Exponent Field
  8669.  
  8670.  
  8671.  F
  8672.  ───────────────────────────────────────────────────────────────────────────
  8673.  F2XM1 (Exponentiation)
  8674.  FADD (Add Real)
  8675.  FADDP (Add Real and POP)
  8676.  FABS (Absolute Value)
  8677.  FBLD (Packed Decimal──BCD──Load)
  8678.  FBSTP (Packed Decimal──BCD──Store and Pop)
  8679.  FCHS (Change Signs)
  8680.  FCLEX/FNCLEX (Clear Exceptions)
  8681.  FCOM (Compare Real)
  8682.  FCOMP (Compare Real and Pop)
  8683.  FCOMPP (Compare Real and Pop Twice)
  8684.  FDECSTP (Decrement Stack Pointer)
  8685.  FDISI/FNDISI
  8686.  FDIV (Divide Real)
  8687.  FDIV DWORD PTR (Division, Single Precision)
  8688.  FDIVP (Divide Real and Pop)
  8689.  FDIVR (Divide Real Reversed)
  8690.  FDIVRP (Divide Real Reversed and Pop)
  8691.  FENI/FNENI
  8692.  FFREE (Free Register)
  8693.  FIADD (Integer Add)
  8694.  FICOM (Integer Compare)
  8695.  FICOMP (Integer Compare and Pop)
  8696.  FIDIV (Integer Divide)
  8697.  FIDIVR (Integer Divide Reversed)
  8698.  FILD (Integer Load)
  8699.  FIMUL (Integer Multiply)
  8700.  FINCSTP (Increment Stack Pointer)
  8701.  FINIT/FNINIT (Initialize Processor)
  8702.  FIST (Integer Store)
  8703.  FISTP (Integer Store and Pop)
  8704.  FISUB (Integer Subtract)
  8705.  FISUBR (Integer Subtract Reversed)
  8706.  FLD (Load Real)
  8707.  FLD1 (Load One)
  8708.  FLDCW (Load Control Word)
  8709.  FLDENV (Load Environment)
  8710.  FLDL2E (Load Log Base 2 of e)
  8711.  FLDL2T (Load Log Base 2 of 10)
  8712.  FLDLG2 (Load Log Base 3 10 of 2)
  8713.  FLDLN2 (Load Log Base e of 2)
  8714.  FLDPI (Load PI)
  8715.  FLDZ (Load Zero)
  8716.  FMUL (Multiply Real)
  8717.  FMULP (Multiply Real and Pop)
  8718.  FNOP (No Operation)
  8719.  FPATAN (Partial Arctangant)
  8720.  FPREM (Partial Remainder)
  8721.  FPTAN (Partial Tangent)
  8722.  FRNDINT (Round to Integer)
  8723.  FRSTOR (Restore State)
  8724.  FSAVE, FNSAVE (Save State)
  8725.  FSCALE (Scale)
  8726.  FSETPM (Set Protected Mode)
  8727.  FSQRT (Square Root)
  8728.  FST (Store Real)
  8729.  FSTCW/FNSTCW (Store Control Word)
  8730.  FSTENV/FNSTENV (Store Environment)
  8731.  FSTP (Store Real and Pop)
  8732.  FSTSW/FNSTSW (Store Status Word)
  8733.  FSTSW AX, FNSTSW AX (Store Status Word in AX)
  8734.  FSUB (Subtract Real)
  8735.  FSUBP (Subtract Real and Pop)
  8736.  FSUBR (Subtract Real Reversed)
  8737.  FSUBRP (Subtract Real Reversed and Pop)
  8738.  FTST (Test)
  8739.  FWAIT (CPU Wait)
  8740.  FXAM (Examine)
  8741.  FXCH (Exchange Registers)
  8742.  FXTRACT (Extract Exponent and Significand)
  8743.  FYL2X (Logarithm──of x)
  8744.  FYL2XP1 (Logarithm──of x+1)
  8745.  
  8746.  
  8747.  G
  8748.  ───────────────────────────────────────────────────────────────────────────
  8749.  GET$REAL$ERROR (Store, then Clear, Exception Flags)
  8750.  
  8751.  
  8752.  H
  8753.  ───────────────────────────────────────────────────────────────────────────
  8754.  Handling Numeric Errors
  8755.  Hardware Interface
  8756.  
  8757.  
  8758.  I
  8759.  ───────────────────────────────────────────────────────────────────────────
  8760.  I/O Locations (Dedicated and Reserved)
  8761.  IEEE P754 Standard, Implementation
  8762.  Indefinite
  8763.  Inexact Result
  8764.  Infinity
  8765.  Infinity Control
  8766.  INIT$REAL$MATH$UNIT (Initialize Processor Procedure)
  8767.  Initialization and Control
  8768.  Instruction Coding and Decoding
  8769.  Instruction Execution Times
  8770.  Instruction Length
  8771.  Integer Bit
  8772.  Introduction to Numeric Processor 80287
  8773.  Invalid Operation
  8774.  
  8775.  
  8776.  L
  8777.  ───────────────────────────────────────────────────────────────────────────
  8778.  Long Integer Format
  8779.  Long Real Format
  8780.  
  8781.  
  8782.  M
  8783.  ───────────────────────────────────────────────────────────────────────────
  8784.  Machine Instruction Encoding and Decoding
  8785.  Masked Response
  8786.  MP (Math Present) Flag
  8787.  
  8788.  
  8789.  N
  8790.  ───────────────────────────────────────────────────────────────────────────
  8791.  NaN (Not a Number)
  8792.  NO-WAIT FORM
  8793.  Nonnormal Real Numbers
  8794.  Number System
  8795.  Numeric Exceptions
  8796.  Numeric Operands
  8797.  Numeric Overflow and Underflow
  8798.  Numeric Processor Overview
  8799.  
  8800.  
  8801.  O
  8802.  ───────────────────────────────────────────────────────────────────────────
  8803.  Output Format
  8804.  Overflow
  8805.  
  8806.  
  8807.  P
  8808.  ───────────────────────────────────────────────────────────────────────────
  8809.  Packed Decimal Notation
  8810.  Precision Control
  8811.  PLM-286
  8812.  Pointers (INstruction/Data)
  8813.  Processor Control Instructions
  8814.  Programming Examples,
  8815.   Comparative
  8816.   Conditional Branching
  8817.   Exception Handling
  8818.   Floating Point to ASCII Conversion
  8819.   Function Partitioning
  8820.   Special Instructions
  8821.  Programming Interface
  8822.  Pseudo zeros and zeros
  8823.  
  8824.  
  8825.  R
  8826.  ───────────────────────────────────────────────────────────────────────────
  8827.  Real Number Range
  8828.  Real Numbers
  8829.  Recognizing the 80287
  8830.  Register Stack
  8831.  RESTORE$REAL$STATUS (Restore Processor State)
  8832.  Rounding Control
  8833.  
  8834.  
  8835.  S
  8836.  ───────────────────────────────────────────────────────────────────────────
  8837.  SAVE$REAL$STATUS (Save Processor State)
  8838.  Scaling
  8839.  SET$REAL$MODE (Set Exception Masks,Rounding Precision, and Infinity
  8840.     Controls)
  8841.  Short Integer Format
  8842.  Short Real Format
  8843.  Significand
  8844.  Software Exception Handling
  8845.  Source Operands
  8846.  Status Word
  8847.  
  8848.  
  8849.  T
  8850.  ───────────────────────────────────────────────────────────────────────────
  8851.  Tag Word
  8852.  Temporary Real Format
  8853.  Transcendental Instructions
  8854.  Trigonometric Calculation Examples
  8855.  
  8856.  
  8857.  U
  8858.  ───────────────────────────────────────────────────────────────────────────
  8859.  Underflow
  8860.  Unnormals
  8861.  Upgradability
  8862.  
  8863.  
  8864.  W
  8865.  ───────────────────────────────────────────────────────────────────────────
  8866.  WAIT Form
  8867.  Word Integer Format
  8868.  
  8869.  
  8870.  Z
  8871.  ───────────────────────────────────────────────────────────────────────────
  8872.  Zero Divisor
  8873.