home *** CD-ROM | disk | FTP | other *** search
/ Compu-Fix / Compu-Fix.iso / referenz / text / primer.87 < prev    next >
Encoding:
Text File  |  1993-03-01  |  224.5 KB  |  3,715 lines

  1.  
  2.  
  3.  
  4.               WHAT YOU ALWAYS WANTED TO KNOW ABOUT MATH COPROCESSORS
  5.          ***************************************************************
  6.  
  7.  
  8.  
  9.          This document has been created to provide the net.community
  10.          with some detailed information about mathematical coprocessors
  11.          for the Intel 80x86 CPU family. It may also help to answer
  12.          some of the FAQs (frequently asked questions) about this topic.
  13.          The focus of this document is on 387 compatible chips, but
  14.          there is also some information on the other chips in the 80x87
  15.          family and the Weitek coprocessors. Care was taken to make the
  16.          information included as accurate as possible. If you think you
  17.          have discovered erroneous information in this text, or think
  18.          that a certain detail needs to be clarified, or want to suggest
  19.          additions to this text, feel free to contact me at:
  20.  
  21.          S_JUFFA@IRAVCL.IRA.UKA.DE
  22.  
  23.          or at my snail mail address:
  24.  
  25.          Norbert Juffa
  26.          Wielandtstr. 14
  27.          7500 Karlsruhe 1
  28.          Germany
  29.  
  30.  
  31.          CONTENTS of this document
  32.  
  33.          1) What are math coprocessors?
  34.          2) What applications benefit from using a math coprocessor
  35.          3) Installing a math coprocessor
  36.          4) Description of available math coprocessors, special features,
  37.             available speeds, packaging, power consumption
  38.          5) Price information
  39.          6) How do math coprocessors work
  40.          7) Performance comparison of math coprocessors
  41.          8) Test for IEEE-754 conformance and accuracy of transcendental
  42.             functions for different math coprocessors
  43.          9) References (literature)
  44.          10)Addresses of manufacturers of math coprocessors
  45.          11)Appendix A: Test programs for partial compatibility checks
  46.          12)Appendix B: Benchmark programs TRNSFORM and PEAKFLOP
  47.  
  48.          What are math coprocessors?
  49.  
  50.          A coprocessor in the traditional sense is a processor that extends
  51.          the capabilities of a CPU in a transparent manner. This means that
  52.          from the programmer's view the CPU and coprocessor together look
  53.          like one machine. The 80x87 math coprocessors are typical examples
  54.          of such coprocessors. The 80x86 CPUs (with the exception of the 80486,
  55.          which has a built-in 'coprocessor') can only handle 8, 16, or 32 bit
  56.          integers as their primary data types. However, many applications
  57.          require the use of floating-point numbers. Simply put, use of floating
  58.          point numbers enables one to express not only integers, but also
  59.          fractional values over a wide range. The most common application
  60.          of floating point numbers is in scientific applications, where very
  61.          small (e.g. Planck's constant) and very large numbers (e.g. speed
  62.          of light) have to be expressed. But floating-point numbers are also
  63.          useful for business applications such as computing interest. Since
  64.          the 80x86 CPUs do not support floating-point numbers or operations
  65.          on them directly, they have to be programmed using the CPU's integer
  66.          capabilities. This results in slow computations when floating-point
  67.          numbers are used. This is where the 80x87 coprocessors come in.
  68.          Adding a 80x87 to a 80x86 based system augments the CPU architecture
  69.          with eight floating point registers, five additional data types and
  70.          over 70 additional mnemonics. This greatly enhances the system's
  71.          capability to do floating-point computations, as the coprocessor is
  72.          specifically designed to handle floating-point numbers efficiently.
  73.          Like most things in life, floating-point arithmetic has been
  74.          standardized. The relevant standard, to which I will refer quite
  75.          often in this document, is IEEE-754 Standard for Binary Floating-Point
  76.          Arithmetic [10,11]. The standard specifies numeric formats, value
  77.          sets and how the basic arithmetic (+,-,*,/,sqrt, remainder) has to
  78.          work. All the coprocessors covered in this document claim full or
  79.          at least partial compliance with this standard. When browsing the
  80.          literature for information on math coprocessors, you will also
  81.          encounter quite a few acronyms that refer to them: MCP (Math
  82.          CoProcessor), NDP (Numerical Data Processor), NPX (Numerical
  83.          Processor eXtension), FPU (Floating Point Unit). The latter usually
  84.          refers to the 'built-in coprocessor' of the i486.
  85.  
  86.  
  87.          The only data type the 80x87 coprocessors (and the 80486 floating
  88.          point unit, or FPU) can hold in their registers is an 80-bit long
  89.          floating-point number. This data type (called temporary real or
  90.          double extended precision) can represent numbers which range in
  91.          size between 3.36*10^-4932 and 1.19*10^4932 (3.65*10^-4951 to
  92.          1.19*10^4932 including denormal numbers) where the '^' denotes the
  93.          power operator. For those familiar with floating point formats, this
  94.          format has 64 mantissa bits, 15 exponent bits and 1 sign bit for
  95.          the total of 80 bits. This format provides a precision of about
  96.          19 decimal places. The 80x87 can handle additional data types
  97.          that are converted to/from the internal format upon being loaded/
  98.          stored to/from the coprocessor. These include 16 bit, 32 bit, and
  99.          64 bit integers as well as a 18 digit BCD (binary coded decimal)
  100.          occupying 10 bytes and two additional floating point types. The
  101.          short real data type, also called single precision, has 32 bits
  102.          that split into 23 mantissa bits, 8 exponent bit and a sign
  103.          bit. This format provides a precision of about 6-7 decimal places
  104.          and can represent numbers between 1.17*10^-38 and 3.40*10^38
  105.          (1.40*10^-45 to 3.40*10^38 including denormal numbers). The long
  106.          real, or double precision, data type has 64 bits, consisting of
  107.          52 mantissa bits, 11 exponent bits and the sign bit. It provides
  108.          15-16 decimal digits of precision and can handle numbers from
  109.          2.22*10^-308 to 1.79*10^308 (4.94*10^-324 to 1.79*10^308 including
  110.          denormal numbers).
  111.  
  112.          In addition to load/store the above mentioned operand types, the
  113.          80x87 coprocessors can perform all the basic arithmetic operation
  114.          on floating point numbers. Besides 'knowing' how to add, subtract,
  115.          multiply and divide they can also compare floating-point numbers,
  116.          change the sign, take the square root or absolute value, compute
  117.          the remainder and compute some of the transcendental functions,
  118.          like the logarithm. The eight registers in the 80x87 are organized
  119.          in a stack-like manner which takes some time getting used to if
  120.          one programs the coprocessor directly in assembler. However,
  121.          nowadays the compilers or interpreters for most high level
  122.          languages (HLL) can give the programmer access to the coprocessor's
  123.          data types and use their instructions, so there is not much need
  124.          to worry about the rather unusual architecture of the 80x87.
  125.  
  126.          Strictly speaking, the Weitek Abacus 3167 and 4167 are not
  127.          coprocessors in that they do not transparently extended the
  128.          CPU architecture. Rather they could be described as special
  129.          memory mapped IO-devices. Since the term coprocessor has been
  130.          traditionally used for these chips, they are also called by
  131.          that term in this document. The architecture of the Weitek
  132.          chips differs significantly from the 80x87. The Weitek's register
  133.          file consists of 31 32-bit register, each one capable of holding
  134.          an IEEE single precision number. Pairs of consecutive single
  135.          precision registers can also be used as 64-bit IEEE double
  136.          precision register. Thus there are 15 double precision registers.
  137.          The Weitek register file has the standard organization known from
  138.          other registers files like those in the 80386, not the special
  139.          stack-like organization of the 80x87 coprocessors. The Weitek
  140.          coprocessors have been tuned for maximum performance. Therefore,
  141.          only a small instruction set has been implemented, but each
  142.          instruction executes at a very high speed, usually only a few
  143.          clock cycles each. Instructions available are load/store, add,
  144.          subtract, subtract reverse, multiply, multiply and negate,
  145.          multiply and accumulate, multiply and take absolute value,
  146.          divide reverse, negate, absolute value, compare/test, convert
  147.          fix/float, and square root. Note that the Weitek Abacus does not
  148.          support a double extended format, has no built-in transcendental
  149.          functions, and does not support denormals. The ressources required
  150.          to implement such features have instead been devoted to implement
  151.          the basic arithmetic operations as fast as possible. While the
  152.          80x87 coprocessors perform all internal calculations in double
  153.          extended precision and therefore have about the same performance
  154.          for single and double precision calculations, the Weitek features
  155.          explicitly single and double precision operations. For applications
  156.          that require only single precision the Weitek provides additional
  157.          performance that way, as single precision operations are about
  158.          twice as fast as their double precision counterparts. Since the
  159.          Weitek Abacus has more registers than the 80x87 coprocessors,
  160.          values can be kept in registers more often and have to be loaded
  161.          from memory less frequently. This also leads to a performance gain.
  162.          To the CPU, the Weitek Abacus looks like a 64 kB block of memory
  163.          starting at physical address 0C0000000h. Every address in this
  164.          range corresponds to a coprocessor instruction. Accessing a
  165.          specified memory location within this block with the 386/486's
  166.          MOV instruction causes the corresponding instruction to be executed.
  167.          The instructions have been assigned to memory locations in such a
  168.          way that loads to consecutive coprocessor registers can make use
  169.          of the 386/486 MOVS string instruction. The memory mapped interface
  170.          of the Weitek coprocessors is much faster than the IO-oriented
  171.          protocol that is used to couple the CPU to the 80287 and 80387
  172.          coprocessors. The Weitek's starting address of 0C0000000h is only
  173.          a physical address. The Weitek's memory block can be assigned to
  174.          any logical address using the MMU (memory managment unit) in the
  175.          386/486's protected and virtual modes. This also means that the
  176.          Weitek Abacus 3167 and 4167 can *not* be used in the real mode
  177.          of those processors, since the physical start address of the
  178.          Weitek coprocessors is not within the 1 MByte address range and
  179.          the MMU is inoperable in real mode. However, DOS programs can
  180.          make use of the Weitek Abacus by using a DOS extender or a
  181.          memory manager like EMM386 that run in protected/virtual mode
  182.          themself and can therefore map the Weitek's memory block to
  183.          any desired location in the 1 MByte address range. Typically
  184.          the FS segment register is then set up to point to the Weitek's
  185.          memory block. The Weitek Abacus 3167 and 4167 are also supported
  186.          by the UNIX operating system [33].
  187.  
  188.  
  189.          What applications will profit by using a math coprocessor?
  190.  
  191.          According to the Intel 387DX User's Guide, there are more
  192.          than 2100 commercial programs that can make use of a 387
  193.          compatible coprocessor. Every program that uses floating
  194.          point arithmetic somewhere and supports a 80x87 coprocessor
  195.          can gain speed by installing a coprocessor. However, the
  196.          speedup will vary from program to program and even within
  197.          the same program depending on how computation intensive the
  198.          program or operation within the program is. Typical applications
  199.          that benefit from the use of a 80x87 coprocessor are:
  200.          - Business graphics programs, such as Arts&Letters, Freedom
  201.            of Press, and Freelance
  202.          - Spreadsheet programs like Lotus 1-2-3, Excel, Quattro, and
  203.            Wingz
  204.          - CAD programs such as AutoCAD, VersaCAD, and GenericCAD
  205.          - Database programs such as dBase IV, FoxBase, and Paradox
  206.          - Math and Science programs such as Mathematica, TKSolver,
  207.            SPSS/PC, and Statgraphics
  208.          Note that for spreadsheets and databases, a coprocessor
  209.          only helps if some kind of floating point computations
  210.          is performed. This is true more often for spreadsheets
  211.          than for data bases. Also note that the speed of many
  212.          programs depends quite heavily on the speed of the graphics
  213.          adaptor (CAD) or the disk performance (databases), so the
  214.          computational performance is only a (small) part of the
  215.          total performance of the application. There are some programs
  216.          that won't run without a coprocessor, among them AutoCAD R10
  217.          and later and Mathematica. GUIs (graphical user interfaces)
  218.          such as Windows do *not* gain additional speed from using a
  219.          *mathematical* coprocessor, since their graphics operations
  220.          only use integer arithmetic. They benefit from a graphics
  221.          board with a graphical 'coprocessor' though that speed up
  222.          certain common operations such as BitBlt or line drawing.
  223.          However, applications running under Windows may take advantage
  224.          of a math coprocessor, e.g. Excel.
  225.  
  226.          While support for 80x87 coprocessors is very common in application
  227.          programs, the Weitek Abacus coprocessors do not enjoy such wide
  228.          spread support. Due to their high price, only a few high-end PCs
  229.          have been equipped with Weitek coprocessors. Therefore most of
  230.          the programs that support these coprocessors are also high-end
  231.          products like AutoCAD and Versacad-386.
  232.  
  233.  
  234.  
  235.          Installing a math coprocessor
  236.  
  237.          Usually, installing a coprocessor doesn't pose much of a problem,
  238.          as every coprocessor comes with installation instructions and a
  239.          diagnostic disk that lets you check for correct operation once
  240.          the coprocessor has been installed. In addition, the user manuals
  241.          of most computers have a section on coprocessor installation.
  242.  
  243.          1) Make sure to get the right coprocessor for your system. An
  244.             8087 works together with 8086, 8088, V20, and V30 CPUs. An
  245.             80287, 287XL or compatible works together with a 80286 CPU.
  246.             There are also some old 386 motherboards that accept a 80287
  247.             coprocessor, but they usually also provide a socket for the
  248.             387 and I recommend to get a 387 then for use with these
  249.             systems. A 80387, 387DX or compatible coprocessor is for 386
  250.             based systems, as is the Intel RapidCAD. 387 coprocessors
  251.             also work together with Cyrix' 486DLC CPU which despite its
  252.             name does not include an FPU. Similarly, the 387SX or compatible
  253.             coprocessor go into systems whose CPU is a 386SX or Cyrix 486SLC.
  254.             The Weitek Abacus 3167 works with a 386 CPU but requires a
  255.             121-pin EMC socket in your system. Some computers, such as
  256.             IBM's PS/2s don't have this socket. The Weitek Abacus 4167
  257.             works together with the 486 and requires the appropriate
  258.             142-pin socket to be present.
  259.             Always install a coprocessor that is rated at the same speed
  260.             as the CPU. That is, for a 40 MHz 386 system using AMD Am386-40,
  261.             install a coprocessor rated for 40 MHz such as a Cyrix 83D87-40,
  262.             IIT 3C87-40, or ULSI 83C87-40. Running a coprocessor above its
  263.             specified frequency rating may cause it to produce false results,
  264.             which you might fail to recognize as such. I have personally
  265.             experienced this problem with a Cyrix 83D87-33 that I tried
  266.             to push to 40 MHz. It passed all the diagnostic benchmarks
  267.             on the Cyrix diagnostic disk and the tests of some commercial
  268.             system test programs. However, I found it to fail the
  269.             Whetstone and Linpack benchmarks, which include accuracy
  270.             checks. So although there is usually no problem with overheating
  271.             when pushing a coprocessor over the specified maximum frequency
  272.             rating, be warned that operation of a coprocessor above the
  273.             maximum ratings stated by the manufacturer makes operation
  274.             unreliable. Some 386 boards allow the coprocessor to be clocked
  275.             differently than the CPU. This is called asynchronous operation
  276.             and allows you to run the coprocessor at 33 MHz while the CPU
  277.             runs at 40 MHz, for example. Please note that only the Intel
  278.             80387 and 387DX support asynchronous operation. The 387 'clones'
  279.             from Cyrix, IIT and ULSI always run at the full speed of the
  280.             CPU, even if you have set up your motherboard for asynchronous
  281.             operation.
  282.          2) Once you've got the correct coprocessor for your system you
  283.             can start the actual installation process:
  284.             - turn off the computer's power switch and unplug the power
  285.               cord from the wall outlet
  286.             - remove the cover of your computer
  287.             - locate the math coprocessor socket. This socket is located
  288.               right next to the CPU, which can be identified by the
  289.               printing on top of the chip. The CPU usually is one of the
  290.               biggest chips on the board. The 8078 and 80287 DIL sockets
  291.               are rectangular sockets with 20 pin holes on each of the
  292.               longer sides. The 387SX PLCC socket is a square socket that
  293.               has 17 vertical connector strips on the 'wall' of each side.
  294.               The 387 PGA socket is square and has two rows of pin holes
  295.               on each side. The EMC socket is similar but has three rows
  296.               of holes on each side. The PGA socket for the Weitek 4167 is
  297.               also square with three rows of holes on each side. If the CPU
  298.               and coprocessor socket is on a separate card rather than on
  299.               the motherboard (typical for modular systems), you have to
  300.               remove the card and place it on a flat and hard surface free
  301.               of static electricity. If you can't find the math coprocessor
  302.               socket, consult your owner's manual or your computer dealer.
  303.               If you want to install the Intel RapidCAD in a 386 system,
  304.               you will have to remove the 386 CPU before starting to
  305.               install the two RapiCAD chips. Intel provides an easy to
  306.               use chip extractor and a storage box for the 386 chip for
  307.               this purpose. Just follow the instructions in the RapidCad's
  308.               installation manual.
  309.             - Be sure you are properly grounded before you remove the
  310.               coprocessor from its antistatic box. Static electricity
  311.               can damage the coprocessor. Make sure you do not touch
  312.               the pins.
  313.             - Check if all pins are straight and not bend. If you find
  314.               bent pins, carefully straigthen them with needle-nose pliers
  315.               or tweezers.
  316.             - Match the coprocessors orientation with the orientation
  317.               of the socket. 8087 and 287 coprocessors have anotch on one
  318.               the shorter sides of their rectangular DIL package that should
  319.               be matched with the notch of the coprocessor socket. Usually
  320.               the 286 CPU and the 287 coprocessor are placed alongside each
  321.               other and both have the same orientation, that is their
  322.               respective notches point in the same direction. 387SX
  323.               coprocessors feature a white dot or similar mark that matches
  324.               with some sort of marking on the socket. 387 coprocessors
  325.               have a beveled corner that is also marked with a white dot
  326.               or similar marking. This should be matched with the beveled
  327.               or otherwise marked corner of the socket. If you install
  328.               a 387 coprocessor in an EMC socket, leave one row of holes
  329.               free on each side. Correct orientation of the coprocessor
  330.               is absolutely essential, because if you insert it the
  331.               wrong way it may be damaged. If you have found the correct
  332.               orientation, make sure all pins are correctly aligned with
  333.               their respective holes. Press firmly and evenly on the chip.
  334.               You may have to press hard to seat the coprocessor all the
  335.               way. Make sure your motherboard does not bend more than
  336.               slighty under the insertion pressure. Otherwise it may
  337.               develop cracks that could damage the signal lines on the
  338.               board. For 8087, 287, and 387 coprocessors it is normal that
  339.               the coprocessor does not go all the way in but about one
  340.               millimeter (1/25 inch) of space is left between the socket
  341.               and the bottom of the coprocessor chip. This enables the
  342.               insertion of a extraction device should it become necessary
  343.               to remove the coprocessor. Note that the construction of the
  344.               387SX's PLCC socket makes it next to impossible to remove
  345.               the coprocessor once fully inserted, as the top of the chip
  346.               is level with the socket's 'walls' then.
  347.          3) Check your computer's manual for the jumpers and/or switches
  348.             you may have to set for coprocessor operation.
  349.             Put the cover back on the system unit and reconnect the power.
  350.             Turn on your computer. Depending on your BIOS, you may have
  351.             to run the setup or configuration program to register the
  352.             coprocessor.
  353.             Use the diagnostic disk included with your coprocessor to
  354.             check for correct operation of your coprocessor.
  355.  
  356.  
  357.  
  358.          Coprocessor emulations
  359.  
  360.          In the absence of a coprocessor, floating-point calculations
  361.          are most often performed by a software package that simulates
  362.          the operations of the coprocessor. Such a program is called
  363.          a coprocessor emulator. Simulating the coprocessor has the
  364.          advantage that identical code can be generated for the
  365.          coprocessor and the emulator so that it is possible to write
  366.          programs that run on both, systems with and systems without a
  367.          coprocessor. Wether the program is to use the coprocessor or the
  368.          emulator can then be decided at run-time by checking if a
  369.          math coprocessor is present in the system.
  370.  
  371.          Two approaches to interface an 80x87 emulator to programs are
  372.          common. While the first method works with all 80x86 processors,
  373.          the second only works from the 80286 on. The first method makes
  374.          use of the fact that all coprocessor instruction start with the
  375.          same five bit pattern 11011. Thus the first byte of a coprocessor
  376.          instruction will be in the range D8-DF hexadecimal. In addition,
  377.          coprocessor instructions usually are preceeded by a WAIT instruction
  378.          (opcode 9Bh) which is one byte long (the reason for doing this
  379.          is described in a later chapter on the operation of the 80x87).
  380.          One common approach is to replace the WAIT instruction and the
  381.          first byte of the coprocessor instruction with one of eight
  382.          interrupts; the remaining bytes of the coprocessor instruction
  383.          are left unchanged. Interrupts 34 to 3B hexadecimal are used for
  384.          this emulation technique. Note that the sequences 9B D8 .. 9B DF
  385.          can be easily converted to the interrupt instructions CD 34 .. CD 3B
  386.          by simple addition and subtraction of constants. The compiler or
  387.          assembler produces code that contains the appropriate interrupt
  388.          calls instead of the coprocessor instructions. If a coprocessor
  389.          is detected at run-time, the emulator interrupts point to a short
  390.          routine that converts the interrupts calls back to coprocessor
  391.          instructions (self modifying code). If no coprocessor is found
  392.          the interrupts point to an emulation package which examines the
  393.          byte(s) following the interrupt intruction to determine what
  394.          operation to perform. The method described is used by the compilers
  395.          from Microsoft and Borland for example. It works with every
  396.          80x86 CPU from the 8086/8088 on.
  397.          The second method to interface an emulator is only available on
  398.          286 and 386 machines. If the emulation bit in the machine status
  399.          word of these processors is set, the processors will generate an
  400.          interrupt 7 whenever a coprocessor instruction is encountered.
  401.          The interrupt vector then points to an emulation package that
  402.          decodes the instruction and performs the desired operation. This
  403.          approach has the advantage that the emulator doesn't have to be
  404.          included in the program code, but can be loaded as a TSR or
  405.          device driver once and then used by every program that requires
  406.          a coprocessor. Emulation via interrupt 7 is transparent, which
  407.          means that programs containing coprocessor instructions execute
  408.          just like a coprocessor was present, only slower. This approach
  409.          is taken by the public domain EM87 emulator and the commercial
  410.          Franke387 emulator, for example. Even programs that require a
  411.          coprocessor to run like AutoCAD are 'fooled' to believe that
  412.          a coprocessor is present with emulators using INT 7.
  413.  
  414.          The size of the emulator used by TP 6.0 is about 9.5 kB, EM87
  415.          occupies about 15.8 kB as a TSR, and Franke387 uses about 13.4 kByte
  416.          as a device driver. Note that Franke387 and especially EM87 model
  417.          a real coprocessor much more closely than Turbo Pascal's emulator
  418.          does. In particular, EM87 supports denormal numbers, precision
  419.          control, and rounding control. The emulator in TP 6.0 does not
  420.          implement these features. The version of Franke387 tested (V2.4)
  421.          supports denormals in single and double precision, but not
  422.          double extended precision. It supports precision control, but
  423.          not rounding control. Intel's E80287 is supposed to be an 100%
  424.          exact emulation of the 80287 coprocessor [44]. Generally, the
  425.          more closely a real coprocessor is modelled by the emulator,
  426.          the slower does the emulator run and the larger the code for the
  427.          emulator is.
  428.  
  429.  
  430.          Relative execution times of coprocessor vs. software emulators
  431.          for particular coprocessor instructions
  432.  
  433.                         Intel 387DX    TP 6.0 Emulator   EM87 Emulator
  434.  
  435.          FADD ST, ST(0)       1              26                104
  436.          FDIV [DWord]         1              22                136
  437.          FXAM                 1              10                 73
  438.          FYL2X                1              33                102
  439.          FPATAN               1              36                110
  440.          F2XM1                1              38                110
  441.  
  442.  
  443.          The following table is an excerpt from [44]:
  444.  
  445.                         Intel 80287  Intel E80287 Emulator
  446.  
  447.          FADD ST, ST(0)       1              42
  448.          FDIV [DWord]         1             266
  449.          FXAM                 1             139
  450.          FYL2X                1              99
  451.          FPATAN               1             153
  452.          F2XM1                1              41
  453.  
  454.  
  455.  
  456.          The following has been adapted from [43] and merged with my own
  457.          data:
  458.  
  459.                         Intel 8087  TP 6.0 Emul. (8086)  Intel Emul. (8086)
  460.  
  461.          FADD ST, ST(0)       1              20                 94
  462.          FDIV [DWord]         1              22                 82
  463.          FPTAN                1              18                144
  464.          F2XM1                1               6                171
  465.          FSQRT                1              44                544
  466.  
  467.  
  468.  
  469.          One of the reasons emulators are so slow is that they are
  470.          often designed to run with every CPU from the 8086/8088 on.
  471.          This is the case with the emulators built into the compiler
  472.          libraries of the Turbo Pascal 6.0 (also used by Turbo C/C++)
  473.          and Microsoft C 6.0 compiler (probably also used in other
  474.          Microsoft products) and is also true for the EM87 emulator
  475.          in the public domain. By using code that can run on a 8086/8088,
  476.          these emulators forego the speed advantage offered by the
  477.          additional instructions and architectureal enhancements (such
  478.          as 32-bit registers) of the more advanced Intel 80x86 processors.
  479.          A notable exception is the Franke387 emulator, a commercial
  480.          emulator that is also sold as shareware. It uses 386 specific
  481.          32-bit code and only runs on 386/386SX computers.
  482.  
  483.          Besides being slow, coprocessor emulators have other drawbacks
  484.          compared with real coprocessors. Most of the emulators do not
  485.          support the additional instructions that the 387 compatible
  486.          coprocessors offer over the 80287. Often, some of the low-level
  487.          stack-manipulating instructions like FDECSTP are not emulated.
  488.          The coprocessor status register is not or only partially emulated.
  489.          Some emulators do not conform to the IEEE-754 standard in their
  490.          implementation of the basic arithmetic functions, while the
  491.          coprocessors do. Also, they sometimes lack the support for
  492.          denormals (a special class of floating point numbers) although
  493.          it is required by the standard. Not all the 80x87 emulators
  494.          support rounding control (a feature required by IEEE-754) and
  495.          precision control (a feature of the 80x87 coprocessor). Most of
  496.          the ommisions are aimed at making the emulator faster and smaller.
  497.          Because of the shortcomings of coprocessor emulators, a real
  498.          coprocessor is a must for anybody planning to do some serious
  499.          computations. At todays prices, this shouldn't pose much of a
  500.          problem to anybody.
  501.  
  502.  
  503.          Available coprocessors, CPU+FPU as of 08-10-92:
  504.  
  505.  
  506.          Intel 8087     [43] was the first coprocessor that Intel brought
  507.                         out for the 80x86 family. It was introduced in 1980
  508.                         and therefore does not have full compatibility with
  509.                         the IEEE-754 standard for floating point arithmetic,
  510.                         which was finally released in 1985. It complements
  511.                         the 8088 and 8086 CPUs and can also be interfaced
  512.                         to the 80188 and 80186 processors. It comes in a
  513.                         40 pin CERDIP (ceramic dual inline package). It
  514.                         is available in 5 MHz, 8 Mhz (8087-2), and 10 MHz
  515.                         (8087-1) versions. The 8087 is implemented using
  516.                         NMOS. Power consumption is rated at max. 2400 mW [42].
  517.                         A neat trick to enhance the processing power of the
  518.                         8087 for computations that use only the basic
  519.                         arithmetic operations (+,-,*,/) and do not require
  520.                         high precision is to set the precision control to
  521.                         single precision. This gives one a performance
  522.                         increase of up to 20%. For details about programming
  523.                         the precision control, see program PCtrl in appendix A.
  524.          Intel 80187    is a rather new coprocessor designed to support the
  525.                         80C186 embedded controller. It was introduced in 1989
  526.                         and implements the complete 80387 instruction set.
  527.                         It is available in a 40 pin CERDIP (ceramic dual
  528.                         inline package) and a 44 pin PLCC (plastic leaded
  529.                         chip carrier) for 12.5 and 16 MHz operation. Power
  530.                         consumption is rated at max. 675 mW for the
  531.                         12.5 MHz version and max. 780 mW for the 16 MHz
  532.                         version [37].
  533.          Intel 80287    [44] is the original Intel coprocessor for the 80286
  534.                         and was introduced in 1983. It uses the same execution
  535.                         unit as the 8087 and therefore has the same speed
  536.                         (sometimes slower due to additional overhead in CPU
  537.                         coprocessor communication). As the 8087, it does not
  538.                         provide full compatibility with the IEEE-754 floating
  539.                         point standard released in 1985. It was manufactured
  540.                         in NMOS technology. There are 6 MHz, 8 MHz, and 10
  541.                         MHz versions. The chip comes in a 40 pin CERDIP
  542.                         (ceramic dual inline package). Power consumption can
  543.                         be estimated to be the same as that for the 8087,
  544.                         which is max. 2400 mW. The 80287 has been replaced
  545.                         in the Intel 80x87 family with its successor, the
  546.                         Intel 287XL, which has been introduced in 1990. The
  547.                         287XL is done in CMOS. It is based on the 387 core
  548.                         and therefore much faster than the 80287. There may
  549.                         still be a few of the old 80287 chips on the market
  550.                         though.
  551.          Intel 80287XL  is the second generation 287 introduced by Intel
  552.                         in 1990. Since it is based on the 387 core, it
  553.                         features full IEEE 754 compatibility and faster
  554.                         execution of coprocessor instructions. Intel claims
  555.                         about 50% faster operation than the 80287 for typical
  556.                         benchmark test such as Whetstone [45]. Comparison
  557.                         with benchmark results for the AMD 80C287, which is
  558.                         identical to the Intel 80287, support this claim [1].
  559.                         The Intel 287XL performed 66% faster than the AMD
  560.                         80C287 on the fractal benchmark and 66% faster on
  561.                         the Whetstone benchmark in these tests. Whetstone
  562.                         results from [46] show the Intel 287XL at 12.5 MHz
  563.                         to perform 552 kWhets/sec as opposed to the AMD's
  564.                         80C287 289 kWhets/sec, a 91% performance increase.
  565.                         A benchmark using the MathPak program showed the
  566.                         Intel 287XL to be 59% faster than the Intel 80287
  567.                         (6.9 sec. vs. 11.0 sec.) [26]. Since the 287XL
  568.                         has all the additional instructions and enhancements
  569.                         of a 387, most software automatically identifies
  570.                         it as an 80387 compatible coprocessors and makes
  571.                         use of the extra features available like the FSIN
  572.                         and FCOS instructions. The 287XL is done in CMOS
  573.                         and therefore uses less power than the older 80287,
  574.                         which was done in NMOS. The 287XL is rated for
  575.                         speeds of up to 12.5 MHz. At 12.5 MHz, the power
  576.                         consumption is rated at max. 675 mW, about 1/4 of
  577.                         the 80287 power consumption. The 287XL comes in
  578.                         either a 40 pin CERDIP (ceramic dual inline package)
  579.                         or a 44 pin PLCC (plastic leaded chip carrier). The
  580.                         latter version is called the 287XLT and intended
  581.                         mainly for laptop use.
  582.          AMD 80C287     is an exact clone of the old Intel 80287 that was
  583.                         brought to market by AMD in 1989. It contains the
  584.                         original microcode of the 80287 and is therefore
  585.                         100% compatible with this chip. However, as the name
  586.                         indicates, the 80C287 is manufactured in CMOS and
  587.                         therefore uses less power than an equivalent Intel
  588.                         80287. At 12.5 Mhz, its power consumption is rated
  589.                         at max. 625 mW or slightly less than that of the
  590.                         Intel 80287XL [27]. There is also another version
  591.                         called AMD 80EC287 that uses an 'intelligent' power
  592.                         save feature to reduce the power consumption below
  593.                         80C287 levels. Tests at 10.7 MHz show typical power
  594.                         consumption for the 80EC287 to be at 30mW, compared
  595.                         to 150 mW for the AMD 80C287, 300 mW for the Intel
  596.                         287XL and 1500 mW for the Intel 80287 [57]. The
  597.                         80EC287 is therefore ideally suited for low power
  598.                         laptop systems. The AMD 80C287 is available in speeds
  599.                         of 10, 12, and 16 MHz. I have only seen it being
  600.                         offered in 10 MHz and 12 MHz versions though. At
  601.                         about US$ 50, it is the cheapest coprocessor available.
  602.                         Note that it provides less performance than the
  603.                         newer Intel 287XL (see above for details). The AMD
  604.                         80C287 is available in 40 pin ceramic and plastic
  605.                         DIPs (dual inline package) and as 44 pin PLCC
  606.                         (plastic leaded chip carrier). Due to recent legal
  607.                         battles with Intel over the right to use the 287
  608.                         microcode, which AMD lost, AMD may have to discontinue
  609.                         this product (disclaimer: I am not a legal expert).
  610.          Cyrix 82S87    was developed from the Cyrix 83D87, Cyrix' 387 'clone'
  611.                         and has been available since 1991. It implements the
  612.                         full 387 instruction set. It totally complies with
  613.                         the IEEE-754 standard for floating point arithmetic
  614.                         and features nearly total compatibility with Intel's
  615.                         coprocessors. It implements the transcendental
  616.                         functions with the same degree of accuracy and the
  617.                         superior speed of the Cyrix 83D87. This makes the
  618.                         Cyrix 82S87 the fastest [1] and most accurate 287
  619.                         compatible coprocessor available. Documentation by
  620.                         Cyrix [46] rates the 82S87 at 730 kWhets/sec for a
  621.                         12.5 MHz system, while the Intel 287XL performs only
  622.                         552 kWhets/sec. The 82S87 is a fully static CMOS
  623.                         design with very low power requirements that can
  624.                         run at speeds of 6 to 20 MHz. Cyrix documentation
  625.                         shows the 82S87 to consume about the same amount of
  626.                         power as the AMD 80C287 (see above). The 82S87 comes
  627.                         in a 40 pin DIP or a 44 pin PLCC (plastic leaded
  628.                         chip carrier) compatible with the pinout of the
  629.                         Intel 287XLT and ideally suited for laptop use.
  630.          IIT 2C87       was the first 287 clone available. It was introduced
  631.                         to the market in 1989. It has about the same speed
  632.                         as the Intel 287XL [1]. The 2C87 implements the
  633.                         full 387 instruction set [38]. Tests I ran on the
  634.                         3C87 seem to indicate that it is not fully compatible
  635.                         with the IEEE-754 standard for floating-point
  636.                         arithmetic (see below for details), so it can be
  637.                         assumed that the 2C87 also fails these test as it
  638.                         presumably uses the same core as the 3C87. The IIT
  639.                         2C87 provides extra functions not available on any
  640.                         other 287 chip [38]. It has 24 user accessible
  641.                         floating-point registers organized into three register
  642.                         banks. Additional instructions (FSBP0, FSBP1, FSBP2)
  643.                         allow switching from one bank to another. Transfers
  644.                         between registers in different banks are not
  645.                         supported however, so this feature by itself
  646.                         is of limited usefulness. Also there seems to
  647.                         be only one status register (containing the
  648.                         stack top pointer), so it has to be manually
  649.                         loaded and stored when switching between banks
  650.                         with a different number of registers in use [40].
  651.                         The register bank's main purpose is to aid the
  652.                         fourth additional instruction the 2C87 has
  653.                         (F4X4), which does a full multiply of a 4x4 matrix
  654.                         by a 4x1 vector, an operation common in 3D graphics
  655.                         applications [39]. The built-in matrix multiply
  656.                         speeds this operations up by a factor of 6 to 8
  657.                         compared with a programmed solution according to
  658.                         the manufacturer [38]. Tests show the speed-up
  659.                         to be indeed in this range [40]. For the 3C87, I
  660.                         measured the execution time of F4X4 to be about
  661.                         280 clock cycles, the execution time on the 2C87
  662.                         should be somewhat bigger. I estimate it to be
  663.                         around 310 clock cycles due to the higher CPU-NDP
  664.                         communication overhead in instruction execution in
  665.                         286/287 systems (~45-50 clock cycles) compared with
  666.                         386/387 systems (~16-20 clock cycles). As useful as
  667.                         the F4X4 instruction may seem, there are only very
  668.                         few applications that make use of this feature if
  669.                         a IIT coprocessor is detected at run time, among
  670.                         them Schroff Development's Silver Screen and
  671.                         Evolution Computing's Fast-CAD 3-D [25]. The 2C87
  672.                         is available for speeds of up to 20 MHz. It is
  673.                         implemented in an advanced CMOS process and has
  674.                         therefore a low power consumption of typically
  675.                         about 500 mW [38].
  676.          Intel 387      was the first generation of coprocessors for the
  677.                         Intel 386. It was introduced in 1986, about one
  678.                         year after introduction of the 80386. Early 386
  679.                         system were therefore equipped with a 80287 and a
  680.                         80387 socket. The 80386 works together with the
  681.                         80287 but the numerical performance is hardly
  682.                         adequate for such a system. The 80387 has since
  683.                         been superseeded by the Intel 387DX introduced
  684.                         by a quiet change in 1990. You might find it
  685.                         when aquiring an old 386 machine, though. The
  686.                         80387 is about 20% slower than the newer 387DX
  687.                         (see the paragraph below for detailed information).
  688.                         Like the other 387 coprocessors, the 80387 is packaged
  689.                         in a 68-pin ceramic PGA. The Intel 80387 is
  690.                         manufactured using Intel's older 1.5 micron CHMOS
  691.                         III technology that has moderate power requirements.
  692.                         Power consumption at 16 MHz is max. 1250 mW (750 mW
  693.                         typical), at 20 MHz it is max. 1550 mW (950 mW
  694.                         typical), and at 25 MHz it is max. 1950 mW (1250 mW
  695.                         typical) [60].
  696.          Intel 387DX    is the second generation Intel 387 that was quietly
  697.                         introduced in 1989. This version is done in a more
  698.                         advanced CMOS process than the 80387 that enables
  699.                         the coprocessor to run at a maximum frequency of 33
  700.                         MHz, while the 80387 had a maximum frequency of 25 MHz.
  701.                         The 387DX is about 20% faster than the 80387 on the
  702.                         average for the same clock frequency. For a 386/387
  703.                         system operating at 29 MHz the Whetstone benchmark
  704.                         compiled with the highly optimizing Metaware High-C
  705.                         V1.6 runs at 2377 kWhetstones/sec for the 80387 and
  706.                         at 2693 kWhetstones/sec for the 387DX, a 13% increase.
  707.                         In a fractal calculation programmed in assembly
  708.                         language, the 387DX performance was 28% higher than
  709.                         the performance of the 80387. The transcendental
  710.                         functions have also sped up from the 80387 to the
  711.                         387DX. In the Savage benchmark compiled with the
  712.                         Metaware High-C V1.6 optimizing compiler and running
  713.                         on a 29 MHz system, the 80387 evaluated 77600 function
  714.                         calls/second, while the 387DX evaluated 97800 function
  715.                         calls/second, a 26% increase [7]. Some instructions
  716.                         have been sped up a lot more more than the average
  717.                         20%. For example the FBSTP instruction has been sped
  718.                         up by a factor of 3.64. The Intel 387DX (and its
  719.                         predecessor 80387) are the only 387 coprocessors
  720.                         that support asynchronous operation of CPU and NDP.
  721.                         The 387 consists of a bus interface unit and a
  722.                         numerical execution unit. The bus interface unit
  723.                         always runs at the speed of the CPU clock (CPUCLK2).
  724.                         If the CKM (ClocK Mode) pin of the 387 is strapped
  725.                         to Vcc, the numerical execution unit runs at the
  726.                         same speed as the bus interface unit. If CKM is tied
  727.                         to ground, the numerical execution unit runs at the
  728.                         speed provided by the NUMCLK2 input. The ratio of
  729.                         NUMCLK2 (coprocessor clock) to CPUCLK2 (CPU clock)
  730.                         must lie within the range 10:16 to 14:10. For example,
  731.                         for a 20 MHz 386, the Intel 387DX could be clocked
  732.                         from 12.5 MHz to 28 MHz via the NUMCLK2 input. On
  733.                         the Cyrix 83D87, Cyrix 387+, ULSI 83C87, and the IIT
  734.                         387, the CKM pin is not connected. These coprocessors
  735.                         always run at the speed of the CPU. The Intel 387DX
  736.                         is manufactured using Intel's advanced low power
  737.                         CHMOS IV technology. Power consumption at 20 MHz is
  738.                         max. 900 mW (525 mW typical), at 25 MHz it is max.
  739.                         1050 mW (625 mW typical), and at 33 MHz it is 1250
  740.                         mW (750mW typical) [59].
  741.          Intel 387SX    is the coprocessor for the Intel 386SX. The 386SX is
  742.                         an Intel 386 with a 16-bit data path. This reduces
  743.                         somewhat the costs to build a complete system as
  744.                         compared to a full 32-bit design required by the
  745.                         80386DX. The 386SX main purpose was to replace the
  746.                         80286 CPU, which Intel subsequently stopped producing.
  747.                         Due to the 16-bit data path, the 386SX is slower than
  748.                         the 386DX and offers about the same speed as a 80286
  749.                         at the same clock frequency for 16-bit applications.
  750.                         As the 386SX is a complete 80386, it offers also the
  751.                         possibility to run 32-bit applications and supports
  752.                         the virtual 8086 mode used for example by Windows'
  753.                         enhanced mode. The 387SX has all the features the
  754.                         Intel 387DX offers, including the ability for
  755.                         asynchronous operation of CPU and coprocessor
  756.                         (see the above paragraph on the Intel 387DX for
  757.                         details). Due to the 16 bit data path between the
  758.                         CPU and the coprocessor, the 387SX is a bit slower
  759.                         than a 387DX operating at the same frequency. The
  760.                         387SX comes in a 68-pin PLCC (pastic leaded chip
  761.                         carrier) package and is available in 16 Mhz and 20
  762.                         MHz versions. Coprocessors for faster 386SX systems
  763.                         based on the Am386SX CPU are available from IIT,
  764.                         Cyrix, and ULSI. Power consumption for the 387SX
  765.                         at 16 MHz is max. 1250 mW (740 mW typical), for
  766.                         the 20 MHz version it is max. 1500 mW (1000 mW
  767.                         typical) [62].
  768.          IIT 3C87       came out in 1989 at about the same time as the
  769.                         Cyrix 83D87. Both coprocessors are faster than
  770.                         Intel's 387DX coprocessor. Tests I ran with the
  771.                         IEEETEST program show that the 3C87 is not fully
  772.                         compatible with the IEEE-754 standard for
  773.                         floating-point arithmetic although the manufacturer
  774.                         claims differently. It is well possible that the
  775.                         reported errors are due to personal interpretations
  776.                         of the standard by the program's author that have
  777.                         been incorporated into IEEETEST and that the
  778.                         standard also supports the different interpretation
  779.                         chosen by IIT. On the other hand, the IEEE test
  780.                         vectors incorporated into IEEETEST have become
  781.                         somewhat of an industry standard [66] and Intel's
  782.                         387, 486, and RapidCAD chips pass the test without
  783.                         a single failure, so the fact that the IIT 3C87
  784.                         fails some of the tests indicates that it is not
  785.                         fully compatible with the Intel 387 coprocessor.
  786.                         My tests also show that the IIT 3C87 does not
  787.                         support denormals for the double extended format.
  788.                         It is not entirely clear wether the IEEE standard
  789.                         mandates support for extended precision denormals,
  790.                         as the IEEE-754 document explicitly only mentions
  791.                         single and double precision denormals. Missing
  792.                         support for denormals is not a critical issue with
  793.                         most applications but there are some programs for
  794.                         which support of denormals is quite helpful, if not
  795.                         important [41]. Anyhow, failure of the 3C87 to
  796.                         support extended precision denormal numbers is an
  797.                         incompatibility with the Intel 387 and 486. The 3C87
  798.                         provides extra functions not available on any other
  799.                         387 chip [38]. It has 24 user accessible floating-point
  800.                         registers organized into three register banks.
  801.                         Additional instructions (FSBP0, FSBP1, FSBP2)
  802.                         allow switching from one bank to another. Transfers
  803.                         between registers in different banks are not
  804.                         supported however, so this feature by itself
  805.                         is of limited usefulness. Also there seems to
  806.                         be only one status register (containing the
  807.                         stack top pointer), so it has to be manually
  808.                         loaded and stored when switching between banks
  809.                         with a different number of registers in use [40].
  810.                         The register banks main purpose is to aid the
  811.                         fourth additional instruction the 3C87 has
  812.                         (F4X4), which does a full multiply of a 4x4 matrix
  813.                         by a 4x1 vector, an operation common in 3D graphics
  814.                         applications [39]. I measured this instruction to
  815.                         execute in about 280 clock cycles, during which
  816.                         time it executes 16 multiplications and 12 additions.
  817.                         The built-in matrix multiply speeds the matrix by
  818.                         vector multiply up by a factor of 3 compared
  819.                         with a programmed solution according to IIT [39].
  820.                         The results for my own TRNSFORM benchmark support
  821.                         this claim (see results below), showing a performance
  822.                         increase by a factor of about 2.5. This makes
  823.                         matrix multiplies on the IIT 3C87 nearly as fast as
  824.                         on an Intel 486 at the same clock frequency. However,
  825.                         there are only very few applications that make use
  826.                         of this feature if a IIT 3C87 is detected at run time,
  827.                         among them Schroff Development's Silver Screen and
  828.                         Evolution Computing's Fast-CAD 3-D [25]. Like the
  829.                         387 'clones' from Cyrix and ULSI, the 3C87 does not
  830.                         support asynchronous operation of the CPU and the
  831.                         coprocessor. The 3C87 always runs at the full speed
  832.                         of the CPU. The 3C87 is implemented in an advanced
  833.                         CMOS process and has low power requirements of
  834.                         typically about 600 mW. It is available in 16, 20,
  835.                         25, 33, and 40 MHz versions.
  836.          IIT 3C87SX     is the version of the IIT 3C87 that is intended for
  837.                         use with Intel's 386SX or AMD's Am386SX CPU. It is
  838.                         functionally equivalent to the IIT3C87. Due to the
  839.                         16-bit data path between the CPU and the coprocessor
  840.                         in a 386SX based system, coprocessor instructions
  841.                         will execute somewhat slower than on the 3C87. The
  842.                         IIT 3C87SX is the only 387SX coprocessor that is
  843.                         offered at speeds of 16, 20, 25, and 33 MHz right
  844.                         now. I have read that Cyrix has also annouced a
  845.                         83S87-33, but haven't seen it being offered yet.
  846.                         The 3C87SX is packaged in a 68-pin PLCC.
  847.          Cyrix 83D87    was introduced in 1989, only shortly after the
  848.                         coprocessors from IIT. It has been the fastest
  849.                         387 compatible coprocessor in several benchmark
  850.                         comparisons [1,7,68,69]. It also came out as the
  851.                         fastest coprocessor in my own tests (see benchmark
  852.                         results below). Although the Cyrix 83D87 provides
  853.                         up to 50% more performance than the Intel 387DX
  854.                         in benchmarks comparisons, the speed advantage
  855.                         over other 387 compatible coprocessors in real
  856.                         applications is usually much smaller. For example,
  857.                         in a test using the program 3D-Studio, the Cyrix
  858.                         83D87 was 6% faster than the Intel 387DX [1].
  859.                         Besides being the fastest 387 coprocessor, the
  860.                         83D87 also offers the most accurate transcendental
  861.                         functions results of all coprocessors tested (see
  862.                         test results below). Unlike the Intel coprocessors,
  863.                         which use the CORDIC [18,19] algorithm to compute
  864.                         the transcendental functions, Cyrix uses rational
  865.                         approximations to the functions. In the past the
  866.                         CORDIC method has been popular since it requires
  867.                         only shifts and adds which makes it easy to implement.
  868.                         It is also reasonably fast. Recently, the cost for
  869.                         the implementation for fast floating-point multipliers
  870.                         has dropped significantly due to the availablity of
  871.                         VLSI, making the use of rational approximations
  872.                         superior to CORDIC for the generation of transcendental
  873.                         functions [61]. The Cyrix 83D87 uses a very fast
  874.                         array multiplier, making its transcendental functions
  875.                         faster than those of any other 387 compatible
  876.                         coprocessor. It also uses 75 bit for the mantissa
  877.                         for intermediate calculations (as opposed to 68 bits
  878.                         on other coprocessors), making its transcendental
  879.                         functions more accurate than those of any other
  880.                         coprocessor or FPU (see results below). The 83D87
  881.                         and its successor, the 387+ are the 387 'clones'
  882.                         with the highest degree of compatibility. There
  883.                         are only very few SW and HW incompatibilties with
  884.                         the Intel 387DX. These have been documented by
  885.                         Cyrix [12]. The software differences are caused
  886.                         by some bugs present in the 387DX that Cyrix fixed
  887.                         for the 83D87. Unlike the Intel 387DX, the 83D87
  888.                         (and all other 387 'clones' as well) does not support
  889.                         asynchronous operation of CPU and coprocessor. There
  890.                         have also been problems in the past with the CPU -
  891.                         coprocessor communication, causing the 83D87 to
  892.                         hang on some machines. The reason was that Cyrix
  893.                         shaved off a wait state in the communication protocol,
  894.                         which caused a communications breakdown between the
  895.                         CPU and the 83D87 for some systems running at 25 MHz
  896.                         or faster. One notable example of this behavior was
  897.                         the Intel 302 board. The problem is only rarely
  898.                         encountered with the current generation of 386
  899.                         motherboards. It is possible that the problem has
  900.                         been entirely eliminated in the 387+, the sucessor
  901.                         to the 83D87. To reduce power consumption the 83D87
  902.                         features advanced power saving features. Those
  903.                         portions of the coprocessor that are not needed
  904.                         are automatically shut down. If no coprocessor
  905.                         instructions are being executed, all parts except
  906.                         the bus interface unit are shut down [12]. Maximal
  907.                         power consumption of the Cyrix 83D87 at 33 MHz is
  908.                         1900 mW, typical power consumption at this clock
  909.                         frequency is 500 mW [15].
  910.  
  911.          Cyrix EMC87    is basically a special version of the Cyrix 83D87.
  912.                         In addition to the normal 387 operating mode, in
  913.                         which coprocessor-CPU communication is handled thru
  914.                         reserved IO-ports, it also offers a memory-mapped
  915.                         mode of operation similar to the operation principle
  916.                         of the Weitek Abacus. Please note that the EMC87 is
  917.                         *not* compatible with Weitek's Abacus coprocessor.
  918.                         They both use the same interface technique (memory
  919.                         mapping) but while the EMC87 uses the standard 387
  920.                         instruction set, the Weitek coprocessors use a
  921.                         different instruction set of their own. Like the
  922.                         Weitek Abacus, the EMC87 occupies a 64 kByte memory
  923.                         block starting at physical address C0000000h. It can
  924.                         therefore only be accessed in the protected or virtual
  925.                         modes of the 386 CPU. DOS programs can access the
  926.                         EMC87 with the help of DOS-extenders or memory
  927.                         managers like EMM386 which run in protected/virtual
  928.                         mode themself. Since the EMC87 provides also the
  929.                         standard CPU interface via IO-ports, it can be used
  930.                         just like any other 387 compatible coprocessor and
  931.                         delivers the same performance as the Cyrix 83D87 in
  932.                         this mode. However, using the memory mapped mode of
  933.                         the EMC87 provides a significant speed advantage.
  934.                         The traditional 387 CPU- coprocessor interface via
  935.                         IO-ports has an overhead of about 16-20 clock cycles.
  936.                         Since the Cyrix 83D87 executes some operations like
  937.                         addition and multiplication in much less time, its
  938.                         performance is limited by the CPU-coprocessor
  939.                         interface. The memory-mapped mode has much less
  940.                         overhead and allows all coprocessor instructions to
  941.                         be executed at full speed and with no penalty. For
  942.                         this reason, Cyrix introduced the EMC87 in 1990.
  943.                         In a test, the EMC87 at 33 MHz ran the single
  944.                         precision Whetstone benchmark at 7608 kWhetstones/sec,
  945.                         while the Cyrix 83D87 at 33 MHz had a speed of
  946.                         only 5049 kWhetstones/sec, an increase of 50.6% [63].
  947.                         In another test, the EMC87 ran a fractal computation
  948.                         at two times the speed of the Cyrix 83D87 and 2.6
  949.                         times as fast as an Intel 387DX [64]. A third test
  950.                         found the EMC87's overall performance to be 20%
  951.                         higher than the performance of the Cyrix 83D87
  952.                         [65]. The Cyrix FasMath EMC87 has also been sold
  953.                         as Cyrix AutoMATH by Cyrix. The two chips are 100%
  954.                         identical. Unlike the Cyrix 83D87, which fits into
  955.                         the 68-pin 387 coprocessor socket, the EMC87 comes
  956.                         in a 121-pin PGA and requires the 121-pin EMC
  957.                         (Extended Math Coprocessor) socket. Note that not
  958.                         all boards have such a socket, a notable exception
  959.                         being IBM's PS/2s, for example. Originally, Cyrix
  960.                         claimed support for the fast memory mapped mode of
  961.                         the EMC87 from a lot of software vendors (including
  962.                         Borland and Microsoft). However, there are only
  963.                         very few applications that make use of it, among
  964.                         them Evolution Computing's FastCAD 3D, MicroWay
  965.                         Inc.'s NDP FORTRAN-386 compiler and Intusofts's
  966.                         Spice [63]. I haven't seen the EMC being offered
  967.                         for about nine month now. It may be that Cyrix
  968.                         has discontinued this product due to lack of
  969.                         sufficient software support. The EMC87 was available
  970.                         in 25 and 33 MHz versions at the end of 1991.
  971.          Cyrix 387+     seems to be the successor to the Cyrix 83D87. On
  972.                         ordering a Cyrix coprocessor about a month ago,
  973.                         I was automatically supplied with a 387+. In my
  974.                         tests, I found the Cyrix 387+ to be about five
  975.                         to 10 percent *slower* than the Cyrix 83D87. However,
  976.                         some instructions like the square root (FSQRT) now
  977.                         ony run at half the speed at which they ran in the
  978.                         83D87 (see performance results below). I also found
  979.                         the transcendental functions on the 387+ to be a bit
  980.                         more accurate than those implemented in the 83D87.
  981.                         Why Cyrix has brought out a new coprocessor slower
  982.                         than the 83D87 I don't know. I have written to Cyrix
  983.                         about this question but haven't received a reply yet.
  984.                         Maybe the new coprocessor solves the one small
  985.                         hardware compatibility problem the 83D87 had (see
  986.                         above paragraph on the 83D87). It could also be that
  987.                         Cyrix had to design around the three Intel patents
  988.                         Intel claims the 83D87 has violated. I have no idea
  989.                         wether the Cyrix 387+ is to replace the 83D87 or
  990.                         if both chips will coexist in the market. Like the
  991.                         83D87, the 387+ is available for speeds of up to
  992.                         40 MHz.
  993.          Cyrix 83S87    is the SX version of the Cyrix 83D87. Just like the
  994.                         Cyrix 83D87 is the fastest 387 compatible coprocessor,
  995.                         the Cyrix 83S87 is the fastest of the 387SX compatible
  996.                         coprocessor [1]. Besides being the fastest 387SX
  997.                         'clone', the Cyrix 83S87 also features the most
  998.                         accurate transcendental functions. The 83S87 is
  999.                         packaged in a 68-pin PLCC  and is available in 16,
  1000.                         20 and 25 MHz versions. Due to the advanced power
  1001.                         saving features of the Cyrix coprocessor, the typical
  1002.                         power consumption of the 20 MHz version is about
  1003.                         350 mW [67].
  1004.          ULSI 83C87     is a 387 'clone' that came out in early 1991, well
  1005.                         after the IIT 3C87 and Cyrix 83D87. Like all clones,
  1006.                         it is somewhat faster than the Intel 387DX. Especially
  1007.                         the basic arithmetic functions are fast, while the
  1008.                         transcendental functions show only a slight speed
  1009.                         improvement over the Intel 387DX (see benchmark
  1010.                         results below). In my tests, the ULSI had the most
  1011.                         inaccurate transcendental functions. However, the
  1012.                         maximum relative error is still within the limits
  1013.                         set by Intel, so this is probably not an important
  1014.                         issue in all but very few applications. The ULSI
  1015.                         shows some minor flaws in the tests for IEEE-754
  1016.                         compatiblity, but this, too, is unimportant under
  1017.                         typical operating conditions. ULSI claims that the
  1018.                         program IEEETEST, which was used to test for IEEE
  1019.                         compatibility, contains many personal interpretations
  1020.                         of the IEEE standard by the program's author and
  1021.                         states that there is no ANSI-certified IEEE-754
  1022.                         complicency test. While this is most probably true,
  1023.                         it is also a fact that the IEEE test vectors used in
  1024.                         IEEETEST are sort of an industry standard and that
  1025.                         Intel's 387, 486, and RapidCAD chips pass it
  1026.                         without a single failure. Since the ULSI Math*Co
  1027.                         83C87 fails some of the tests, it is certainly less
  1028.                         than 100% compatible with Intel's chips, although
  1029.                         this will hardly make any difference in typical
  1030.                         operating conditions. The ULSI 83C87 is also not fully
  1031.                         compatible with the Intel 387DX in that is does
  1032.                         not implement the precision control feature of
  1033.                         Intel's coprocessor [58]. While all the internal
  1034.                         operations of 80x87 coprocessors are usually done
  1035.                         with the maximum precision available (double extended
  1036.                         presision with 64 mantissa bits), the 80x87 also
  1037.                         offer the possiblity to force lower precision to
  1038.                         be used for the basic arithmetic functions add,
  1039.                         subtract, multiply, divide, and square root. This
  1040.                         feature was included for compatiblity with existing
  1041.                         floating-point implementations at the time the 8087
  1042.                         was devised. All coprocessors except the ones from
  1043.                         ULSI support this feature. Since precision control
  1044.                         is rarely used, this incompatibility with the Intel
  1045.                         387DX does not pose major problems. IEEE-754 mentions
  1046.                         precision control, but requires it only for those
  1047.                         systems that don't have the possibility to store
  1048.                         single and double precision results. Therefore, the
  1049.                         standard does not call for precision control in the
  1050.                         387 coprocessor, so the ULSI 83C87's failure to
  1051.                         provide rounding control does not constitute a
  1052.                         conflict with the IEEE-754 standard for floating
  1053.                         point arithmetic. Like the other 387 'clones', the
  1054.                         83C87 does not support asynchronous operation of the
  1055.                         CPU and the coprocessor. This means that the 83C87
  1056.                         always runs at the full speed of the CPU. The ULSI
  1057.                         83C87 is available in 20, 25, 33, and 40 MHz versions.
  1058.                         The ULSI is produced in high perfromance, low power
  1059.                         CMOS. Power consumption at 20 MHz is max. 800 mW
  1060.                         (400 mW typical), at 25 MHz it is max. 1000 mW
  1061.                         (500 mW typical), at 33 MHz it is max. 1250 mW
  1062.                         (625 mW), and at 40 MHz the ULSI Math*Co 83C87
  1063.                         consumes max. 1500 mW (750 mW typical) [58]. The
  1064.                         83C87 is packaged in a 68-pin ceramic PGA. ULSI
  1065.                         coprocessors come with a lifetime warranty. ULSI
  1066.                         Systems, Inc. will replace the coprocessor up to
  1067.                         three times free of charge should it ever fail.
  1068.          ULSI 83S87     is the SX version of the ULSI 83C87 for operation
  1069.                         with an Intel 387SX or an AMD Am387SX. It is
  1070.                         functionally equivalent to the 83C87. To aid low
  1071.                         power laptop designs, the ULSI 83S87 features an
  1072.                         advanced power saving design with a sleep mode and
  1073.                         a standby mode with only minimal power requirements.
  1074.                         Power consumption under normal operating conditions
  1075.                         (dynamic mode) is max. 400 mW at 16 MHz (300 mW
  1076.                         typical), max. 450 mW at 20 MHz (350 mW typical),
  1077.                         and max. 500 mW at 25 MHz (400 mW typical) [58].
  1078.                         The ULSI 83S87 is packaged in a 68-pin PLCC.
  1079.          Intel RapidCAD is not a coprocessor, strictly seen, although it
  1080.                         is marketed as one. Rather, it is a CPU replacement.
  1081.                         It is basically an Intel 486DX without the cache and
  1082.                         with a 386 pinout. RapidCAD is delivered as a set of
  1083.                         two chips. RapidCAD-1 goes into the 386 socket and
  1084.                         contains the CPU and FPU, RapidCAD-2 goes into the
  1085.                         coprocessor socket and contains a PAL that generates
  1086.                         the Ferr signal that is normally generated by a
  1087.                         coprocessor and used by the motherboard circuitry to
  1088.                         provide 287 compatible coprocessor exception handling
  1089.                         in 386/387 systems. The RapidCAD instruction set is
  1090.                         compatible with the 386, so it doesn't know the 486
  1091.                         specific instructions like BSWAP. Since the RapidCAD
  1092.                         CPU core is very similar to 486 CPU core, most of the
  1093.                         register to register instructions execute in the same
  1094.                         number of clock cycles as on the 486. The use of the
  1095.                         386 bus interface causes instructions that access memory
  1096.                         to execute at about the same speed as on the 386. The
  1097.                         integer performance on the RapidCAD is definitely
  1098.                         limited by the low memory bandwidth provided by the
  1099.                         386 bus interface (2 clock cylces per bus cycle)
  1100.                         and the lack of an internal cache. CPU instructions
  1101.                         often execute faster than they can be fetched from
  1102.                         memory, even with a big and fast external cache.
  1103.                         Therefore, the integer performance of the RapidCAD
  1104.                         exceeds that of a 386 by at most 25%. This value
  1105.                         was derived by running some programs that use
  1106.                         mostly register-to-register operations and few
  1107.                         memory accesses. This finding is supported by the
  1108.                         SPEC ratings that Intel reports for the 386-33
  1109.                         and the RapidCAD-33. While the 386-33 has a
  1110.                         SPECint of 6.4, the RapidCAD has a SPECint of 7.3
  1111.                         [28], a 14% increase. Note that these tests used
  1112.                         the old (1989) SPEC benchmarks suite. While CPU
  1113.                         instructions often execute in one clock cycle on
  1114.                         the RapidCAD, FPU instructions always take more
  1115.                         than seven clock cycles. They are therefore rarely
  1116.                         slowed down by the low memory bandwidth provided
  1117.                         by the 386 bus interface. My tests show a 70%-100%
  1118.                         performance increase for floating-point intensive
  1119.                         benchmarks (see below) over a 386 based system
  1120.                         using the Intel 387DX math coprocessor. This is
  1121.                         consistent with the SPECfp rating reported by Intel.
  1122.                         The 386/387 at 33 MHz is rated at 3.3 SPECfp, while
  1123.                         the RapidCAD is rated at 6.1 SPECfp at the same
  1124.                         frequency, a 85% increase. This means that a system
  1125.                         that uses the RapidCAD is faster than any 386/387
  1126.                         combination, regardless of the type of 387 used
  1127.                         (Intel 387DX or faster clone). The diagnostic disk
  1128.                         for the RapidCAD also gives some application
  1129.                         performance data for the RapidCAD compared to the
  1130.                         Intel 387DX:
  1131.  
  1132.                         Application    Time w/ 387DX  Time w/ RapidCAD  Speedup
  1133.  
  1134.                         AUTOCAD 11            32 sec            52 sec      63%
  1135.                         AutoShade/Renderman  108 sec           180 sec      67%
  1136.                         Mathematica(Windows) 103 sec           139 sec      35%
  1137.                         SPSS/PC+ 4.01         14 sec            17 sec      21%
  1138.  
  1139.                         RapidCAD is available in 25 MHz and 33 MHz versions.
  1140.                         It is distributed through other channels than the
  1141.                         other Intel math coprocessors. Therefore, I have been
  1142.                         unable to obtain a data sheet for it. The RapidCad-1
  1143.                         chip gets quite hot when operating and it can be
  1144.                         assumed that its power consumption is similar to
  1145.                         the 486-33. Therefore, I recommend extra cooling
  1146.                         for this chip (see the paragraph below on the 486 for
  1147.                         details). The RapidCAD-1 is packaged in a 132-pin
  1148.                         PGA, just like the 80386, and the RapidCAD-2 is
  1149.                         packaged in a 68-pin PGA like a 80387 coprocessor.
  1150.          Intel 486DX    is not a coprocessor. This chip, brought out in
  1151.                         1989 functionally combines the CPU (a heavily pipelined
  1152.                         implementation of the 386 architecture) with an
  1153.                         enhanced 387 (the floating-point unit, FPU) and
  1154.                         8 kB of unified code/data cache on one chip. Of
  1155.                         course, this description is simplified, for a
  1156.                         detailed hardware description, see [52]. The
  1157.                         486DX offers about two to three times the integer
  1158.                         performance of a 386 at the same frequency.
  1159.                         Floating point performance is about three to four
  1160.                         times as high as on the Intel 387DX at the same
  1161.                         clock rate [29]. Since the FPU is on the same
  1162.                         chip as the CPU, the considerable communication
  1163.                         overhead between CPU and coprocessor in a 386/387
  1164.                         system is omitted, letting FPU instructions run
  1165.                         at the full speed permitted by the implementation.
  1166.                         The FPU also takes advantage of the on-chip cache
  1167.                         and the highly pipelined execution unit. Besides
  1168.                         the higher speed, the 486 FPU features more accurate
  1169.                         transcendental functions than the Intel 387DX
  1170.                         coprocessor according to tests run by me (see below).
  1171.                         To achieve better interrupt latency, FPU instructions
  1172.                         with a long execution time have been made abortable
  1173.                         in the case an interrupt occurs during their
  1174.                         execution. The concurrent execution of CPU and
  1175.                         coprocessor instructions typical for 80x86/80x87
  1176.                         systems is still in existence on the 486, but
  1177.                         some FPU instructions like FSIN have nearly no
  1178.                         concurrency with CPU instructions, indicating
  1179.                         that they make heavy use of both, CPU and FPU
  1180.                         resources [53, 1]. The 486DX comes in a 168 pin
  1181.                         ceramic PGA (pin grid array). It is available in
  1182.                         25 MHz and 33 Mhz versions. Since the end of 1991,
  1183.                         there is also a 50 MHz version available done in
  1184.                         a CHMOS V process (the 25 MHz and 33 MHz are
  1185.                         produced using the CHMOS IV process). Maximum
  1186.                         power consumption is 3500 mW for the 25 MHz 486
  1187.                         (2600 mW typical), 4500 mW for the 33 MHz version
  1188.                         (3500 mW typical), and 5000 mW (4000 mW typical)
  1189.                         for the 50 MHz chip. Due to the considerable amount
  1190.                         of heat produced by these chips, and taking into
  1191.                         consideration the slow air flow provided by the
  1192.                         fan in garden variety PC tower cases, I recommend
  1193.                         an extra fan directly above the CPU for safer
  1194.                         operation. If you measure the surface temperature
  1195.                         of an i486 in a normal tower case without extra
  1196.                         cooling after some time of operation, you may well
  1197.                         come up with something like 80 - 90 degrees Celsius
  1198.                         (that is 176 - 194 degrees Fahrenheit for those not
  1199.                         familiar with metric units) [54,55]. You don't need
  1200.                         the well known and expensive IceCap(tm) to effectively
  1201.                         cool your CPU. A simple fan mounted directly above
  1202.                         the CPU can bring the temperature down to about 50
  1203.                         to 60 degrees Celsius (122 - 140 degrees Fahrenheit)
  1204.                         depending on the room temperature and the temperature
  1205.                         within the PC case (which depends on the total power
  1206.                         dissipation of all the components and the cooling
  1207.                         provided by the fan in the power unit). According
  1208.                         to a simple rule known as Arrehnius' Law, lowering
  1209.                         the temperature by 10 degrees Celsius slows down
  1210.                         chemical reactions by a factor of two, thus lowering
  1211.                         the temperature of your CPU by 30 degrees should
  1212.                         prolong the live of the device by a factor of eight
  1213.                         due to the slower aging process. If you are reluctant
  1214.                         to add a fan to your system because of the additional
  1215.                         noise, settle for a low-noise fan like those
  1216.                         available from the German manufacturer Pabst (this
  1217.                         is not meant to be an advertisement. I am just the
  1218.                         happy owner of such a fan. Besides that, I have no
  1219.                         connections to the firm).
  1220.          Intel 486DX2   is the name for Intel latest generation of 486 CPUs.
  1221.                         Using the DX2 suffix instead of simply DX is meant
  1222.                         to be an indicator that these are clock-doubled
  1223.                         versions. A normal 486DX operates at the frequency
  1224.                         provided by the incoming clock signal. A 486DX2
  1225.                         generates a new clock signal from the incoming clock
  1226.                         by means of a PLL (phase locked loop). In the DX2,
  1227.                         this clock signal has twice the frequency of the
  1228.                         incoming clock, hence the name clock-doubler. All
  1229.                         internal parts of the 486DX2 (cache, CPU core, FPU)
  1230.                         run at this higher frequency. Only the bus interface
  1231.                         runs at the normal speed. That way, a 486DX-50 can
  1232.                         run on a motherboard designed for 25 MHz operation.
  1233.                         Since motherboards for 50 MHz operations are much
  1234.                         harder to design than those for 25 Mhz, this makes
  1235.                         a 486DX2-50 system easier to built and cheaper than
  1236.                         a 486DX-50 system. For all operations that don't
  1237.                         access off-chip resources (e.g. register operations)
  1238.                         a 486DX2-50 provides exactly the same performance as
  1239.                         a 486DX-50 and twice the performance of a 486DX-25.
  1240.                         However, since the main memory in a 486DX2-50 systems
  1241.                         still operates at 25 MHz, all instructions involving
  1242.                         memory accesses are potentially slower than in a
  1243.                         486DX-50 system, whose memory also runs at 50 Mhz.
  1244.                         The internal cache of the 486 helps this problem a
  1245.                         bit, but overall performance of a 486DX2-50 is still
  1246.                         lower than that of a 486DX-50, although Intel's
  1247.                         documentation [32] shows this drop to be quite small.
  1248.                         It depends a lot on the code one runs, though. The
  1249.                         nice thing about the 486DX2 is that it allows easy
  1250.                         upgrading of 25 and 33 Mhz 486 systems, since the
  1251.                         486DX2 is completely pin-compatible with the 486DX.
  1252.                         Just take out the 486DX and plug in the new 486DX2.
  1253.                         Note that power consumption of the 486DX2-50 equals
  1254.                         that of the 486DX-50 (4000 mW typical), and that the
  1255.                         486DX2-66 exceeds this by about 30%. These chips get
  1256.                         really hot in a standard PC case with no extra cooling.
  1257.                         See the above paragraph for more detailed information
  1258.                         on this problem.
  1259.          Intel 487SX    is the coprocessor intended for use in 486SX systems.
  1260.                         The 486SX is basically a 486DX without the floating-
  1261.                         point unit (FPU) [48, 50]. Originally Intel sold
  1262.                         486DXs with a defective FPU as 486SXs but it has
  1263.                         now completly removed the FPU part from the 486SX
  1264.                         mask for mass production. The introduction of the
  1265.                         486SX in 1991 has been viewed mainly as a marketing
  1266.                         'trick' by Intel to take market share from the 386
  1267.                         based systems once AMD became successful with their
  1268.                         Am386 (AMD has taken as much as 40% of the 386 market
  1269.                         due to some superior features such as higher clock
  1270.                         frequency, lower power consumption, and a fully
  1271.                         static design). A 486SX at 20 MHz delivers a bit
  1272.                         less integer performance than a 40 MHz Am386. To add
  1273.                         floating-point capabilities to a 486SX based system,
  1274.                         it would be easiest to swap the 486SX with a 486DX
  1275.                         which includes the FPU. However, Intel has prevented
  1276.                         this easy solution by giving the 486SX a slightly
  1277.                         different pin out [48, 51]. Since only three pins
  1278.                         are assigned differently, clever board manufacturers
  1279.                         have come out with boards that accept anything from
  1280.                         a 486SX-20 to a 486DX2-50 in their CPU socket and
  1281.                         provide a clean upgrade path this way. A set of
  1282.                         three jumpers ensures correct signal assignment to
  1283.                         the pins for either configuration. To upgrade systems
  1284.                         without this feature, one has to buy the 487SX and
  1285.                         put it into the "Performance Upgrade Socket" present
  1286.                         in most 486SX systems. Once the 487SX was available,
  1287.                         it was quickly found out that it is just a normal
  1288.                         486DX with a slightly different pin out [49]. Inserting
  1289.                         the 487SX effectively shuts down the 486SX in the
  1290.                         486SX/487SX system, so the 486SX could be removed
  1291.                         once the 487SX is installed. Since the shut down is
  1292.                         logical, not electrical, the 486SX still uses power
  1293.                         if used with the 487SX, although it is unoperational.
  1294.                         Technically speaking, the solution Intel chose was
  1295.                         the only practical way to provide a 486SX system with
  1296.                         the high level of floating-point performance the
  1297.                         486DX offers. The CPU and FPU have to be on the same
  1298.                         chip, otherwise the FPU can not make use of the cache
  1299.                         on the CPU chip and there would be considerable
  1300.                         overhead in CPU-FPU communication (similar to a
  1301.                         386/387 system), nullifying most of the arithmetic
  1302.                         speedups over the 387. That the 486SX, 487SX, and
  1303.                         486DX are not pin-compatible seems to be purely for
  1304.                         marketing reasons. To upgrade a 486SX based system,
  1305.                         Intel also offers the OverDrive chip, which is just
  1306.                         the same as a 487SX with internal clock doubling. It
  1307.                         goes also goes into the "Performance Upgrade Socket"
  1308.                         found in 486SX systems. The OverDrive roughly doubles
  1309.                         the performance of a 486SX/487SX based system. For a
  1310.                         explanation of clock doubling, see the description
  1311.                         of the 486DX2 above. As the 486SX, the 487SX is
  1312.                         available in 20 MHz and 25 MHz versions. At 20 MHz,
  1313.                         the 487SX has a power consumption of max. 4000 mW.
  1314.                         It is available in a 169 pin ceramic PGA (pin grid
  1315.                         array).
  1316.          Weitek 3167    was introduced in 1989 to provide the fastest
  1317.                         floating point performance possible on a 386 based
  1318.                         system at that time. The Weitek Abacus 3167 is not
  1319.                         a real coprocessor, strictly speaking, but rather
  1320.                         a memory mapped peripheral device. The Weitek 3167
  1321.                         was optimized for speed wherever possible. Besides
  1322.                         using the faster memory mapped interface to the CPU
  1323.                         (the 80x87 uses IO-ports), it does not support many
  1324.                         of the features of the 80x87 coprocessors, allowing
  1325.                         all of the chip's ressources to be concentrated on
  1326.                         the fast execution of the basic arithmetic operations.
  1327.                         For a more detailed description of the Weitek 3167 see
  1328.                         the first chapter of this document. In benchmark
  1329.                         comparisons, the Weitek 3167 provided up to 2.5 times
  1330.                         the performance of an Intel 387DX coprocessor. For
  1331.                         example, on a 33 MHz 3167 the Whetstone benchmark
  1332.                         performed at 7574 kWhetstones/sec compared with the
  1333.                         the 3743 kWhetstones/s for the Intel 387DX. Note
  1334.                         however that these are single precision results and
  1335.                         that the Weitek 3167's performance would drop to
  1336.                         about half the stated rate for double precision,
  1337.                         while the value for the Intel 387DX would not change
  1338.                         much. Anyhow, before the advent of the Intel RapidCAD,
  1339.                         the Weitek 3167 usually beat all 387 compatible
  1340.                         coprocessors even for double precision operations
  1341.                         [63,65,69]. For typical applications the advantage
  1342.                         of the Weitek 3167 over the 387 clones is much smaller.
  1343.                         In a benchmark test using AutoDesk's 3D-Studio the
  1344.                         Weitek 3167 performed at 123% of the Intel 487DX's
  1345.                         perfromance comapred with 106% for the Cyrix FasMath
  1346.                         83D87 and 118% for the Intel RapidCAD. The Weitek
  1347.                         Abacus 3167 is packaged in a 121-pin PGA that fits
  1348.                         into an EMC socket provided by most 386 based systems.
  1349.                         It does *not* fit into the normal coprocessor socket
  1350.                         designed to hold a 387 compatible coprocessor in a
  1351.                         68-pin PGA. To get the best of both worlds, one might
  1352.                         want to use a Weitek 3167 and a 387 compatible
  1353.                         coprocessor in the same system. These coprocessors
  1354.                         can coexist in the same system just fine. Only problem
  1355.                         is that most 386 based systems contain only one
  1356.                         coprocessor socket, usually of the EMC (extended math
  1357.                         coprocessor) type. Thus, you can install either a
  1358.                         387 coprocessor or a Weitek 3167, but not both. There
  1359.                         are little daughter boards available though that fit
  1360.                         into the EMC socket and provide two sockets, an EMC
  1361.                         and a standard coprocessor socket. At 25 MHz, the
  1362.                         Weitek 3167 has a power consumption of max. 1750 mW.
  1363.                         At 33 MHz, the max. power consumption is 2250 mW.
  1364.          Weitek 4167    is a memory mapped coprocessor that has the same
  1365.                         architecture as the 3167 and is designed to provide
  1366.                         486 based systems with the highest floating point
  1367.                         performance available. It executes coprocessor
  1368.                         instructions at three to four times the speed of
  1369.                         the Weitek 3167. Although it is up to 80% faster
  1370.                         than the Intel 468 in some benchmarks [1,69], the
  1371.                         performance advantage for real application is more
  1372.                         like 10%. The introduction of the 486DX2 processors
  1373.                         has more or less obliterated the need for a Weitek
  1374.                         4167, since the DX2 CPUs provide the same performance
  1375.                         and all the additional features the 80x87 has over
  1376.                         the Weitek Abacus. The Weitek 4167 is packaged in
  1377.                         a 142-pin PGA package that is only slightly smaller
  1378.                         than the 486's package. At 25 MHz, it has a max.
  1379.                         power consumption of 2500 mW [32].
  1380.  
  1381.          Chips & Technologies has shipped samples of their 38700 and
  1382.          38700SX coprocessors, which are compatible with the Intel 387DX
  1383.          and Intel 387SX coprocessors, respectively. Both have already
  1384.          been tested in [1]. However, C&T's German distributor (Rein
  1385.          Elektronik, Nettetal) states that these coprocessors will
  1386.          become generally available not before 4Q 1992. The samples
  1387.          tested in [1] showed about the same performance as the Cyrix
  1388.          83D87.
  1389.  
  1390.  
  1391.  
  1392.          Pricing
  1393.  
  1394.          Due to a recent price slashing by Cyrix and subsequently by Intel
  1395.          for 387 coprocessors, prices have dropped significantly for all
  1396.          287 and 387 compatible coprocessors with hardly any price difference
  1397.          between manufacturers. 387DX compatible coprocessors typically sell
  1398.          for ~US$ 100 for all speeds except for 40 MHz versions which are
  1399.          typically ~US$ 130. 387SX compatible coprocessors sell for ~US$ 90
  1400.          regardless of speed with the exception of the 33 MHz version, which
  1401.          are ~US$ 100. The Intel 287XL sells for ~US$ 100, while the IIT 2C87
  1402.          and Cyrix 82S87 sell for about US$ 70. 8087s may be more expensive,
  1403.          the price of an 8087-10 being US$ 150. I bought the Intel RapidCAD
  1404.          for US$ 320 and haven't seen it offered for a better price. I see
  1405.          the Weitek Abacus 3167-33 being offered for US$ 780 and the 4167-33
  1406.          being offered for US$ 1100. This price information reflects the
  1407.          price situation as of 08-14-92. Prices can be expected to drop
  1408.          slightly in the near future.
  1409.  
  1410.          If you have a demand for high floating-point performance, you
  1411.          should consider to buy a 486 based system rather than buying
  1412.          a 386 based system with an additional coprocessor. A 386 mother
  1413.          board for 33 MHz operation sell for ~ US$ 300, together with the
  1414.          coprocessor, costs total ~ US$ 400. A 486-33 ISA-board sells for
  1415.          US$ 650. While the 486-33 system is 60% more expensive than the
  1416.          386/387 system, it also provides 100% more integer and floating-
  1417.          point performance (twice the performance). If you want to push
  1418.          your 386 based system to maximum floating-point performance and
  1419.          can't switch to a 486 based system for some reason, I recommend
  1420.          the Intel RapidCAD. It is both faster [1] and cheaper than installing
  1421.          a Weitek Abacus 3167 with your 386, which used to be the highest
  1422.          performing combination before the RapidCAD came out. Similarily,
  1423.          the introduction of the 486DX2 clock-doubler chips have obliterated
  1424.          the need for a Weitek 4167 to get maximum floating-point performance
  1425.          out of a 486 based system. A 486DX2-66 performs at or above the
  1426.          performance level of a 33 Mhz Weitek 4167, even if the latter
  1427.          uses single precision rather than double precision. The 486DX-66
  1428.          is rated by Intel at 24700 double precision kWhetstones/sec and
  1429.          3.1 double precision Linpack MFLOPS. Of course, these benchmarks
  1430.          used the highest performance compilers available. But even with
  1431.          a Turbo Pascal 6.0 program, I managed to squeeze 1.6 double precision
  1432.          MFLOPS out of the 486DX2-66 for the LLL benchmark (for a description
  1433.          of the benchmarks mentioned, see the paragraph on benchmarks below).
  1434.          Although I haven't yet seen 486DX2-66 processors seen offered to
  1435.          the end users for upgrade purposes, I'll recommend the 486DX2-66
  1436.          to those that need highest floating-point performance and are
  1437.          planning on buying a new PC. The price difference between a
  1438.          33 MHz 486DX motherboard and a 486DX2-66 motherboard is around
  1439.          US$ 600, well below the price for the Weitek Abacus 4167.
  1440.  
  1441.  
  1442.  
  1443.          Operation
  1444.  
  1445.          In a 80x86/80x87 system CPU instructions and coprocessor
  1446.          instructions are executed concurrently. This means that
  1447.          the CPU can execute CPU instructions while the coprocessor
  1448.          executes a coprocessor instruction at the same time. The
  1449.          concurrency is restricted somewhat by the fact that the
  1450.          CPU has to aid the coprocessor in certain operations. As
  1451.          the CPU and the coprocessor are fed from the same instruction
  1452.          stream and both instruction streams may operate on the same
  1453.          data, there has to be a synchronizing mechanism between the
  1454.          CPU and the coprocessor.
  1455.  
  1456.          8086/8087 or 8088/8087 system, both of the chips look at the
  1457.          opcodes coming in from the bus. To do this, both chips have
  1458.          the same BIU (bus interface unit) and the 8086 BIU sends the
  1459.          status signals of its prefetch queue to the 8087 BIU. This
  1460.          assures that both processors always decode the same instructions
  1461.          in parallel. Since all coprocessor instruction start with the
  1462.          bit pattern 11011, it is easy for the 8087 to ignore all other
  1463.          instructions. Likewise the CPU ignores all coprocessor instructions
  1464.          except if they access memory. In this case, the CPU computes
  1465.          the address of the LSB (least significant byte) of the memory
  1466.          operand and does a dummy read. The 8087 then takes the data                                                                                    and does a dummy read.
  1467.          from the data bus. If more than one meory access is needed to
  1468.          load an memory operand, the 8087 requests the bus from the CPU,
  1469.          generates the consecutive addresses of the operand's bytes
  1470.          and fetches them from the data bus. After completing the operation,
  1471.          the 8087 hands bus control back to the CPU. Since 8087 and CPU
  1472.          are hooked up to the same synchronous bus, they have to run at
  1473.          the same speed. This means that with the 8087, only synchronous
  1474.          operation of CPU and coprocessor is possible. Another 8087
  1475.          coprocessor instruction can only be started if the previous one
  1476.          has been completed in the NEU (numerical execution unit) of the
  1477.          8087. To prevent the 8086 from decoding a new coprocessor
  1478.          instruction while the 8087 is still excuting the previous
  1479.          coprocessor instruction, the following mechanism is used: The
  1480.          compilers and assemblers automatically generate a WAIT instruction
  1481.          before each coprocessor instruction. The WAIT instruction tests
  1482.          the /TEST pin until its input becomes "LOW". In 8086/8087 systems,
  1483.          the 8086 /TEST pin is connected to the 8087 BUSY pin. As long
  1484.          as the NEU executes a coprocessor instruction, it forces its
  1485.          BUSY pin "HIGH". Thus the WAIT instruction in front of every
  1486.          coprocessor instruction stops the CPU until a still executing
  1487.          previous coprocessor instruction has finished. The same
  1488.          synchronization is used before the CPU accesses data that
  1489.          was written by the coprocessor. A WAIT instruction after the
  1490.          coprocessor instruction that writes to memory causes the CPU to
  1491.          stop until the coprocessor has transferred the data to memory,
  1492.          after which the CPU can safely access the data.
  1493.  
  1494.          With the help of an additional chip, the 8087 can also be inter-
  1495.          faced to the 80186 [36]. The 80186 was the CPU in some PCs (e.g.
  1496.          from Philips, Siemens) in the 1982/1983 time frame, but with
  1497.          the introduction of the IBM AT which used the 80286, it lost all
  1498.          significance for the PC market. The 80C186 (CMOS version of the
  1499.          80186) nowadays sells as an embedded controller and can be combined
  1500.          with a 80C187 coprocessor which is based on the internals of the
  1501.          Intel 387 [37].
  1502.  
  1503.          The 80287 CPU-interface is totally different from the solution
  1504.          used in the 8087. Since the 80286 implements memory protection
  1505.          via an MMU based on segmentation, it would have been much to
  1506.          expensive to duplicate the whole protection logic on the coprocessor
  1507.          for an interface solution similar to the 8087. In a 80286/80287
  1508.          system, the CPU fetches and stores all opcodes and operands for
  1509.          the coprocessor. Information is passed through ports F8h - FFh.
  1510.          As these ports are accessible under program control, care must
  1511.          be taken to not accidentally perform write operation to them, as
  1512.          this could corrupt the information in the math coprocessor.
  1513.          The execution unit of the 80287 is practically identical to that
  1514.          of the 8087, that is, nearly all coprocessor instructions execute
  1515.          in the same number of clock cycles on both coprocessors. Due to
  1516.          the additional overhead of the CPU/coprocessor interface (at
  1517.          least ~40 clock cycles), a 8 MHz 80286/80287 combination can be
  1518.          slower than a 8086/8087 system running at the same speed for
  1519.          floating point intensive programs. Additionally, most of the
  1520.          older 286 boards were configured to run the coprocessor at 2/3
  1521.          the speed of the CPU, making use of the ability of the 80287
  1522.          to run asynchronous with the CPU. The 80287 has a CKM pin that
  1523.          causes the incoming system clock to be divided by three for
  1524.          the coprocessor if it is tied to ground. The 80286 always
  1525.          divides the system clock by two internally. Thus the ratio 2/3.
  1526.          However, when the CKM (ClocK Mode) pin is tied high on the 80287,
  1527.          it does not divide the CLK input. This feature has been exploited
  1528.          by the maker of coprocessor speed sockets. These sockets tie
  1529.          CKM high and supply their own CLK signal with a built-in oscillator,
  1530.          thereby allowing the 80287 or compatible to run at a much higher
  1531.          speed than the CPU. With an IIT or Cyrix 287 one can have a
  1532.          20 MHz coprocessor running with a 8 MHz 80286. Note however that
  1533.          the floating-point performance in such a configuration does not
  1534.          scale linearly with the coprocessor clock, since all the data
  1535.          has to be passed through the much slower CPU. If the coprocessor
  1536.          executes mostly simple intructions such as addition and multiplication
  1537.          doubling the coprocessor clock in a 10 MHz system to 20 MHz does
  1538.          not show any performance increase at all [24]. The 80C287 by AMD
  1539.          is a 100% clone of the original Intel 80287, but is produced in
  1540.          CMOS not in NMOS as the original Intel chip. This makes for lower
  1541.          power consumption.
  1542.  
  1543.          The 80287XL, the Cyrix 82S87, and the IIT 2C87 contain the internals
  1544.          of a 387 coprocessor, but are pin-compatible to the original 287.
  1545.          However, these chips divide the system clock by two internally,
  1546.          as opposed to three in the original Intel 80287. Since the 80286
  1547.          also divides the system clock by two, they usually run synchronously
  1548.          with the CPU. They can also run asynchronously, though.
  1549.  
  1550.          The 8087/8087 combination can be characterized as a cooperation of
  1551.          partners with equal rights, while the 80286/287 is more a master-
  1552.          slave relationship. This makes synchronization much more easy, since
  1553.          the complete instruction and data flow of the coprocessor goes thru
  1554.          the CPU. Before executing most coprocessor instructions, the 80286
  1555.          tests its /BUSY pin which is hooked up to the 287 coprocessor and
  1556.          signals if the 80287 is still executing a previous coprocessor
  1557.          instruction or has encountered an exception. The 80286 then waits
  1558.          until the 80287 is not busy before loading the coprocessor instruction
  1559.          into the coprocessor. Therefore, a WAIT instruction before every
  1560.          coprocessor instruction is not required. These WAITs are permissible,
  1561.          but not necessary in 80287 programs. The second form of WAIT
  1562.          synchronisation after the coprocessor has written a memory operand is
  1563.          still necessary on 286/287 systems.
  1564.  
  1565.          The coprocessor interface in 80386/80387 systems is very similar to
  1566.          the one found in 286/287 systems. However, to prevent corruption
  1567.          of the coprocessor's contents by programming errors, the IO-ports
  1568.          800000F8 - 800000FF are used which are not user accessible. The
  1569.          interface has been optimized and uses 32-bit transfers. The overhead
  1570.          of the interface has been reduced to about 16-20 clock cycles. For
  1571.          some operations on the 387 'clones', that take less than 16 clock
  1572.          cycles to complete this effectively limits the execution rate of
  1573.          coprocessor instructions. The only sensible solution to provide
  1574.          even higher floating point performance was to integrate the CPU
  1575.          and coprocessor functionality onto the same chip. This is what
  1576.          Intel did with the 80486. The FPU in the 486 also benefits from
  1577.          the instruction pipelining and from the integrated cache.
  1578.  
  1579.  
  1580.  
  1581.          Performance
  1582.  
  1583.          Several computer magazines have published performance comparisons
  1584.          at the application level for the 387 coprocessors and Weitek's
  1585.          ABACUS 3167 and 4167 chips [1,25,68,70]. Applications tested included
  1586.          AutoCAD R11, RenderStar, Quattro Pro, Lotus 1-2-3, and AutoDesk's
  1587.          3D-Studio. For most tests, performance improvements for the 387
  1588.          clones over Intel's 387DX were small to marginal, the clones running
  1589.          the applications no more than 5% to 15% faster than the Intel 387DX.
  1590.          In the test of 3D-Studio, one of the few programs that supports
  1591.          the Weitek Abacus, the Weitek 3167 improved performance by 23%
  1592.          over an Intel 387DX and the 4167 improved performance by 10% over
  1593.          the 486 [1].
  1594.  
  1595.  
  1596.          The Intel Math Coprocessor Utilities Disk that accompanies the
  1597.          Intel 387DX coprocessor has a demonstration program that shows
  1598.          the speedup of certain application programs when run with the
  1599.          Intel coprocessor vs. a system with no coprocessor.
  1600.  
  1601.          Application      Time w/o 387   Time w/ 387  Speedup
  1602.  
  1603.          Art&Letters          87.0 sec      34.8 sec     150%
  1604.          Quattro Pro           8.0 sec       4.0 sec     100%
  1605.          Wingz                17.9 sec       9.1 sec      97%
  1606.          Mathematica         420.2 sec     337.0 sec      25%
  1607.  
  1608.  
  1609.          The following table is an excerpt from [70]:
  1610.  
  1611.          Application      Time w/o 387   Time w/ 387  Speedup
  1612.  
  1613.          Corel Draw          471.0 sec     416.0 sec      13%
  1614.          Freedom Of Press    163.0 sec      77.0 sec     112%
  1615.          Lotus 1-2-3         257.0 sec      43.0 sec     597%
  1616.  
  1617.  
  1618.          The following table is an excerpt from [25]:
  1619.  
  1620.          Application      Time w/o 387   Time w/ 387  Speedup
  1621.  
  1622.          Design CAD, Test1    98.1 sec      50.0 sec      96%
  1623.          Design CAD, Test2    75.3 sec      35.0 sec     115%
  1624.          Excel, Test 1         9.2 sec       6.8 sec      35%
  1625.          Excel, Test 1        12.6 sec       9.3 sec      35%
  1626.  
  1627.  
  1628.  
  1629.          The performance statistics below were put together with the
  1630.          help of four widely known numeric benchmarks and two benchmarks
  1631.          developed by me. Three Pascal programs, one FORTRAN program,
  1632.          and two assembly language program were used. The assembly language
  1633.          programs were linked with Turbo-Pascal 6.0 for library support,
  1634.          especially to include the coprocessor emulator of the TP 6.0
  1635.          run-time library. The Pascal programs were compiled with Turbo
  1636.          Pascal 6.0 from Borland International, a non-optimizing compiler
  1637.          that produces 16-bit code. The FORTRAN program was compiled using
  1638.          MS FORTRAN 5.0, an optimizing compiler that generates 16-bit
  1639.          code. All programs except PEAKFLOP and SAVAGE, which use double
  1640.          extended precision, use double precision variables. Note that
  1641.          using a highly optimizing compiler producing 32-bit code you
  1642.          will see much higher performance for some benchmarks. For example,
  1643.          Intel rates the 33 MHz 386/387DX at 3290 KWhetstones/sec and 0.4
  1644.          double precision LINPACK MFLOPS [28,29]. The 33 MHz Intel 486 is
  1645.          rated by Intel at 12300 KWhetstones/sec and 1.6 double precision
  1646.          LINPACK MFLOPS [30]. The compilers used in these benchmarks run by
  1647.          the chip vendor are the ones that give the highest performance
  1648.          available. These compilers are in the US$ 1000+ price range.
  1649.          Some of them may be experimental or prereleased versions not
  1650.          available to the general public. The relative performance of
  1651.          one coprocessor to another could vary depending on the code
  1652.          generated by compilers. Non-optimizing compilers tend to generate
  1653.          a high percentage of operations which access variables in memory,
  1654.          while optimizing compiler produce code that contains many
  1655.          operations involving registers. Thus it is well possible that
  1656.          coprocessor A beats coprocessor B running benchmark Z if compiled
  1657.          with compiler C, but B beats A when the same benchmark is compiled
  1658.          using compiler D. All benchmark in this overview were run from
  1659.          floppy under a 'bare-bones' MS-DOS 5.0 without the CONFIG.SYS
  1660.          and AUTOEXEC.BAT files. This way, it was made sure no TSR or
  1661.          other program unnecessarily stole computing resources from the
  1662.          benchmarks.
  1663.  
  1664.          Coprocessor performance also depends on the motherboard, or more
  1665.          specifically the chip set used on the motherboard. In [34] and [35]
  1666.          identically configured motherboards using different 386 chip sets
  1667.          were tested. Among other tests a coprocessor benchmark was run
  1668.          which is based on a fractal computation and its execution time
  1669.          recorded. The following tables showing coprocessor performance
  1670.          to vary with the chip set have been copied from these articles
  1671.          in abridged form.
  1672.  
  1673.                        Cyrix                                   Cyrix
  1674.          chip set      387+                 chip set           83D87
  1675.  
  1676.          Opti, 40 MHz  24.57 sec   97.0%    PC-Chips, 33 MHz  26.97 sec   93.0%
  1677.          Elite,40 MHz  24.46 sec   97.4%    UMC,      33 MHz  27.69 sec   90.5%
  1678.          ACT,  40 MHz  23.84 sec  100.0%    Headland, 33 MHz  25.08 sec  100.0%
  1679.          Forex,40 MHz  23.84 sec  100.0%    Eteq,     33 MHZ  27.38 sec   91.6%
  1680.  
  1681.          This shows that performance of the same coprocessor can vary by
  1682.          up to ~10% depending on the chip set used on your board, at least
  1683.          for 386 motherboards (similar numbers for 286, 386sx, and 486 are
  1684.          unfortunately not available). The benchmarks for this article were
  1685.          run on a board with the Forex chip set, which is one of the fastest
  1686.          386 chip sets there is, not only with respect to floating-point
  1687.          performance [35].
  1688.  
  1689.  
  1690.          Description of benchmarks
  1691.  
  1692.          PEAKFLOP is the kernel of a fractal computation. It consists
  1693.          mainly of a tight loop written in assembly code and fine tuned
  1694.          to give maximum performance. All variables are held in the
  1695.          CPU's and coprocessor's registers, so the only memory access
  1696.          is for opcode fetches. The main loop contains three multiplications
  1697.          and five additions/subtractions. This ratio is fairly typical
  1698.          for other floating point intensive programs as well. The whole
  1699.          program fits nicely into even a very small CPU cache. Due to
  1700.          the nature of this program, its MFLOPS rate is hardly to be
  1701.          exceeded by any program that calculates anything useful. Thus
  1702.          the name PEAKFLOP. You will find the source code for PEAKFLOP
  1703.          in appendix B.
  1704.  
  1705.          TRNSFORM multiplies an array of 8191 vectors with a 3D-transformation
  1706.          matrix (a 4x4 matrix). Each vector consists of four double precision
  1707.          values. Multiplying vectors with a matrix is a typical operation in
  1708.          the manipulation (e.g. rotation) of 3D objects which are made up from
  1709.          many vectors decribing the object. This benchmark stresses addition
  1710.          and multiplication as well as memory access. For each vector, 16
  1711.          multiplications and 12 additions are used. About 256 kByte of data
  1712.          is accessed during the benchmark. TRNSFORM is implemented as an
  1713.          optimized assembler program linked with the Turbo Pascal 6.0 library.
  1714.          For the IIT 3C87, a special version was written that makes use of
  1715.          the special F4X4 instruction available on that coprocessor. F4X4
  1716.          does a full multiplication of a 4x4 matrix by a 4x1 vector in a
  1717.          single instruction. The full source code for the TRNSFORM program is
  1718.          in appendix B.
  1719.  
  1720.          LLL is short for Lawrence Livermore Loops [21], a set of kernels
  1721.          taken from real floating point extensive programs. Some of these
  1722.          loops are vectorizable, but since we don't deal with vector
  1723.          processors here, this doesn't matter. For this test, LLL was
  1724.          adapted from the FORTRAN original [20] to Turbo Pascal 6.0. By
  1725.          variable overlaying (similar to FORTRAN's EQUIVALENCE statement)
  1726.          memory allocation for data was reduced to 64 kB, so all data fits
  1727.          into a single 64 kB segment. The older version of LLL is used here
  1728.          which contains 14 loops. There also exists a newer, more elaborate
  1729.          version consisting of 24 kernels. The kernels in LLL exercise only
  1730.          multiplication and addition. The MFLOPS rate reported is the
  1731.          average of the MFLOPS rate of all 14 kernels as reported by the
  1732.          LLL program. LLL and Whetstone results (see below) are reported
  1733.          as returned by my COMPTEST test program in which they have been
  1734.          included as a measure of coprocessor/FPU performance. COMPTEST
  1735.          has been compiled under Turbo Pascal 6.0 with all 'optimizations'
  1736.          on and using my own run-time library, which gives higher perfor-
  1737.          mance than the one included with TP 6.0. My library is available
  1738.          as TPL60N15.ZIP from garbo.uwasa.fi and ftp-sites that mirror
  1739.          this site.
  1740.  
  1741.          Linpack [5] is a well known floating-point benchmark that also
  1742.          heavily exercises the memory system. Linpack operates on large
  1743.          matrices and takes up about 570 kB in the version used for this
  1744.          test. This is about the largest program size a pure DOS system
  1745.          can accomodate. Linpack was originally designed to estimate
  1746.          performance of BLAS, a library of FORTRAN subroutines that
  1747.          handles various vector and matrix operations. It uses two routines
  1748.          from BLAS which are thought to be typical of the matrix operations
  1749.          used by BLAS. Both routines only use addition/subtraction and
  1750.          multiplication. The FORTRAN source code for Linpack can be
  1751.          obtained from the automated mail server netlib@ornl.gov. Linpack
  1752.          was compiled using MS Fortran 5.0 in the HUGE memory model (which
  1753.          can handle data structures larger than 64 kB) and with compiler
  1754.          switches set for maximum optimization. Linpack repeatedly does
  1755.          the same test. The number reported is the maximum MFLOPS rate
  1756.          returned by Linpack. Linpack MFLOPS ratings for a great number
  1757.          of machines are contained in [6]. This PostScript document is
  1758.          also available from netlib@ornl.gov.
  1759.  
  1760.          Whetstone [2,3,4] is a synthetic benchmark based upon statistics
  1761.          collected about the use of certain control and data structures
  1762.          in programs written in high level languages. Based on these
  1763.          statistics, Whetstone tries to mirror a 'typical' HLL program.
  1764.          Whetstone performance is expressed by how many theoretical
  1765.          'whetstone' instructions are executed per second. It was
  1766.          originally implemented in ALGOL. Unlike PEAKFLOP, LLL, and
  1767.          Linpack, Whetstone not only uses addition and multiplication
  1768.          but exercises all basic arithmetic operations as well as some
  1769.          transcendental functions. Whetstone performance depends on the
  1770.          speed of the coprocessor as well as on the speed of the CPU,
  1771.          while PEAKFLOP, LLL, and Linpack place a heavier burden on the
  1772.          coprocessor/FPU. There exists an old and a new version of
  1773.          Whetstone. Note that results from the two versions can differ
  1774.          by as much as 20% for the same test configuration. For this
  1775.          test, the new version in Pascal from [3] was used. It was
  1776.          compiled with Turbo Pascal 6.0 and my own library (see above)
  1777.          with all 'optimizations' on.
  1778.  
  1779.          SAVAGE tests the performance of transcendental function
  1780.          evaluation. It is basically a small loop in which the sin,
  1781.          cos, arctan, ln, exp, and sqrt functions are combined in a
  1782.          single expression. While sin, cos, arctan, and sqrt can be
  1783.          evaluated directly with a single 387 coprocessor instruction
  1784.          each, ln and exp need additional preprocessing for argument
  1785.          reduction and result conversion. According to [14], the Savage
  1786.          benchmark was devised by Bill Savage, and is distributed by:
  1787.          The Wohl Engine Company, Ltd., 8200 Shore Front Parkway,
  1788.          Rockaway Beach, NY 11693, USA. Usually, Savage is programmed
  1789.          to make 250,000 passes though the loop. Here only 10,000 loops
  1790.          are executed for a total of 60,000 transcendental function
  1791.          evaluations. The result is expressed in function evaluations
  1792.          per second. SAVAGE source code was taken from [7] and compiled
  1793.          with Turbo Pascal 6.0 and my own run-time library (see above).
  1794.  
  1795.  
  1796.          Benchmark results for 387 coprocessors, coprocessor emulators and
  1797.          the Intel RapidCAD and Intel 486 CPUs.
  1798.  
  1799.  
  1800.          40 MHz         PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  1801.                         MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  1802.  
  1803.          386, EM87      0.0084   0.0080   0.0060  0.0060         31      502 ##
  1804.          386, Franke387 0.0369   0.0295   0.0233  0.0215        164     4002 $$
  1805.          386, TP 6 Emu  0.0316   0.0273   0.0200  0.0190        160     3794 %%
  1806.          Intel 387DX    0.9204   0.7212   0.3932  0.3211       2428    52677
  1807.          ULSI 83C87     1.2093   0.7936   0.3890  0.3120       2528    56926
  1808.          IIT 3C87       1.0196   0.7145   0.3834  0.3179       2663    58766
  1809.          IIT 3C87,4x4   1.0196   1.7244   0.3834  0.3179       2663    58766 ??
  1810.          Cyrix 387+     1.1305   0.8162   0.3945  0.3208       2946    80322
  1811.          Intel RapidCAD 2.2128   1.8931   0.7377  0.5432       4810    86957
  1812.          Intel 486      2.4762   2.1335   1.1110  0.8204       6195    98522
  1813.  
  1814.  
  1815.          33.3 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  1816.                         MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  1817.  
  1818.          386, EM87      0.0070   0.0040   0.0050  0.0050         26      418 ##
  1819.          Franke387      0.0307   0.0246   0.0194  0.0179        137     3335 $$
  1820.          386, TP 6 Emu  0.0263   0.0227   0.0167  0.0158        133     3160 %%
  1821.          Intel 387DX    0.7647   0.6004   0.3283  0.2676       2046    43860
  1822.          ULSI 83C87     1.0097   0.6609   0.3239  0.2598       2089    47431
  1823.          IIT 3C87       0.8455   0.5957   0.3198  0.2646       2203    49020
  1824.          IIT 3C87,4X4   0.8455   1.4334   0.3198  0.2646       2203    49020 ??
  1825.          Cyrix 387+     0.9286   0.6806   0.3293  0.2669       2435    66890
  1826.          Cyrix 83D87    1.013       N/A   0.333   0.273        2550      N/A
  1827.          Intel RapidCAD 1.8572   1.5798   0.6072  0.4533       3953    72464
  1828.          Intel 486      2.0800   1.7779   0.9387  0.6682       5143    82192
  1829.  
  1830.          For comparison:
  1831.  
  1832.                         PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  1833.                         MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  1834.  
  1835.          i486DX2-66     4.1601   3.4227   1.6531  1.3010      10655   163934
  1836.          i486DX2-50     3.0589   2.6665   1.2537  0.9744       7962   123203
  1837.          i387, 20 MHz   0.2253   0.3271   0.1434  0.1171        952    21739 ++
  1838.          i387DX, 20 MHz 0.3567   0.4444   0.1484  0.1161       1034    24155 &&
  1839.          i80287, 5 MHz  0.0281   0.0310   0.0242  0.0222        150     3261 !!
  1840.          i8087,9.54 MHz 0.0636   0.0705   0.0321  0.0219        234     5782 **
  1841.  
  1842.          HW configuration for test of 387 coprocessors and Intel RapidCAD:
  1843.          System A: Motherboard with Forex chip set, 128 kB CPU Cache, 8 MB RAM
  1844.  
  1845.          HW configuration for test of 486 FPU (extra fan for 40 MHz operation):
  1846.          System B: Motherboard with SIS chip set, 256 kB CPU Cache, 8 MB RAM
  1847.  
  1848.          ## EM87 V1.2 by Ron Kimball is a public domain coprocessor emulator
  1849.             that loads as a TSR. It uses INT 7 traps emitted by 80286, 80386
  1850.             systems with no coprocessor upon encountering coprocessor
  1851.             instructions to catch coprocessor instructions and emulate them.
  1852.             Whetstone and Savage benchmarks for this test were compiled
  1853.             with the original TP 6.0 library, as EM87 chokes on the 387
  1854.             specific FSIN and FCOS instructions used in my own library if
  1855.             a 387 is detected. Obviously EM87 identifies itself as a 387,
  1856.             but has no support for 387 specific instructions.
  1857.          $$ Franke387 is a commercial 387 emulator that is also available in
  1858.             a shareware version. For this test, shareware version V2.4 was
  1859.             used. Franke387 unlike many other emulators supports all 387
  1860.             instructions. It is loaded as a device driver and uses INT 7
  1861.             to trap coprocessor instructions.
  1862.          %% These benchmarks were run using the built-in coprocessor emulators
  1863.             of the TP 6.0 and the MS FORTRAN 5.0 run-time libraries.
  1864.          ?? The 3C87 specific F4X4 instruction was used in the vector trans-
  1865.             formation benchmark.
  1866.          ++ Older motherboard with no chip set (discrete logic), no CPU cache,
  1867.             16 MB RAM
  1868.          && System A, CPU cache disabled via extended set-up, turbo-switch
  1869.             set to half speed (that is, 20 MHz)
  1870.          !! 80386 @ 20 MHz / Intel 80287 @ 5 MHz, no CPU cache, 4 MB RAM
  1871.             due to the fast CPU used here, performance figures are somewhat
  1872.             higher than can be expected for a 80286/287 combination, except
  1873.             for the PEAKFLOP benchmark, which is basically coprocessor limited
  1874.          ** 8086/8087 system with 640 kB RAM
  1875.  
  1876.  
  1877.          Since neither a Weitek coprocessor nor a compiler that generates
  1878.          code for the Weitek chips were available, performance data for
  1879.          the Weitek Abacus are given here according to [31,32] and scaled to
  1880.          show performance of a 33 MHz system. The benchmarks were compiled
  1881.          using highly optimizing 32-bit compilers.
  1882.  
  1883.                               Single Prec.     Double Prec.    Double Prec.
  1884.  
  1885.                               3167    4167     3167    4167      387    486
  1886.  
  1887.          Linpack MFLOPS        1.8     5.0      0.8     3.2      0.4    1.6
  1888.          Whetstone kWhet/sec  7470   22700     4900   14000     3290  12300
  1889.  
  1890.          Note that for the Intel coprocessors, running programs in single
  1891.          vs. double precision doesn't provide much of an performance advantage
  1892.          since all internal calculations are always done in extended precision.
  1893.          Using Weitek coprocessors however, performance nearly doubles when
  1894.          switching fron double to single precision. For double precision
  1895.          calculations using only basic arithmetic, the Weitek Abacus can
  1896.          provide performance at twice the level of the respective Intel
  1897.          coprocessor (387/486) clocked at the same speed at most.
  1898.  
  1899.  
  1900.          Speed of various coprocessor instructions measured in clock cycles
  1901.          as measured with my program 87TIMES. Error is +/- one clock cycle,
  1902.          except for the Intel 80287. Times for the 80287 were determined on
  1903.          a system with a 20 MHz 80386 and a 5 MHz Intel 80287. Therefore,
  1904.          times may differ from a genuine 80286/287 system, especially for
  1905.          those instructions that access an operand in memory. Since the
  1906.          times are stated as the number of coprocessor clock cycles used,
  1907.          the faster 386 which can execute four clock cycles where the 80287
  1908.          executes one clock cycle may decrease memory access times as seen
  1909.          by the coprocessor.
  1910.  
  1911.  
  1912.                            Intel  Intel  Cyrix Cyrix ULSI  IIT  Intel Intel
  1913.                            i486 RapidCAD 387+  83D87 83C87 3C87 387DX 80387
  1914.  
  1915.                     FLD1 |   5      7    17    17    17    22    27    35
  1916.                     FLDZ |   5      7    17    17    17    22    22    29
  1917.                    FLDPI |   8      9    17    17    17    22    37    45
  1918.                   FLDLG2 |   8      9    17    17    17    22    37    44
  1919.                   FLDL2T |   8      9    17    17    17    22    37    44
  1920.                   FLDL2E |   8      9    17    17    17    22    37    44
  1921.                   FLDLN2 |   8      9    17    17    17    22    37    45
  1922.                FLD ST(0) |   5      7    17    17    17    22    17    24
  1923.                FST ST(1) |   4      7    17    17    17    17    17    24
  1924.               FSTP ST(0) |   5      7    17    17    17    18    23    25
  1925.               FSTP ST(1) |   5      7    17    17    17    17    23    25
  1926.                FLD ST(1) |   5      7    17    17    17    22    17    25
  1927.               FXCH ST(1) |   5      7    17    17    17    22    22    25
  1928.              FILD [Word] |  13     16    35    36    41    46    46    65
  1929.             FILD [DWord] |  12     17    30    30    37    37    40    51
  1930.             FILD [QWord] |  13     20    40    40    47    47    45    66
  1931.              FLD [DWord] |   7     13    30    36    32    37    25    35
  1932.              FLD [QWord] |   7     15    40    44    42    47    35    45
  1933.              FLD [TByte] |  10     19    52    52    52    57    57    61
  1934.             FBLD [TByte] |  83     91    84    66   145   205    70   278
  1935.              FIST [Word] |  32     34    43    42    45    54    72    92
  1936.             FIST [DWord] |  33     35    48    44    48    57    74    91
  1937.              FST [DWord] |  11     14    44    42    49    41    46    47
  1938.              FST [QWord] |  16     18    56    54    60    53    58    60
  1939.             FISTP [Word] |  32     35    43    42    45    49    73    93
  1940.            FISTP [DWord] |  34     37    48    44    48    52    75    88
  1941.            FISTP [QWord] |  35     37    57    53    61    63    86    96
  1942.             FSTP [DWord] |  12     13    44    42    48    37    46    42
  1943.             FSTP [QWord] |  16     17    56    55    60    50    59    57
  1944.             FSTP [TByte] |  14     16    59    58    58    56    67    70
  1945.            FBSTP [TByte] | 171    175   101    98   126   216   147   535
  1946.                    FINIT |  18     35    18    18    18    18    19    25
  1947.                    FCLEX |   8     24    18    18    18    18    19    25
  1948.                     FCHS |   8     11    17    17    17    17    31    35
  1949.                     FABS |   6      8    17    17    17    17    28    31
  1950.                     FXAM |  13     15    17    17    17    17    37    40
  1951.                     FTST |   5      7    22    17    22    22    32    35
  1952.                   FSTENV |  68     85   127   127   135   127   162   169
  1953.                   FLDENV |  45     62   109   109   123   109   122   132
  1954.                    FSAVE | 160    172   359   359   366   377   467   504
  1955.                   FRSTOR | 131    206   361   361   369   367   424   453
  1956.              FSTSW [mem] |   4      7    16    16    17    16    17    22
  1957.                 FSTSW AX |   4      7    14    14    14    14    14    17
  1958.              FSTCW [mem] |   4      7    16    16    16    16    16    22
  1959.              FLDCW [mem] |   5     14    28    28    29    29    29    34
  1960.            FADD ST,ST(0) |   8      9    22    17    17    22    27    30
  1961.            FADD ST,ST(1) |   9     10    22    17    17    22    22    34
  1962.            FADD ST(1),ST |  10     10    22    17    17    22    23    35
  1963.           FADDP ST(1),ST |  11     11    22    17    17    22    23    34
  1964.             FADD [DWord] |   9     14    30    30    33    32    31    42
  1965.             FADD [QWord] |   9     16    40    40    43    42    41    51
  1966.             FIADD [Word] |  20     21    36    36    43    43    49    77
  1967.            FIADD [DWord] |  20     25    30    30    38    38    43    65
  1968.            FSUB ST(1),ST |  10     10    22    17    17    22    23    35
  1969.           FSUBR ST(1),ST |   9     10    22    17    20    25    27    35
  1970.          FSUBRP ST(1),ST |  10     10    22    17    17    22    23    35
  1971.             FSUB [DWord] |  11     14    30    30    32    32    30    41
  1972.             FSUB [QWord] |  11     16    40    40    42    43    40    51
  1973.             FISUB [Word] |  21     21    36    36    44    43    56    77
  1974.            FISUB [DWord] |  21     25    30    30    39    38    43    65
  1975.            FMUL ST,ST(1) |  16     17    22    22    22    27    38    56
  1976.            FMUL ST(1),ST |  16     17    22    22    22    27    40    60
  1977.           FMULP ST(1),ST |  16     17    22    22    22    27    38    59
  1978.             FIMUL [Word] |  22     23    36    36    50    43    50    77
  1979.            FIMUL [DWord] |  22     25    36    36    45    38    46    73
  1980.             FMUL [DWord] |  11     14    36    36    32    38    31    48
  1981.             FMUL [QWord] |  14     16    46    46    42    48    41    72
  1982.            FDIV ST,ST(0) |  73     74    38    23    52    57    92    95
  1983.            FDIV ST,ST(1) |  73     74    42    36    52    57    78    95
  1984.            FDIV ST(1),ST |  73     74    42    36    52    57    78    99
  1985.           FDIVR ST(1),ST |  73     74    42    36    53    57    77   100
  1986.          FDIVRP ST(1),ST |  73     74    42    36    52    57    78   101
  1987.             FIDIV [Word] |  84     85    61    54    79    73   105   144
  1988.            FIDIV [DWord] |  84     85    54    47    74    68   101   129
  1989.             FDIV [DWord] |  73     74    54    48    63    62    78   100
  1990.             FDIV [QWord] |  73     74    64    57    72    72    79   113
  1991.              FSQRT (0.0) |  26     28    17    17    17    22    27    35
  1992.              FSQRT (1.0) |  83     84    72    36    87    57   112   128
  1993.              FSQRT (L2T) |  86     87    72    36    87    57   102   133
  1994.            FXTRACT (L2T) |  17     17    22    17    32    76    56    68
  1995.            FSCALE (PI,5) |  30     31    22    36    47    77    57    80
  1996.             FRNDINT (PI) |  31     31    27    19    32    27    47    74
  1997.            FPREM (99,PI) |  58     60   102    52    57    52    77   100
  1998.            FPREM1(99,PI) |  90     91   102    57    62    52   102   119
  1999.                     FCOM |   5      7    17    17    27    17    27    34
  2000.                    FCOMP |   6      7    17    17    27    17    28    35
  2001.                   FCOMPP |   7      8    17    17    27    22    28    34
  2002.             FICOM [Word] |  16     20    36    36    49    37    61    77
  2003.            FICOM [DWord] |  18     25    30    30    44    32    48    61
  2004.             FCOM [DWord] |   7     14    30    30    33    32    31    35
  2005.             FCOM [QWord] |   7     15    40    40    43    42    41    51
  2006.               FSIN (0.0) |  25     27    97    17    17    22    37    45
  2007.               FSIN (1.0) | 310    314   162   116   492   222   512   593
  2008.                FSIN (PI) |  88     90   187   121    67   217   132   155
  2009.               FSIN (LG2) | 284    288    84    73   445   184   434   505
  2010.               FSIN (L2T) | 299    303   177   121   472   217   452   533
  2011.               FCOS (0.0) |  25     27   157    17    22    22    37    44
  2012.               FCOS (1.0) | 302    306   107    87   487   212   457   540
  2013.                FCOS (PI) |  89     92   257   151    62   222   197   230
  2014.               FCOS (LG2) | 300    304   152   106   452   192   502   584
  2015.               FCOS (L2T) | 307    311   242   156   467   222   507   598
  2016.            FSINCOS (0.0) |  26     29    17    17    22    31    41    54
  2017.            FSINCOS (1.0) | 353    357   172   126   492   416   536   637
  2018.             FSINCOS (PI) | 105    107   262   161    67   421   226   273
  2019.            FSINCOS (LG2) | 340    344   157   116   457   361   531   628
  2020.            FSINCOS (L2T) | 347    351   247   166   472   421   536   643
  2021.              FPTAN (0.0) |  26     28    17    17    22    31    36    43
  2022.              FPTAN (1.0) | 267    269   147   121   537   306   322   392
  2023.               FPTAN (PI) | 145    146   227   136   112   306   167   212
  2024.              FPTAN (LG2) | 244    246   132    91   502   276   297   363
  2025.              FPTAN (L2T) | 247    249   217   136   517   306   297   363
  2026.             FPATAN (0.0) |  39     41    27    22    22    27    97    92
  2027.             FPATAN (1.0) | 294    298   157   121   372   602   358   433
  2028.              FPATAN (PI) | 304    307   192   143   357   422   378   468
  2029.             FPATAN (LG2) | 289    293   157   126   362   382   373   447
  2030.             FPATAN (L2T) | 304    307   192   141   362   422   373   463
  2031.              F2XM1 (0.0) |  26     28    17    17    17    22    37    38
  2032.              F2XM1 (LN2) | 209    212   122    86   392   287   297   348
  2033.              F2XM1 (LG2) | 204    207   107    76   377   287   292   340
  2034.              FYL2X (1.0) |  60     60    42    36    72    92   112   127
  2035.               FYL2X (PI) | 294    297   162   111   452   357   393   497
  2036.              FYL2X (LG2) | 311    314   162   106   457   337   408   512
  2037.              FYL2X (L2T) | 293    296   162   111   437   357   393   496
  2038.            FYL2XP1 (LG2) | 334    337   167   101   462   282   433   533
  2039.  
  2040.  
  2041.  
  2042.                                          80386 +   80386 +  80386 +
  2043.                             Intel Intel  Franke387 TP 6.0   EM87
  2044.                             8087  80287  Emulator  Emulator Emulator
  2045.  
  2046.               FSTP ST(0) |   26     54     507       358      2115
  2047.                     FLD1 |   26     55     481       422      1626
  2048.                     FLDZ |   21     53     480       416      1646
  2049.                    FLDPI |   26     55     486       443      1626
  2050.                   FLDLG2 |   26     56     486       423      1626
  2051.                   FLDL2T |   26     55     486       440      1626
  2052.                   FLDL2E |   26     53     486       423      1626
  2053.                   FLDLN2 |   26     55     486       441      1626
  2054.                FLD ST(0) |   31     55     493       362      1851
  2055.                FST ST(1) |   26     54     489       355      1931
  2056.               FSTP ST(1) |   21     55     507       356      2116
  2057.                FLD ST(1) |   26     55     493       362      1852
  2058.               FXCH ST(1) |   21     57     497       486      2187
  2059.              FILD [Word] |   58     90     667       712      2259
  2060.             FILD [DWord] |   64     74     608       812      2164
  2061.             FILD [QWord] |   74     93     652       707      2971
  2062.              FLD [DWord] |   49     44     633       473      2077
  2063.              FLD [QWord] |   54     57     641       524      2336
  2064.              FLD [TByte] |   59     45     607       492      2063
  2065.             FBLD [TByte] |  309    310    2019      1512     17827
  2066.              FIST [Word] |   79     72     854       766      2418
  2067.             FIST [DWord] |   84     80     865       518      2325
  2068.              FST [DWord] |   89     85     686       441      2200
  2069.              FST [QWord] |   99     92     703       516      2481
  2070.             FISTP [Word] |   79     80     864       794      2620
  2071.            FISTP [DWord] |   79     81     879       541      2523
  2072.            FISTP [QWord] |   88     75     904       916      3226
  2073.             FSTP [DWord] |   89     75     713       467      2400
  2074.             FSTP [QWord] |   93     72     732       538      2678
  2075.             FSTP [TByte] |   49     21     685       467      2124
  2076.            FBSTP [TByte] |  528    472    3305      1555     27013
  2077.                    FINIT |   11     10     742       641      1369
  2078.                    FCLEX |   11     10     440       323       912
  2079.                     FCHS |   21     54     460       354      1744
  2080.                     FABS |   21     54     456       349      1738
  2081.                     FXAM |   21     54     481       380      1551
  2082.                     FTST |   51     75     585       386      2721
  2083.                   FSTENV |   54     57     928       519      2104
  2084.                   FLDENV |   48     50    1125       450      1631
  2085.                    FSAVE |  214    244    1949       976      2749
  2086.                   FRSTOR |  209    227    2182       657      2225
  2087.              FSTSW [mem] |   28     10     516       401      1189
  2088.                 FSTSW AX |  N/A     55     451       N/A       N/A
  2089.              FSTCW [mem] |   28     10     506       359      1167
  2090.              FLDCW [mem] |   19     47     524       437      1584
  2091.            FADD ST,ST(0) |   86    128     643       706      2805
  2092.            FADD ST,ST(1) |   85    116     707       808      3093
  2093.            FADD ST(1),ST |   92    131     664       812      3146
  2094.           FADDP ST(1),ST |   92    129     704       799      3143
  2095.             FADD [DWord] |  105    122     874       969      3139
  2096.             FADD [QWord] |  115    122     888      1021      3396
  2097.             FIADD [Word] |  115    122     940      1211      3330
  2098.            FIADD [DWord] |  125    122     882      1297      3215
  2099.            FSUB ST(1),ST |   88    130     738       817      3156
  2100.           FSUBR ST(1),ST |   96    132     740       868      3004
  2101.          FSUBRP ST(1),ST |   99    132     733       805      3301
  2102.             FSUB [DWord] |  119    122     918      1018      3127
  2103.             FSUB [QWord] |  129    123     932      1070      3632
  2104.             FISUB [Word] |  115    123     977      1081      3802
  2105.            FISUB [DWord] |  125    125     940       980      4161
  2106.            FMUL ST,ST(1) |  145    151     810      1368      3924
  2107.            FMUL ST(1),ST |  145    151     817      1377      3962
  2108.           FMULP ST(1),ST |  148    168     840      1365      4164
  2109.             FIMUL [Word] |  132    151    1039      1517      4039
  2110.            FIMUL [DWord] |  141    151     980      1643      3976
  2111.             FMUL [DWord] |  125    123     948      1480      3445
  2112.             FMUL [QWord] |  175    192     991      1602      4416
  2113.            FDIV ST,ST(0) |  201    207     726      1536      9789
  2114.            FDIV ST,ST(1) |  203    218     808      1658     10332
  2115.            FDIV ST(1),ST |  207    214     825      1655     10342
  2116.           FDIVR ST(1),ST |  201    206     819      1806     10213
  2117.          FDIVRP ST(1),ST |  201    205     845      1803     10409
  2118.             FIDIV [Word] |  237    227     980      1779     11225
  2119.            FIDIV [DWord] |  246    227     944      1680     11572
  2120.             FDIV [DWord] |  229    226     893      1722     10577
  2121.             FDIV [QWord] |  236    227     993      1777     10829
  2122.              FSQRT (0.0) |   21     57     512       382      1755
  2123.              FSQRT (1.0) |  186    206    1106      2504     37836
  2124.              FSQRT (L2T) |  186    207    1398      2467     37925
  2125.            FXTRACT (L2T) |   51     56     726       571      3326
  2126.            FSCALE (PI,5) |   41     56     817       443      3194
  2127.             FRNDINT (PI) |   51     58     808       800      7092
  2128.            FPREM (99,PI) |   81    131    1696       941      4098
  2129.            FPREM1(99,PI) |  N/A    N/A    1625       N/A       N/A
  2130.                     FCOM |   56     75     582       483      2799
  2131.                    FCOMP |   61     92     616       485      2983
  2132.                   FCOMPP |   61     90     661       476      3198
  2133.             FICOM [Word] |   79     77     808       861      3654
  2134.            FICOM [DWord] |   89     77     750       964      3684
  2135.             FCOM [DWord] |   74     75     741       625      3643
  2136.             FCOM [QWord] |   74     76     754       667      3771
  2137.               FSIN (0.0) |  N/A    N/A     639       N/A       N/A
  2138.               FSIN (1.0) |  N/A    N/A    4640       N/A       N/A
  2139.                FSIN (PI) |  N/A    N/A    2488       N/A       N/A
  2140.               FSIN (LG2) |  N/A    N/A    3911       N/A       N/A
  2141.               FSIN (L2T) |  N/A    N/A    3767       N/A       N/A
  2142.               FCOS (0.0) |  N/A    N/A     740       N/A       N/A
  2143.               FCOS (1.0) |  N/A    N/A    4777       N/A       N/A
  2144.                FCOS (PI) |  N/A    N/A    2557       N/A       N/A
  2145.               FCOS (LG2) |  N/A    N/A    4176       N/A       N/A
  2146.               FCOS (L2T) |  N/A    N/A    3905       N/A       N/A
  2147.            FSINCOS (0.0) |  N/A    N/A     714       N/A       N/A
  2148.            FSINCOS (1.0) |  N/A    N/A    6049       N/A       N/A
  2149.             FSINCOS (PI) |  N/A    N/A    4091       N/A       N/A
  2150.            FSINCOS (LG2) |  N/A    N/A    5640       N/A       N/A
  2151.            FSINCOS (L2T) |  N/A    N/A    5405       N/A       N/A
  2152.              FPTAN (0.0) |   41     58     752      8381      2324
  2153.              FPTAN (1.0) |  581    582    6366     10817     29824
  2154.               FPTAN (PI) |  606    587    4388     12410      2300
  2155.              FPTAN (LG2) |  516    513    5939     12502     26770
  2156.              FPTAN (L2T) |  576    586    5723     12483      2301
  2157.             FPATAN (0.0) |   41     55     616      1208     10578
  2158.             FPATAN (1.0) |  736    736    1426     13446     34208
  2159.              FPATAN (PI) |  206    207   12835     13305     46903
  2160.             FPATAN (LG2) |  756    736   12490     13319     41312
  2161.             FPATAN (L2T) |  206    204   12922     13364     50149
  2162.              F2XM1 (0.0) |   16     56     563       723      1722
  2163.              F2XM1 (LN2) |  631    624    4178     11070     33823
  2164.              F2XM1 (LG2) |  611    585    4798     11116     32163
  2165.              FYL2X (1.0) |   56     57     961      1214      4327
  2166.               FYL2X (PI) |  946    961    8987     12858     40148
  2167.              FYL2X (LG2) | 1081   1038    8933     12748     46821
  2168.              FYL2X (L2T) |  926    886    8982     12712     38986
  2169.            FYL2XP1 (LG2) | 1026   1037   10485     11867     44708
  2170.  
  2171.          The Weitek 3167 and 4167 processors only implement the basic
  2172.          arithmetic functions (add, subtract, multiply, divide, square
  2173.          root) in hardware. Transcendental functions are implemented
  2174.          by means of a software library supplied by Weitek that uses
  2175.          the Weitek hardware to approximate the transcendental functions
  2176.          with polynomial and rational approximations. The clock cycle
  2177.          timings for the transcendental functions are average values,
  2178.          since execution time differs with the value of argument. The
  2179.          speed of transcendental functions for the 4167 is estimated
  2180.          based on the numbers in [31,33], from which this timing
  2181.          information has been extracted.
  2182.  
  2183.  
  2184.          Execution time for floating-point operations in clock cycles on
  2185.          Weitek coprocessors
  2186.  
  2187.                   Single Precision         Double Precision
  2188.  
  2189.                   3167       4167          3167        4167
  2190.  
  2191.          ABS         3          2             3           2
  2192.          NEG         6          2             6           2
  2193.          ADD         6          2             6           2
  2194.          SUB         6          2             6           2
  2195.          SUBR        6          2             6           2
  2196.          MUL         6          2            10           3
  2197.          DIVR       38         17            66          31
  2198.          SQRT       60         17           118          31
  2199.          SIN       146        ~50           292        ~100
  2200.          COS       140        ~50           285        ~100
  2201.          TAN       188        ~60           340        ~110
  2202.          EXP       179        ~60           401        ~130
  2203.          LOG       171        ~60           365        ~120
  2204.          F->ASCII 1000        N/A          1700         N/A  //
  2205.          ASCII->F 1100        N/A          1800         N/A  //
  2206.  
  2207.          // rough average of the timings given for different numeric
  2208.             formats by Weitek. Note that these conversions routines
  2209.             do much more work than the FBLD and FBSTP instructions
  2210.             provided by the 80x87 coprocessors. FBLD and FBSTP are
  2211.             useful for conversion routines but quite a bit of additional
  2212.             code is need for this purpose.
  2213.  
  2214.  
  2215.          Accuracy
  2216.  
  2217.          The IEEE-754 Standard for Binary Floating-Point Arithmetic [10,11]
  2218.          is fully implemented by Intel's 387 coprocessor [17]. Among other
  2219.          things, this means that the add, subtract, multiply, divide,
  2220.          remainder, and square root operations always deliver the 'exact'
  2221.          result. By exact it is meant that the coprocessor always delivers
  2222.          the machine number closest to the real result, which may not
  2223.          be representable exactly in the available numeric format. The
  2224.          80387 implements the single, double, and double extended formats
  2225.          as specified in the standard as well as all functions required
  2226.          by it [17]. Note that earlier Intel coprocessors (the 8087 and
  2227.          the 80287) comply with a draft version of the standard that differs
  2228.          from the final version. These chips came out before the IEEE-754
  2229.          standard was finally accepted in 1985. As in the 80387, the basic
  2230.          arithmetic in the 8087 and the 80287 is exact in the sense that
  2231.          the computed result is always the machine number closest to the
  2232.          real result. However, there are some differences regarding certain
  2233.          operands like infinities and some operation like the remainder are
  2234.          defined differently. Some instructions have been added in the 80387,
  2235.          most notably the FSIN and FCOS operations. The argument range for
  2236.          some transcendental function has been extended [17]. Note that the
  2237.          IEEE-754 standard says nothing about the quality of the implementation
  2238.          of transcendental functions like sin, cos, tan, arctan, log. Intel
  2239.          uses a modified CORDIC [18,19] technique to compute the transcendental
  2240.          functions. Intel claims that maximum error in the 8087, 80287, and
  2241.          80387 for all transcendental functions does not exceeed two bits
  2242.          in the mantissa of the double extended format, which features 64
  2243.          mantissa bits for an accuracy of approximately 19 decimal places
  2244.          [22,23]. This claim has been independently verified by a competing
  2245.          vendor [13]. This means that at least 62 of the 64 mantissa bits
  2246.          in a transcendental function result are correct.
  2247.  
  2248.          The Weitek Abacus 3167 and 4167 are 'mostly compatible' with
  2249.          IEEE-754 [31,32,33]. It supports the single precision and double
  2250.          precision numeric formats formats described in the standard as
  2251.          well as the four rounding modes required by it. However, due to
  2252.          the need for extremely high speed operation, some of the finer
  2253.          points of IEEE-754 have not been implemented. One of the most
  2254.          notable omissions is the missing support for denormal numbers.
  2255.          Denormals are always flushed to zero.
  2256.  
  2257.          The 387 clone makers claim 100% compatibility with Intel's 80387.
  2258.          So one would expect the same accuracy from their chips. For example,
  2259.          on the packaging of the IIT 3C87 it says that ".. the requirements
  2260.          of ANSI/IEEE standards are fulfilled and exceeded". Cyrix states
  2261.          that their 83D87 complies fully with the IEEE-754 standard [12].
  2262.          Cyrix delivers with their copocessors some diagnostic software.
  2263.          This includes the program IEEETEST which is based on the IEEE test
  2264.          vectors from the Ph.D. thesis of Jerome T. Coonen [9]. A test using
  2265.          the IEEE test vectors has also been included into the RUNDIAG
  2266.          program on the Intel RapidCAD diagnostic disk. Rather than performing
  2267.          random tests, the test vectors check specific cases that may
  2268.          be hard to get right. Each test vector specifies the operation
  2269.          to be performed, the operands, precision and rounding mode to be
  2270.          used, and the result (including flags set) to be expected according
  2271.          to IEEE-754. I ran IEEETEST on all the available coprocessors/ FPUs.
  2272.          The Intel 486, Intel RapidCAD, Intel 387, Intel 387DX, Cyrix 83D87,
  2273.          and the Cyrix 387+ passed with no errors. The ULSI 83C87 showed
  2274.          some minor flaws in the FCOM, FDIV, FMUL, and FSCALE operations,
  2275.          getting flag errors in about 1% of the tested cases, but no
  2276.          computational errors. However, for the IIT 3C87, the IEEETEST
  2277.          program showed flag *and* some computational errors (that is, wrong
  2278.          results) for all tested operations except FXTRACT and FCHS. The Intel
  2279.          80287 shows numerous errors, but this it not surprising, since the
  2280.          80287 does not comply with IEEE-754 but with an earlier draft of that
  2281.          standard, so it does some thing differently than required by the final
  2282.          version of the standard.
  2283.  
  2284.          Although IEEETEST is written in Turbo Pascal, the coprocessor
  2285.          emulator in the TP 6.0 library could not be tested since IEEETEST
  2286.          was compiled with the $E- switch excluding the emulator from
  2287.          program code. The public domain emulator EM87 could be tested, but
  2288.          hung in the last test which checks the implementation of the
  2289.          remainder operation. This is probably caused by some bug in the
  2290.          emulation of the FPREM instruction tested in this test. It is
  2291.          interesting to note how the error profile of EM87 matches exactly
  2292.          that of the Intel 80287, so it can be assumed that EM87 is a very
  2293.          good emulation of the 80287. The Franke387 V2.4 emulator hung in
  2294.          the division test quite early in IEEETEST. The tests performed
  2295.          up to the division test reported several errors.
  2296.  
  2297.  
  2298.  
  2299.          Explanatory text printed at the start of the IEEETEST program:
  2300.  
  2301.          JT Coonen's 1984 UC Berkeley Ph.D. thesis centers around his
  2302.          activities as a member of the floating-point working group that
  2303.          defined the IEEE 754-1985 Standard for Binary Floating-Point
  2304.          Arithmetic. Appendix C of his thesis presents FPTEST, a Pascal
  2305.          program written by J Thomas and JT Coonen. IEEETEST is a port of
  2306.          FPTEST and runs on PCs whose math coprocessor accepts 80387
  2307.          compatible floating-point instructions.
  2308.  
  2309.          IEEETEST reads test vectors from the file TESTVECS and compares
  2310.          the answer returned by the math coprocessor with the answer listed
  2311.          in the test vector. If these answers differ an 'F' is displayed,
  2312.          otherwise a '.'is displayed. Answers can differ due to two types
  2313.          of failures: numeric failures or flag failures. Numeric failures
  2314.          occur when the computed answer has the wrong value. Flag failures
  2315.          occur when the status (invalid operation, divide by zero, underflow,
  2316.          overflow, inexact) is incorrectly identified.
  2317.  
  2318.          TESTVECS is the concatenation of unmodified versions of all the
  2319.          test vectors distributed by UC Berkeley. The test data base is
  2320.          copyrighted by UC Berkeley (1985) and is being distributed with
  2321.          their permission. FPTEST and the test data base can be obtained
  2322.          by asking for 'IEEE-754 Test Vector' from UC Berkeley, Electrical
  2323.          Engineering and Computer Science, Industrial Liaison Program,
  2324.          479 Corey Hall, Berkeley, CA, 94720 (415)643-6687.
  2325.  
  2326.          The initial version of this test data base for the proposed IEEE
  2327.          754 binary floating-point standard (draft 8.0) was developed for
  2328.          Zilog, Inc. and was donated to the floating-point working group
  2329.          for dissemination. Errors in or additions to the distributed data
  2330.          base should be reported to the agency of distribution, with copies
  2331.          to Zilog, Inc., 1315 Dell Avenue, Campbell, CA, 95008.
  2332.  
  2333.  
  2334.          IEEETEST output for Intel 80387, Intel 387DX, Intel 486,
  2335.                              Cyrix 83D87, Cyrix 387+, RapidCAD
  2336.  
  2337.          IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2338.                                |     TESTS     | numeric TYPE OF FAILURE flag
  2339.                 Operation Code | Passed Failed |    S    D    E |   S    D    E
  2340.          ----------------------------------------------------------------------
  2341.            Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2342.                  Addition    + |   3528      0 |    0    0    0 |   0    0    0
  2343.                Comparison    C |   4320      0 |    0    0    0 |   0    0    0
  2344.                 Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2345.                  Division    / |   4311      0 |    0    0    0 |   0    0    0
  2346.             Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  2347.                      Logb    L |    960      0 |    0    0    0 |   0    0    0
  2348.            Multiplication    * |   3978      0 |    0    0    0 |   0    0    0
  2349.                  Negation    - |    216      0 |    0    0    0 |   0    0    0
  2350.                Next After    N |   2832      0 |    0    0    0 |   0    0    0
  2351.          Round to Integer    I |    558      0 |    0    0    0 |   0    0    0
  2352.                     Scalb    S |    948      0 |    0    0    0 |   0    0    0
  2353.               Square Root    V |    744      0 |    0    0    0 |   0    0    0
  2354.               Subtraction    - |   3528      0 |    0    0    0 |   0    0    0
  2355.                 Remainder    % |   2984      0 |    0    0    0 |   0    0    0
  2356.                         Totals |  31235      0 |
  2357.  
  2358.  
  2359.          IEEETEST output for ULSI 83C87
  2360.  
  2361.          IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2362.                                |     TESTS     | numeric TYPE OF FAILURE flag
  2363.                 Operation Code | Passed Failed |    S    D    E |   S    D    E
  2364.          ----------------------------------------------------------------------
  2365.            Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2366.                  Addition    + |   3528      0 |    0    0    0 |   0    0    0
  2367.                Comparison    C |   4312      8 |    0    0    0 |   0    0    8
  2368.                 Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2369.                  Division    / |   4250     61 |    0    0    0 |  28   28    5
  2370.             Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  2371.                      Logb    L |    960      0 |    0    0    0 |   0    0    0
  2372.            Multiplication    * |   3936     42 |    0    0    0 |  19   19    4
  2373.                  Negation    - |    216      0 |    0    0    0 |   0    0    0
  2374.                Next After    N |   2828      4 |    0    0    0 |   0    0    4
  2375.          Round to Integer    I |    558      0 |    0    0    0 |   0    0    0
  2376.                     Scalb    S |    930     18 |    0    0    0 |   6    6    6
  2377.               Square Root    V |    744      0 |    0    0    0 |   0    0    0
  2378.               Subtraction    - |   3528      0 |    0    0    0 |   0    0    0
  2379.                 Remainder    % |   2984      0 |    0    0    0 |   0    0    0
  2380.                         Totals |  31102    133 |
  2381.  
  2382.  
  2383.          IEEETEST output for IIT 3C87
  2384.  
  2385.          IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2386.                                |     TESTS     | numeric TYPE OF FAILURE flag
  2387.                 Operation Code | Passed Failed |    S    D    E |   S    D    E
  2388.          ----------------------------------------------------------------------
  2389.            Absolute Value    A |    200     16 |    0    0   16 |   0    0    0
  2390.                  Addition    + |   3336    192 |    0    0  128 |   0    0   96
  2391.                Comparison    C |   4224     96 |    0    0   96 |   0    0    0
  2392.                 Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2393.                  Division    / |   4159    152 |    0    0  124 |   0    0  116
  2394.             Fraction Part    F |    600     24 |    0    0   24 |   0    0   24
  2395.                      Logb    L |    960      0 |    0    0    0 |   0    0    0
  2396.            Multiplication    * |   3702    276 |    0    0  248 |   0    0  100
  2397.                  Negation    - |    200     16 |    0    0   16 |   0    0    0
  2398.                Next After    N |   2248    584 |    0    0  584 |   0    0  168
  2399.          Round to Integer    I |    542     16 |    0    0    4 |   0    0   16
  2400.                     Scalb    S |    874     74 |    5    5   44 |   8    8   20
  2401.               Square Root    V |    688     56 |    0    0   56 |   0    0   56
  2402.               Subtraction    - |   3336    192 |    0    0  128 |   0    0   96
  2403.                 Remainder    % |   2844    140 |    0    0  140 |   0    0  116
  2404.                         Totals |  29401   1834 |
  2405.  
  2406.  
  2407.          IEEETEST output for Intel 80287 run together with a 80386 CPU
  2408.  
  2409.          IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2410.                                |     TESTS     | numeric TYPE OF FAILURE flag
  2411.                 Operation Code | Passed Failed |    S    D    E |   S    D    E
  2412.          ----------------------------------------------------------------------
  2413.            Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2414.                  Addition    + |   2886    642 |   16   16  112 | 174  174  174
  2415.                Comparison    C |      0   4320 | 1324 1324 1324 |1332 1332 1332
  2416.                 Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2417.                  Division    / |   3777    534 |   18   18   37 | 169  169  165
  2418.             Fraction Part    F |    552     72 |   24   24   24 |  24   24   24
  2419.                      Logb    L |    900     60 |   12   12   12 |  20   20   20
  2420.            Multiplication    * |   2944   1034 |  105  105  197 | 303  303  231
  2421.                  Negation    - |    216      0 |    0    0    0 |   0    0    0
  2422.                Next After    N |    348   2484 |  768  768  768 | 504  504  526
  2423.          Round to Integer    I |    546     12 |    0    0    0 |   4    4    4
  2424.                     Scalb    S |    663    285 |   45   43   26 | 102   98   46
  2425.               Square Root    V |    720     24 |    4    4    4 |   8    8    8
  2426.               Subtraction    - |   2886    642 |   16   16  112 | 174  174  174
  2427.                 Remainder    % |    708   2276 |  768  768  560 | 216  216  216
  2428.                         Totals |  18850  12385 |
  2429.  
  2430.  
  2431.          IEEETEST output for EM87 coprocessor emulator run on a Intel 386 CPU
  2432.  
  2433.          IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2434.                                |     TESTS     | numeric TYPE OF FAILURE flag
  2435.                 Operation Code | Passed Failed |    S    D    E |   S    D    E
  2436.          ----------------------------------------------------------------------
  2437.            Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2438.                  Addition    + |   2886    642 |   16   16  112 | 174  174  174
  2439.                Comparison    C |      0   4320 | 1324 1324 1324 |1332 1332 1332
  2440.                 Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2441.                  Division    / |   3777    534 |   18   18   37 | 169  169  165
  2442.             Fraction Part    F |    552     72 |   24   24   24 |  24   24   24
  2443.                      Logb    L |    900     60 |   12   12   12 |  20   20   20
  2444.            Multiplication    * |   2944   1034 |  105  105  197 | 303  303  231
  2445.                  Negation    - |    216      0 |    0    0    0 |   0    0    0
  2446.                Next After    N |    348   2484 |  768  768  768 | 504  504  526
  2447.          Round to Integer    I |    546     12 |    0    0    0 |   4    4    4
  2448.                     Scalb    S |    663    285 |   45   43   26 | 102   98   46
  2449.               Square Root    V |    720     24 |    4    4    4 |   8    8    8
  2450.               Subtraction    - |   2886    642 |   16   16  112 | 174  174  174
  2451.  
  2452.  
  2453.          To complement the checks done by IEEETEST I wrote some short
  2454.          programs DENORMTS, RCTRL, PCTRL in Turbo Pascal 6.0 that test
  2455.          the following features:
  2456.  
  2457.          1. support for denormals in all precisions (single, double, extended)
  2458.          2. support for the four IEEE rounding modes (up, down, nearest, chop)
  2459.          3. support for precision control
  2460.  
  2461.          Note that 1) and 2) are required for IEEE conformance, while 3)
  2462.          is required for compatibility with Intel's coprocessors. Precision
  2463.          control forces the results of the FADD, FSUB, FMUL, FDIV, and FSQRT
  2464.          instruction to be rounded to the specified precision (single, double,
  2465.          double extended). This feature is provided to obtain compatibility
  2466.          with certain programming languages [17]. By specifying lower
  2467.          precision, one effectively nullifies the advantages of extended
  2468.          precision intermediate results. The programs that test precision
  2469.          control and rounding control are designed to return a different
  2470.          result for each of the modes for the same sequence of operation.
  2471.          The source code of the programs can be found in appendix A. The
  2472.          Intel 8087 and 80287 were not tested with DENORMTS since Turbo
  2473.          Pascal does not support extended precision denormals on 8087/80287
  2474.          processors, so the denormal test fails anyway. The 8087 and 287
  2475.          pass the RCTRL and PCTRL tests, though.
  2476.  
  2477.  
  2478.          These are the results for the Intel 387, Intel 387DX, Intel 486,
  2479.          Intel RapidCAD, Cyrix 83D87, Cyrix 387+, and the EM87 emulator
  2480.          (on a 80386 machine)
  2481.  
  2482.          Precision Control           SINGLE   1.13311278820037842E+0000
  2483.                                      DOUBLE   1.23456789006442125E+0000
  2484.                                      EXTENDED 1.23456789012337585E+0000
  2485.  
  2486.          Rounding Control            NEAREST -1.23427629010100635E+0100
  2487.                                      DOWN    -1.23427623555772409E+0100
  2488.                                      UP      -1.23457760966801097E+0100
  2489.                                      CHOP    -1.23397493540770643E+0100
  2490.  
  2491.          Denormal support
  2492.  
  2493.          SINGLE denormals supported
  2494.          SINGLE denormal prints as:    4.60943116855005E-0041
  2495.          Denormal should be printed as 4.60943...E-0041
  2496.  
  2497.          DOUBLE denormals supported
  2498.          DOUBLE denormal prints as:    8.75000000000016E-0311
  2499.          Denormal should be printed as 8.75...E-0311
  2500.  
  2501.          EXTENDED denormals supported
  2502.          EXTENDED denormal prints as:  1.31640625000000E-4934
  2503.          Denormal should be printed as 1.3164...E-4934
  2504.  
  2505.  
  2506.          These are the results for the ULSI 83C87
  2507.  
  2508.          Precision Control           SINGLE   1.23456789012337585E+0000
  2509.                                      DOUBLE   1.23456789012337585E+0000
  2510.                                      EXTENDED 1.23456789012337585E+0000
  2511.  
  2512.          Rounding Control            NEAREST -1.23427629010100635E+0100
  2513.                                      DOWN    -1.23427623555772409E+0100
  2514.                                      UP      -1.23457760966801097E+0100
  2515.                                      CHOP    -1.23397493540770643E+0100
  2516.  
  2517.          Denormal support
  2518.  
  2519.          SINGLE denormals supported
  2520.          SINGLE denormal prints as:    4.60943116855005E-0041
  2521.          Denormal should be printed as 4.60943...E-0041
  2522.  
  2523.          DOUBLE denormals supported
  2524.          DOUBLE denormal prints as:    8.75000000000016E-0311
  2525.          Denormal should be printed as 8.75...E-0311
  2526.  
  2527.          EXTENDED denormals supported
  2528.          EXTENDED denormal prints as:  1.31640625000000E-4934
  2529.          Denormal should be printed as 1.3164...E-4934
  2530.  
  2531.  
  2532.          These are the results for the IIT 3C87
  2533.  
  2534.          Precision Control           SINGLE   1.13311278820037842E+0000
  2535.                                      DOUBLE   1.23456789006442125E+0000
  2536.                                      EXTENDED 1.23456789012337585E+0000
  2537.  
  2538.          Rounding Control            NEAREST -1.23427629010100635E+0100
  2539.                                      DOWN    -1.23427623555772409E+0100
  2540.                                      UP      -1.23457760966801097E+0100
  2541.                                      CHOP    -1.23397493540770643E+0100
  2542.  
  2543.          Denormal support
  2544.  
  2545.          SINGLE denormals supported
  2546.          SINGLE denormal prints as:    4.60943116855005E-0041
  2547.          Denormal should be printed as 4.60943...E-0041
  2548.  
  2549.          DOUBLE denormals supported
  2550.          DOUBLE denormal prints as:    8.75000000000016E-0311
  2551.          Denormal should be printed as 8.75...E-0311
  2552.  
  2553.          EXTENDED denormals not supported
  2554.  
  2555.  
  2556.          These are the results for the TP 6.0 coprocessor emulator:
  2557.  
  2558.          Precision Control           SINGLE   1.23456789012351396E+0000
  2559.                                      DOUBLE   1.23456789012351396E+0000
  2560.                                      EXTENDED 1.23456789012351396E+0000
  2561.  
  2562.          Rounding Control            NEAREST -1.23457766383395931E+0100
  2563.                                      DOWN    -1.23457766383395931E+0100
  2564.                                      UP      -1.23457766383395931E+0100
  2565.                                      CHOP    -1.23457766383395931E+0100
  2566.  
  2567.          Denormal support
  2568.  
  2569.          SINGLE denormals not supported
  2570.          DOUBLE denormals not supported
  2571.          EXTENDED denormals not supported
  2572.  
  2573.  
  2574.          The test results show that the IIT 3C87 does not conform to the
  2575.          IEEE-754 floating-point standard in that it does not support
  2576.          denormals in double extended precision. The ULSI 83C87 is not
  2577.          Intel 387 compatible in that it does not support precision control,
  2578.          but allways uses double extended precision. The TP 6.0 emulator
  2579.          supports neither precision control, rounding control nor support
  2580.          for any denormals. In addition, its basic arithmetic operations
  2581.          do not seem to conform to the IEEE standard as the results of
  2582.          the test programs differ from that of any result computed by a
  2583.          coprocessor for any mode.
  2584.  
  2585.  
  2586.          With regard to the accuracy of transcendental functions, Cyrix
  2587.          claims that the relative error of the transcendental functions
  2588.          on the 83D87 never exceeds 0.5 units in the last place (0.5 ULP)
  2589.          of the double extended format [13]. This means that the maximum
  2590.          relative error is below 2**-64, while Intel's published error
  2591.          limit is 2**-62. While Intel uses a modified CORDIC algorithm
  2592.          [18,19] to compute the transcendental functions, Cyrix uses
  2593.          rational approximations that utilize a very fast array multiplier.
  2594.          For an explanation why this approach is superior to CORDIC with
  2595.          todays technology, see [61]. Also, Cyrix uses an internal 75 bit
  2596.          data path for the mantissa [15], so intermediate computations in
  2597.          the generation of transcendental function values will enjoy some
  2598.          additional accuracy over the 64 bits provided by the double
  2599.          extended format. Using 75 mantissa bits also provides an advantage
  2600.          over other coprocessors like the Intel 387DX and ULSI 83C87 which
  2601.          use only a 68 bit data path for the mantissa [58,59]. Note that a
  2602.          maximum relative error of 0.5 ULP for the Cyrix coprocessor does
  2603.          not mean that it returns the 'exact' result (machine number closest
  2604.          to infinitely precise result) all the time. Just consider the case
  2605.          where the infinitely precise result of a transcendental function
  2606.          falls nearly half way between two machine numbers. A relative error
  2607.          of 0.5 ULP can cause the result to be either of the numbers after
  2608.          rounding, depending on the direction of the error. But the 83D87
  2609.          should deliver results that never differ from the 'exact' result
  2610.          by more than one ULP. Cyrix also claims that its transcendental
  2611.          functions satisfy the monotonicity criterion [13], a claim not
  2612.          made by any of the competitors. Monotonicity means that for all
  2613.          x1 > x2, it always follows that f(x1) >= f(x2) for an increasing
  2614.          function like sin on [0..pi/4]. Likewise, for a decreasing
  2615.          function like cos on [0..pi/4], for all x1 > x2, it follows that
  2616.          f(x1) <= f(x2).
  2617.  
  2618.          The Weitek Abacus 3167 and 4167 implement only the basic arithmetic
  2619.          operations (add, subtract, negate, multiply, divide, square root)
  2620.          in hardware. Transcendental functions are provided via a software
  2621.          library provided by Weitek. For these library functions Weitek
  2622.          claims a maximum relative error of 5 ULPs [31,33] (ULP = Unit in
  2623.          the Last Place, numeric weight of the least significant mantissa
  2624.          bit). This means that the last three bits in the mantissa of a
  2625.          double precision result can be wrong. Note that the Intel 387 and
  2626.          compatible math coprocessors generate the transcendental functions
  2627.          with a small relative error with regard to the _extended double
  2628.          precision_ format. Thus, when rounded to double precision, their
  2629.          function values are nearly always 'exact'. 387 type coprocessors
  2630.          have superior accuracy when compared with Weitek's coprocesssors.
  2631.  
  2632.          The test diskette distributed with early versions of the
  2633.          Cyrix 83D87 contained a program TRANCK that checks the
  2634.          accuracy of the transcendental functions in the coprocessor
  2635.          against a more precise software arithmetic [16]. I used this
  2636.          program to compare the accuracy of the transcendental functions
  2637.          on those 287/387/486 coprocessors/FPUs available to me. As TRANCK
  2638.          will not accept negative numbers as intervall limits, I tested
  2639.          each function on an intervall along the positive x-axis. The
  2640.          functions tested are F2XM1 (2**x-1), FSIN (sine), FCOS (cosine),
  2641.          FPTAN (tangent), FPATAN (arctangent), FYL2X (y * log2 (x)),
  2642.          and FYL2XP1 (y * log2 (x+1)). These are all the transcendental
  2643.          functions implemented on the 80387. Note that the square root
  2644.          (FSQRT) is *not* a transcendental function. For every function,
  2645.          100,000 arguments were evaluated. The arguments were uniformally
  2646.          distributed within the intervall tested. The EM87 emulator could
  2647.          not be checked with TRANCK, since the multiple precision package
  2648.          in TRANCK would always return with an error message immediately.
  2649.          However, the Franke387 could be tested and
  2650.  
  2651.  
  2652.          Test results for accuracy of transcendental functions for double
  2653.          extended precision as returned by the program TRANCK. 100,000
  2654.          trials per function.
  2655.  
  2656.          %wrong      is the percentage of results that differ from the 'exact'
  2657.                      result (infinitely precise result rounded to 64 bits)
  2658.          ULP_hi      is the number of results where the returned result was
  2659.                      greater than the 'exact' (correctly rounded) result by
  2660.                      one ULP (the numeric weight of the last mantissa bit,
  2661.                      2**-64 to 2**-63 depending of the size of the number).
  2662.          ULPs_hi     is the number of results where the returned result was
  2663.                      greater than the 'exact' result by two or more ULPs.
  2664.          ULP_lo      is the number of results where the returned result was
  2665.                      smaller than the 'exact' (correctly rounded) result by
  2666.                      one ULP (the numeric weight of the last mantissa bit,
  2667.                      2**-64 to 2**-63 depending of the size of the number).
  2668.          ULPs_lo     is the number of results where the returned result was
  2669.                      smaller than the 'exact' result by two or more ULPs.
  2670.          max ULP err is the maximum deviation of a returned result from the
  2671.                      'exact' answer expressed in ULPs.
  2672.  
  2673.  
  2674.          Franke387 V2.4 emulator
  2675.                                                                  max
  2676.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2677.  
  2678.          SIN    0,pi/4      39.042  25301     708  13029       4       2
  2679.          COS    0,pi/4      75.714  49827   25887      0       0       3
  2680.          TAN    0,pi/4      76.976  14230   10029  24323   28394       9
  2681.          ATAN   0,1         55.826  26028    1529  24044    4225       4
  2682.          2XM1   0,0.5       96.717      0       0  47910   48807       5
  2683.          YL2XP1 0,sqrt(2)-1 93.007    578       9  27416   65004       8
  2684.          YL2X   0.1,10      62.252  16817    4712  37082    3641    2953
  2685.  
  2686.  
  2687.          INTEL 80287
  2688.                                                                  max
  2689.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2690.  
  2691.          SIN    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  2692.          COS    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  2693.          TAN    0,pi/4      37.001  18756     524  17405     316       2
  2694.          ATAN   0,1          9.666   6065       0   3601       0       1
  2695.          2XM1   0,0.5       19.920      0       0  19920       0       1
  2696.          YL2XP1 0,sqrt(2)-1  7.780    868       0   6912       0       1
  2697.          YL2X   0.1,10       1.287    723       0    564       0       1
  2698.  
  2699.  
  2700.          INTEL 387
  2701.                                                                  max
  2702.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2703.  
  2704.          SIN    0,pi/4      28.872   2467       0  26392      13       2
  2705.          COS    0,pi/4      27.213  27169      35      9       0       2
  2706.          TAN    0,pi/4      10.532    441       0  10091       0       1
  2707.          ATAN   0,1          7.088   2386       0   4691       1       2
  2708.          2XM1   0,0.5       32.024      0       0  32024       0       1
  2709.          YL2XP1 0,sqrt(2)-1 22.611   3461       0  19150       0       1
  2710.          YL2X   0.1,10      13.020   6508       0   6512       0       1
  2711.  
  2712.  
  2713.          INTEL 387DX
  2714.                                                                  max
  2715.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2716.  
  2717.          SIN    0,pi/4      28.873   2467       0  26393      13       2
  2718.          COS    0,pi/4      27.121  27090      22      9       0       2
  2719.          TAN    0,pi/4      10.711    457       0  10254       0       1
  2720.          ATAN   0,1          7.088   2386       0   4691       1       2
  2721.          2XM1   0,0.5       32.024      0       0  32024       0       1
  2722.          YL2XP1 0,sqrt(2)-1 22.611   3461       0  19150       0       1
  2723.          YL2X   0.1,10      13.020   6508       0   6512       0       1
  2724.  
  2725.  
  2726.          ULSI 83C87
  2727.                                                                  max
  2728.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2729.  
  2730.          SIN    0,pi/4      35.530   4989       6  30238     297       2
  2731.          COS    0,pi/4      43.989  11193     675  31393     728       2
  2732.          TAN    0,pi/4      48.539  18880    1015  26349    2295       3
  2733.          ATAN   0,1         20.858     62       0  20796       0       1
  2734.          2XM1   0,0.5       21.257      4       0  21253       0       1
  2735.          YL2XP1 0,sqrt(2)-1 27.893   9446       0  18213     234       2
  2736.          YL2X   0.1,10      13.603   9816       0   3787       0       1
  2737.  
  2738.  
  2739.          IIT 3C87
  2740.                                                                  max
  2741.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2742.  
  2743.          SIN    0,pi/4      18.650  11171      0    7479       0       1
  2744.          COS    0,pi/4       7.700   3024      0    4676       0       1
  2745.          TAN    0,pi/4      20.973   9681      0   11291       1       2
  2746.          ATAN   0,1         19.280  13186      0    6094       0       1
  2747.          2XM1   0,0.5       25.660  17570      0    8090       0       1
  2748.          YL2XP1 0,sqrt(2)-1 45.830  23503   1896   19654     777       3
  2749.          YL2X   0.1,10      10.888   5638    357    4845      48       3
  2750.  
  2751.  
  2752.          CYRIX 83D87
  2753.                                                                  max
  2754.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2755.  
  2756.          SIN    0,pi/4       1.554   1015      0     539       0       1
  2757.          COS    0,pi/4       0.925    143      0     782       0       1
  2758.          TAN    0,pi/4       4.147    881      0    3266       0       1
  2759.          ATAN   0,1          0.656    229      0     427       0       1
  2760.          2XM1   0,0.5        2.628   1433      0    1194       0       1
  2761.          YL2XP1 0,sqrt(2)-1  3.242    825      0    2417       0       1
  2762.          YL2X   0.1,10       0.931    256      0     675       0       1
  2763.  
  2764.  
  2765.          CYRIX 387+
  2766.                                                                  max
  2767.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2768.  
  2769.          SIN    0,pi/4       1.486    864       0    622       0       1
  2770.          COS    0,pi/4       2.072     12       0   2060       0       1
  2771.          TAN    0,pi/4       0.602     63       0    539       0       1
  2772.          ATAN   0,1          0.384     12       0    372       0       1
  2773.          2XM1   0,0.5        1.985     27       0   1958       0       1
  2774.          YL2XP1 0,sqrt(2)-1  3.662   1705       0   1957       0       1
  2775.          YL2X   0.1,10       0.764    367       0    397       0       1
  2776.  
  2777.  
  2778.          INTEL RapidCAD, Intel 486
  2779.                                                                  max
  2780.          funct. intervall   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  2781.  
  2782.          SIN    0,pi/4      16.991   1517       0  15474       0       1
  2783.          COS    0,pi/4       9.003   7603       0   1400       0       1
  2784.          TAN    0,pi/4      10.532    441       0  10091       0       1
  2785.          ATAN   0,1          7.078   2386       0   4691       1       2
  2786.          2XM1   0,0.5       32.025      0       0  32025       0       1
  2787.          YL2XP1 0,sqrt(2)-1 21.800    533       0  21267       0       1
  2788.          YL2X   0.1,10       3.894   1879       0   2015       0       1
  2789.  
  2790.  
  2791.          The test results above indicate that all 80x87 compatibles do not
  2792.          exceed Intel's stated error bound of 3 ULPs for the transcendental
  2793.          functions. However, some coprocessors are more accurate than others.
  2794.          Rating the coprocessors according to the accuracy of their trans-
  2795.          cendental functions gives the following list (highest accuracy
  2796.          first): Cyrix 387+, Cyrix 83D87, Intel 486, Intel RapidCAD, Intel
  2797.          80287(!), Intel 387DX, Intel 80387, IIT 3C87, ULSI 83C87. The tests
  2798.          also show that the problems with excessive inaccuracy of the trans-
  2799.          cendental functions in early versions of the IIT coprocessors with
  2800.          errors of up to 8 ULPs [8] have been eliminated. According to [56],
  2801.          certain problems with the FPATAN instruction on the IIT 3C87 occuring
  2802.          under the UNIX version of AutoCAD have been corrected in June, 1990.
  2803.          The Franke387 has acceptable accuracy for the FSIN, FCOS, and FPATAN
  2804.          instructions, taking into consideration that according to its
  2805.          documentation, Franke387 uses only 64 bits of precision for the
  2806.          intermediate results, while coprocessorsa typically use 68 bits
  2807.          and more. However, the larger error in the FPTAN, F2XM1, FYL2XP1,
  2808.          and especially the FYL2X operations show that the emulator doesn't
  2809.          use state of the art algorithms, which ensure an error of only a
  2810.          very few ULPs even if no extra precise intermediate results are
  2811.          available.
  2812.  
  2813.          References
  2814.  
  2815.          [1]  Schnurer, G.: Zahlenknacker im Vormarsch.
  2816.               c't 1992, Heft 4, Seiten 170-186
  2817.          [2]  Curnow, H.J.; Wichmann, B.A.: A synthetic benchmark.
  2818.               Computer Journal, Vol. 19, No. 1, 1976, pp. 43-49
  2819.          [3]  Wichmann, B.A.: Validation code for the Whetstone benchmark.
  2820.               NPL Report DITC 107/88, National Physics Laboratory, UK,
  2821.               March 1988
  2822.          [4]  Curnow, H.J.: Wither Whetstone? The Synthetic Benchmark after
  2823.               15 Years.
  2824.               In: Aad van der Steen (ed.): Evaluating Supercomputers.
  2825.               London: Chapman and Hall 1990
  2826.          [5]  Dongarra, J.J.: The Linpack Benchmark: An Explanation.
  2827.               In: Aad van der Steen (ed.): Evaluating Supercomputers.
  2828.               London: Chapman and Hall 1990
  2829.          [6]  Dongarra, J.J.: Performance of Various Computers Using Standard
  2830.               Linear Equations Software.
  2831.               Report CS-89-85, Computer Science Department, University of
  2832.               Tennessee, March 11, 1992
  2833.          [7]  Huth, N.: Dichtung und Wahrheit oder Datenblatt und Test.
  2834.               Design & Elektronik 1990, Heft 13, Seiten 105-110
  2835.          [8]  Ungerer, B.: Sockelfolger.
  2836.               c't 1990, Heft 4, Seiten 162-163
  2837.          [9]  Coonen, J.T.: Contributions to a Proposed Standard for Binary
  2838.               Floating-Point Arithmetic
  2839.               Ph.D. thesis, University of California, Berkeley, 1984
  2840.          [10] IEEE: IEEE Standard for Binary Floating-Point Arithmetic.
  2841.               SIGPLAN Notices, Vol. 22, No. 2, 1985, pp. 9-25
  2842.          [11] IEEE Standard for Binary Floating-Point Arithmetic.
  2843.               ANSI/IEEE Std 754-1985.
  2844.               New York, NY: Institute of Electrical and Electronics
  2845.               Engineers 1985
  2846.          [12] FasMath 83D87 Compatibility Report. Cyrix Corporation, Nov. 1989
  2847.               Order No. B2004
  2848.          [13] FasMath 83D87 Accuracy Report. Cyrix Corporation, July 1990
  2849.               Order No. B2002
  2850.          [14] FasMath 83D87 Benchmark Report. Cyrix Corporation, June 1990
  2851.               Order No. B2004
  2852.          [15] FasMath 83D87 User's Manual. Cyrix Corporation, June 1990
  2853.               Order No. L2001-003
  2854.          [16] Brent, R.P.: A FORTRAN multiple-precision arithmetic package.
  2855.               ACM Transactions on Mathematical Software, Vol. 4, No. 1,
  2856.               March 1978, pp. 57-70
  2857.          [17] 387DX User's Manual, Programmer's Reference. Intel Corporation,
  2858.               1989
  2859.               Order No. 231917-002
  2860.          [18] Volder, J.E.: The CORDIC Trigonometric Computing Technique.
  2861.               IRE Transactions on Electronic Computers, Vol. EC-8, No. 5,
  2862.               September 1959, pp. 330-334
  2863.          [19] Walther, J.S.: A unified algorithm for elementary functions.
  2864.               AFIPS Conference Proceedings, Vol. 38, SJCC 1971, pp. 379-385
  2865.          [20] Esser, R.; Kremer, F.; Schmidt, W.G.: Testrechnungen auf der
  2866.               IBM 3090E mit Vektoreinrichtung.
  2867.               Arbeitsbericht RRZK-8803, Regionales Rechenzentrum an der
  2868.               Universit"at zu Köln, Februar 1988
  2869.          [21] McMahon, H.H.: The Livermore Fortran Kernels: A test of the
  2870.               numerical performance range.
  2871.               Technical Report UCRL-53745, Lawrence Livermore National
  2872.               Laboratory, USA, December 1986
  2873.          [22] Nave, R.: Implementation of Transcendental Functions on a Numerics
  2874.               Processor.
  2875.               Microprocessing and Microprogramming, Vol. 11, No. 3-4,
  2876.               March-April 1983, pp. 221-225
  2877.          [23] Yuen, A.K.: Intel's Floating-Point Processors.
  2878.               Electro/88 Conference Record, Boston, MA, USA, 10-12 May 1988,
  2879.               pp. 48/5-1 - 48/5-7
  2880.          [24] Stiller, A.; Ungerer, B.: Ausgerechnet.
  2881.               c't 1990, Heft 1, Seiten 90-92
  2882.          [25] Rosch, W.L.: Handfeste Hilfe oder Seifenblase?
  2883.               PC Professionell, Juni 1991, Seiten 214-237
  2884.          [26] Intel 80286 Hardware Reference Manual. Intel Corporation, 1987
  2885.               Order No.210760-002
  2886.          [27] AMD 80C287 80-bit CMOS Numeric Processor. Advanced Micro Devices,
  2887.               June 1989
  2888.               Order No. 11671B/0
  2889.          [28] Intel RapidCAD(tm) Engineering CoProcessor Performance Brief.
  2890.               Intel Corporation, 1992
  2891.          [29] i486(tm) Microprocessor Performance Report. Intel Corporation,
  2892.               April 1990
  2893.               Order No. 240734-001
  2894.          [30] Intel486(tm) DX2 Microprocessor Performance Brief. Intel
  2895.               Corporation, March 1992
  2896.               Order No. 241254-001
  2897.          [31] Abacus 3167 Floating-Point Coprocessor Data Book. Weitek
  2898.               Corporation, July 1990
  2899.               DOC No. 9030
  2900.          [32] WTL 4167 Floating-Point Coprocessor Data Book. Weitek
  2901.               Corporation, July 1989
  2902.               DOC No. 8943
  2903.          [33] Abacus Software Designer's Guide. Weitek Corporation,
  2904.               September 1989
  2905.               DOC No. 8967
  2906.          [34] Stiller, A.: Cache & Carry.
  2907.               c't 1992, Heft 6, Seiten 118-130
  2908.          [35] Stiller, A.: Cache & Carry, Teil 2.
  2909.               c't 1992, Heft 7, Seiten 28-34
  2910.          [36] Palmer, J.F.; Morse, S.P.: Die mathematischen Grundlagen der
  2911.               Numerik-Prozessoren 8087/80287.
  2912.               München: tewi 1985
  2913.          [37] 80C187 80-bit Math Coprocessor Data Sheet. Intel Corporation,
  2914.               September 1989
  2915.               Order No. 270640-003
  2916.          [38] IIT-2C87 80-bit Numeric Co-Processor Data Sheet. IIT, May 1990
  2917.          [39] Engineering note 4x4 matrix multiply transformation. IIT, 1989
  2918.          [40] Tscheuschner, E.: 4 mal 4 auf einen Streich.
  2919.               c't 1990, Heft 3, Seiten 266-276
  2920.          [41] Goldberg, D.: Computer Arithmetic.
  2921.               In: Hennessy, J.L.; Patterson, D.A.: Computer Architecture A
  2922.               Quantitative Approach. San Mateo, CA: Morgan Kaufmann 1990
  2923.          [42] 8087 Math Coprocessor Data Sheet. Intel Corporation, October 1989,
  2924.               Order No. 205835-007
  2925.          [43] 8086/8088 User's Manual, Programmer's and Hardware Reference.
  2926.               Intel Corporation, 1989
  2927.               Order No. 240487-001
  2928.          [44] 80286 and 80287 Programmer's Reference Manual. Intel Corporation,
  2929.               1987
  2930.               Order No. 210498-005
  2931.          [45] 80287XL/XLT CHMOS III Math Coprocessor Data Sheet. Intel
  2932.               Corporation, May 1990
  2933.               Order No. 290376-001
  2934.          [46] Cyrix FasMath(tm) 82S87 Coprocessor Data Sheet. Cyrix Coporation,
  2935.               1991
  2936.               Document 94018-00 Rev. 1.0
  2937.          [47] IIT-3C87 80-bit Numeric Co-Processor Data Sheet. IIT, May 1990
  2938.          [48] 486(tm)SX(tm) Microprocessor/ 487(tm)SX(tm) Math CoProcessor
  2939.               Data Sheet. Intel Corporation, April 1991.
  2940.               Order No. 240950-001
  2941.          [49] Schnurer, G.: Die gro"se Verlade.
  2942.               c't 1991, Heft 7, Seiten 55-57
  2943.          [50] Schnurer, G.: Eine 4 f"ur alle.
  2944.               c't 1991, Heft 6, Seite 25
  2945.          [51] Intel486(tm)DX Microprocessor Data Book. Intel Corporation,
  2946.               June 1991
  2947.               Order No. 240440-004
  2948.          [52] i486(tm) Microprocessor Hardware Reference Manual. Intel
  2949.               Corporation, 1990
  2950.               Order No. 240552-001
  2951.          [53] i486(tm) Microprocessor Programmer's Reference Manual. Intel
  2952.               Corporation, 1990
  2953.               Order No. 240486-001
  2954.          [54] Ungerer, B.: Kalte H"ute.
  2955.               c't 1992, Heft 8, Seiten 140-144
  2956.          [55] Ungerer, B.: Hei"se Sache.
  2957.               c't 1991, Heft 4, Seiten 104-108
  2958.          [56] Rosch, W.L.: Handfeste Hilfe oder Seifenblase?
  2959.               PC Profesionell, Juni 1991, Seiten 214-237
  2960.          [57] Niederkr"uger, W.: Lebendige Vergangenheit.
  2961.               c't 1990, Heft 12, Seiten 114-116
  2962.          [58] ULSI Math*Co Advanced Math Coprocessor Technical Specification.
  2963.               ULSI System, 5/92, Rev. E
  2964.          [59] 387(tm)DX Math CoProcessor Data Sheet. Intel Corporation,
  2965.               September 1990.
  2966.               Order No. 240448-003
  2967.          [60] 387(tm) Numerics Coprocessor Extension Data Sheet. Intel
  2968.               Corporation, February 1989.
  2969.               Order No. 231920-005
  2970.          [61] Koren, I.; Zinaty, O.: Evaluating Elementary Functions in a
  2971.               Numerical Coprocessor Based on Rational Approximations.
  2972.               IEEE Transactions on Computers, Vol. C-39, No. 8, August 1990,
  2973.               pp. 1030-1037
  2974.          [62] 387(tm) SX Math CoProcessor Data Sheet. Intel Corporation,
  2975.               November 1989
  2976.               Order No. 240225-005
  2977.          [63] Frenkel, G.: Coprocessors Speed Numeric Operations.
  2978.               PC-Week, August 27, 1990
  2979.          [64] Schnurer, G.; Stiller, A.: Auto-Matt.
  2980.               c't 1991, Heft 10, Seiten 94-96
  2981.          [65] Grehan, R.: FPU Face-Off.
  2982.               Byte, November 1990, pp. 194-200
  2983.          [66] Tang, P.T.P.: Testing Computer Arithmetic by Elementary Number
  2984.               Theory. Preprint MCS-P84-0889, Mathematics and Computer Science
  2985.               Division, Argonne National Laboratory, August 1989
  2986.          [67] Ferguson, W.E.: Selecting math coprocessors.
  2987.               IEEE Spectrum, July 1991, pp. 38-41
  2988.          [68] Schnabel, J.: Viermal 387.
  2989.               Computer Pers"onlich 1991, Heft 22, Seiten 153-156
  2990.          [69] Hofmann, J.: Starke Rechenknechte.
  2991.               mc 1990, Heft 7, Seiten 64-67
  2992.          [70] Woerrlein, H.; Hinnenberg, R.: Die Lust an der Power.
  2993.               Computer Live 1991, Heft 10, Seiten 138-149
  2994.  
  2995.  
  2996.  
  2997.          Manufacturer's addresses
  2998.  
  2999.          Intel Corporation
  3000.          3065 Bowers Avenue
  3001.          Santa Clara, CA 95051
  3002.          USA
  3003.  
  3004.          IIT Integrated Information Technology, Inc.
  3005.          2540 Mission College Blvd.
  3006.          Santa Clara, CA 95054
  3007.          USA
  3008.  
  3009.          ULSI Systems, Inc.
  3010.          58 Daggett Drive
  3011.          San Jose, CA 95134
  3012.          USA
  3013.  
  3014.          Chips & Technologies, Inc.
  3015.          3050 Zanker Road
  3016.          San Jose, CA 95134
  3017.          USA
  3018.  
  3019.          Weitek Corporation
  3020.          1060 East Arques Avenue
  3021.          Sunnyvale, CA 94086
  3022.          USA
  3023.  
  3024.          AMD Advanced Microdevices, Inc.
  3025.          901 Thompson Place
  3026.          P.O.B. 3453
  3027.          Sunnyvale, CA 94088-3453
  3028.          USA
  3029.  
  3030.          Cyrix Corporation
  3031.          P.O.B. 850118
  3032.          Richardson, TX 75085
  3033.          USA
  3034.  
  3035.  
  3036.          Appendix A
  3037.  
  3038.  
  3039.          {$N+,E+}
  3040.          PROGRAM PCtrl;
  3041.  
  3042.          VAR B,c: EXTENDED;
  3043.              Precision, L: WORD;
  3044.  
  3045.          PROCEDURE SetPrecisionControl (Precision: WORD);
  3046.          (* This procedure sets the internal precision of the NDP. Available *)
  3047.          (* precision values:  0  -  24 bits (SINGLE)                        *)
  3048.          (*                    1  -  n.a. (mapped to single)                 *)
  3049.          (*                    2  -  53 bits (DOUBLE)                        *)
  3050.          (*                    3  -  64 bits (EXTENDED)                      *)
  3051.  
  3052.          VAR CtrlWord: WORD;
  3053.  
  3054.          BEGIN {SetPrecisionCtrl}
  3055.             IF Precision = 1 THEN
  3056.                Precision := 0;
  3057.             Precision := Precision SHL 8; { make mask for PC field in ctrl word}
  3058.             ASM
  3059.                FSTCW    [CtrlWord]        { store NDP control word }
  3060.                MOV      AX, [CtrlWord]    { load control word into CPU }
  3061.                AND      AX, 0FCFFh        { mask out precision control field }
  3062.                OR       AX, [Precision]   { set desired precision in PC field }
  3063.                MOV      [CtrlWord], AX    { store new control word }
  3064.                FLDCW    [CtrlWord]        { set new precision control in NDP }
  3065.             END;
  3066.          END; {SetPrecisionCtrl}
  3067.  
  3068.          BEGIN {main}
  3069.             FOR Precision := 1 TO 3 DO BEGIN
  3070.                B := 1.2345678901234567890;
  3071.                SetPrecisionControl (Precision);
  3072.                FOR L := 1 TO 20 DO BEGIN
  3073.                   B := Sqrt (B);
  3074.                END;
  3075.                FOR L := 1 TO 20 DO BEGIN
  3076.                   B := B*B;
  3077.                END;
  3078.                SetPrecisionControl (3);   { full precision for printout }
  3079.                WriteLn (Precision, B:28);
  3080.             END;
  3081.          END.
  3082.  
  3083.  
  3084.          +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3085.  
  3086.          {$N+,E+}
  3087.          PROGRAM RCtrl;
  3088.  
  3089.          VAR B,c: EXTENDED;
  3090.              RoundingMode, L: WORD;
  3091.  
  3092.  
  3093.          PROCEDURE SetRoundingMode (RCMode: WORD);
  3094.          (* This procedure selects one of four available rounding modes *)
  3095.          (* 0  -  Round to nearest (default)                            *)
  3096.          (* 1  -  Round down (towards negative infinity)                *)
  3097.          (* 2  -  Round up (towards positive infinity)                  *)
  3098.          (* 3  -  Chop (truncate, round towards zero)                   *)
  3099.  
  3100.          VAR CtrlWord: WORD;
  3101.  
  3102.          BEGIN
  3103.             RCMode := RCMode SHL 10;      { make mask for RC field in control word}
  3104.             ASM
  3105.                FSTCW    [CtrlWord]        { store NDP control word }
  3106.                MOV      AX, [CtrlWord]    { load control word into CPU }
  3107.                AND      AX, 0F3FFh        { mask out rounding control field }
  3108.                OR       AX, [RCMode]      { set desired precision in RC field }
  3109.                MOV      [CtrlWord], AX    { store new control word }
  3110.                FLDCW    [CtrlWord]        { set new rounding control in NDP }
  3111.             END;
  3112.          END;
  3113.  
  3114.          BEGIN
  3115.             FOR RoundingMode := 0 TO 3 DO BEGIN
  3116.                B := 1.2345678901234567890e100;
  3117.                SetRoundingMode (RoundingMode);
  3118.                FOR L := 1 TO 51 DO BEGIN
  3119.                   B := Sqrt (B);
  3120.                END;
  3121.                   FOR L := 1 TO 51 DO BEGIN
  3122.                   B := -B*B;
  3123.                END;
  3124.                SetRoundingMode (0);        { round to nearest for printout }
  3125.                WriteLn (RoundingMode, B:28);
  3126.             END;
  3127.          END.
  3128.  
  3129.  
  3130.          +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3131.  
  3132.          {$N+,E+}
  3133.  
  3134.          PROGRAM DenormTs;
  3135.  
  3136.          VAR E: EXTENDED;
  3137.              D: DOUBLE;
  3138.              S: SINGLE;
  3139.  
  3140.          BEGIN
  3141.             WriteLn ('Testing support and printing of denormals');
  3142.             WriteLn;
  3143.             Write ('Coprocessor is: ');
  3144.             CASE Test8087 OF
  3145.                0: WriteLn ('Emulator');
  3146.                1: WriteLn ('8087 or compatible');
  3147.                2: WriteLn ('80287 or compatible');
  3148.                3: WriteLn ('80387 or compatible');
  3149.             END;
  3150.             WriteLn;
  3151.             S := 1.18e-38;
  3152.             S := S * 3.90625e-3;
  3153.             IF S = 0 THEN
  3154.                WriteLn ('SINGLE denormals not supported')
  3155.             ELSE BEGIN
  3156.                WriteLn ('SINGLE denormals supported');
  3157.                WriteLn ('SINGLE denormal prints as:   ', S);
  3158.                WriteLn ('Denormal should be printed as 4.60943...E-0041');
  3159.             END;
  3160.             WriteLn;
  3161.             D := 2.24e-308;
  3162.             D := D * 3.90625e-3;
  3163.             IF D = 0 THEN
  3164.                WriteLn ('DOUBLE denormals not supported')
  3165.             ELSE BEGIN
  3166.                WriteLn ('DOUBLE denormals supported');
  3167.                WriteLn ('DOUBLE denormal prints as:   ', D);
  3168.                WriteLn ('Denormal should be printed as 8.75...E-0311');
  3169.             END;
  3170.             WriteLn;
  3171.             E := 3.37e-4932;
  3172.             E := E * 3.90625e-3;
  3173.             IF E = 0 THEN
  3174.                WriteLn ('EXTENDED denormals not supported')
  3175.             ELSE BEGIN
  3176.                WriteLn ('EXTENDED denormals supported');
  3177.                WriteLn ('EXTENDED denormal prints as: ', E);
  3178.                WriteLn ('Denormal should be printed as 1.3164...E-4934');
  3179.             END;
  3180.          END.
  3181.  
  3182.  
  3183.          Appendix B
  3184.  
  3185.  
  3186.          ; FILE: APFELM4.ASM
  3187.          ; assemble with MASM /e APFELM4 or TASM /e APFELM4
  3188.  
  3189.  
  3190.          CODE        SEGMENT BYTE PUBLIC 'CODE'
  3191.                      ASSUME  CS: CODE
  3192.  
  3193.                      PAGE    ,120
  3194.  
  3195.                      PUBLIC  APPLE87;
  3196.  
  3197.          APPLE87     PROC    NEAR
  3198.                      PUSH    BP                  ; save caller's base pointer
  3199.                      MOV     BP, SP              ; make new frame pointer
  3200.                      PUSH    DS                  ; save caller's data segment
  3201.                      PUSH    SI                  ; save register
  3202.                      PUSH    DI                  ;  variables
  3203.                      LDS     BX, [BP+04]         ; pointer to parameter record
  3204.                      FINIT                       ; init 80x87          FSP->R0
  3205.                      FILD   WORD  PTR [BX+02]    ; maxrad              FSP->R7
  3206.                      FLD    QWORD PTR [BX+08]    ; qmax                FSP->R6
  3207.                      FSUB   QWORD PTR [BX+16]    ; qmax-qmin           FSP->R6
  3208.                      DEC    WORD  PTR [BX+04]    ; ymax-1
  3209.                      FIDIV  WORD  PTR [BX+04]    ; (qmax-qmin)/(ymax-1)FSP->R6
  3210.                      FSTP   QWORD PTR [BX+16]    ; save delta_q        FSP->R7
  3211.                      FLD    QWORD PTR [BX+24]    ; pmax                FSP->R6
  3212.                      FSUB   QWORD PTR [BX+32]    ; pmax-pmin           FSP->R6
  3213.                      DEC    WORD  PTR [BX+06]    ; xmax-1
  3214.                      FIDIV  WORD  PTR [BX+06]    ; delta_p             FSP->R6
  3215.                      MOV    AX, [BX]             ; save maxiter,[BX] needed for
  3216.                      MOV    [BX+2], AX           ;  80x87 status now
  3217.                      XOR    BP, BP               ; y=0
  3218.                      FLD    QWORD PTR [BX+08]    ; qmax                FSP->R5
  3219.                      CMP    WORD  PTR [BX+40], 0 ; fast mode on 8087 desired ?
  3220.                      JE     yloop                ; no, normal mode
  3221.                      FSTCW  [BX]                 ; save NDP control word
  3222.                      AND    WORD PTR [BX], 0FCFFh; set PCTRL = single precision
  3223.                      FLDCW  [BX]                 ; get back NDP control word
  3224.          yloop:      XOR    DI, DI               ; x=0
  3225.                      FLD    QWORD PTR [BX+32]    ; pmin                FSP->R4
  3226.          xloop:      FLDZ                        ; j**2= 0             FSP->R3
  3227.                      FLDZ                        ; 2ij = 0             FSP->R2
  3228.                      FLDZ                        ; i**2= 0             FSP->R1
  3229.                      MOV    CX, [BX+2]           ; maxiter
  3230.                      MOV    DL, 41h              ; mask for C0 and C3 cond.bits
  3231.          iteration:  FSUB   ST, ST(2)            ; i**2-j**2           FSP->R1
  3232.                      FADD   ST, ST(3)            ; i**2-j**2+p = i     FSP->R1
  3233.                      FLD    ST(0)                ; duplicate i         FSP->R0
  3234.                      FMUL   ST(1), ST            ; i**2                FSP->R0
  3235.                      FADD   ST, ST(0)            ; 2i                  FSP->R0
  3236.                      FXCH   ST(2)                ; 2*i*j               FSP->R0
  3237.                      FADD   ST, ST(5)            ; 2*i*j+q = j         FSP->R0
  3238.                      FMUL   ST(2), ST            ; 2*i*j               FSP->R0
  3239.                      FMUL   ST, ST(0)            ; j**2                FSP->R0
  3240.                      FST    ST(3)                ; save j**2           FSP->R0
  3241.                      FADD   ST, ST(1)            ; i**2+j**2           FSP->R0
  3242.                      FCOMP  ST(7)                ; i**2+j**2 > maxrad? FSP->R1
  3243.                      FSTSW  [BX]                 ; save 80x87 cond.codeFSP->R1
  3244.                      TEST   BYTE PTR [BX+1], DL  ; test carry and zero flags
  3245.                      LOOPNZ iteration            ; until maxiter if not diverg.
  3246.                      MOV    DX, CX               ; number of loops executed
  3247.                      NEG    CX                   ; carry set if CX <> 0
  3248.                      ADC    DX, 0                ; adjust DX if no. of loops<>0
  3249.  
  3250.                      ; plot point here (DI = X, BP = y, DX has the color)
  3251.  
  3252.                      FSTP   ST(0)                ; pop i**2            FSP->R2
  3253.                      FSTP   ST(0)                ; pop 2ij             FSP->R3
  3254.                      FSTP   ST(0)                ; pop j**2            FSP->R4
  3255.                      FADD   ST,ST(2)             ; p=p+delta_p         FSP->R4
  3256.                      INC    DI                   ; x:=x+1
  3257.                      CMP    DI, [BX+6]           ; x > xmax ?
  3258.                      JBE    xloop                ; no, continue on same line
  3259.                      FSTP   ST(0)                ; pop p               FSP->R5
  3260.                      FSUB   QWORD PTR [BX+16]    ; q=q-delta_q         FSP->R5
  3261.                      INC    BP                   ; y:=y+1
  3262.                      CMP    BP, [BX+4]           ; y > ymax ?
  3263.                      JBE    yloop                ; no, picture not done yet
  3264.  
  3265.          groesser:   POP    DI                   ; restore
  3266.                      POP    SI                   ;  register variables
  3267.                      POP    DS                   ; restore caller's data segm.
  3268.                      POP    BP                   ; save caller's base pointer
  3269.                      RET    4                    ; pop parameters and return
  3270.          APPLE87     ENDP
  3271.  
  3272.          CODE        ENDS
  3273.  
  3274.                      END
  3275.  
  3276.          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3277.  
  3278.          UNIT Time;
  3279.  
  3280.          INTERFACE
  3281.  
  3282.          FUNCTION Clock: LONGINT;          { same as VMS; time in milliseconds }
  3283.  
  3284.  
  3285.          IMPLEMENTATION
  3286.  
  3287.          FUNCTION Clock: LONGINT; ASSEMBLER;
  3288.          ASM
  3289.                     PUSH    DS            { save caller's data segment }
  3290.                     XOR     DX, DX        { initialize data segment to }
  3291.                     MOV     DS, DX        {  access ticker counter }
  3292.                     MOV     BX, 46Ch      { offset of ticker counter in segm.}
  3293.                     MOV     DX, 43h       { timer chip control port }
  3294.                     MOV     AL, 4         { freeze timer 0 }
  3295.                     PUSHF                 { save caller's int flag setting }
  3296.                     STI                   { allow update of ticker counter }
  3297.                     LES     DI, DS:[BX]   { read BIOS ticker counter }
  3298.                     OUT     DX, AL        { latch timer 0 }
  3299.                     LDS     SI, DS:[BX]   { read BIOS ticker counter }
  3300.                     IN      AL, 40h       { read latched timer 0 lo-byte }
  3301.                     MOV     AH, AL        { save lo-byte }
  3302.                     IN      AL, 40h       { read latched timer 0 hi-byte }
  3303.                     POPF                  { restore caller's int flag }
  3304.                     XCHG    AL, AH        { correct order of hi and lo }
  3305.                     MOV     CX, ES        { ticker counter 1 in CX:DI:AX }
  3306.                     CMP     DI, SI        { ticker counter updated ? }
  3307.                     JE      @no_update    { no }
  3308.                     OR      AX, AX        { update before timer freeze ? }
  3309.                     JNS     @no_update    { no }
  3310.                     MOV     DI, SI        { use second }
  3311.                     MOV     CX, DS        {  ticker counter }
  3312.          @no_update:NOT     AX            { counter counts down }
  3313.                     MOV     BX, 36EDh     { load multiplier }
  3314.                     MUL     BX            { W1 * M }
  3315.                     MOV     SI, DX        { save W1 * M (hi) }
  3316.                     MOV     AX, BX        { get M }
  3317.                     MUL     DI            { W2 * M }
  3318.                     XCHG    BX, AX        { AX = M, BX = W2 * M (lo) }
  3319.                     MOV     DI, DX        { DI = W2 * M (hi) }
  3320.                     ADD     BX, SI        { accumulate }
  3321.                     ADC     DI, 0         {  result }
  3322.                     XOR     SI, SI        { load zero }
  3323.                     MUL     CX            { W3 * M }
  3324.                     ADD     AX, DI        { accumulate }
  3325.                     ADC     DX, SI        {  result in DX:AX:BX }
  3326.                     MOV     DH, DL        { move result }
  3327.                     MOV     DL, AH        {  from DL:AX:BX }
  3328.                     MOV     AH, AL        {   to }
  3329.                     MOV     AL, BH        {    DX:AX:BH }
  3330.                     MOV     DI, DX        { save result }
  3331.                     MOV     CX, AX        {  in DI:CX }
  3332.                     MOV     AX, 25110     { calculate correction }
  3333.                     MUL     DX            {  factor }
  3334.                     SUB     CX, DX        { subtract correction }
  3335.                     SBB     DI, SI        {  factor }
  3336.                     XCHG    AX, CX        { result back }
  3337.                     MOV     DX, DI        {  to DX:AX }
  3338.                     POP     DS            { restore caller's data segment }
  3339.          END;
  3340.  
  3341.  
  3342.          BEGIN
  3343.             Port [$43] := $34;           { need rate generator, not square wave}
  3344.             Port [$40] := 0;             { generator as prog. by some BIOSes }
  3345.             Port [$40] := 0;             { for timer 0 }
  3346.          END. { Time }
  3347.  
  3348.  
  3349.          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3350.  
  3351.          {$A+,B-,R-,I-,V-,N+,E+}
  3352.          PROGRAM PeakFlop;
  3353.  
  3354.          USES Time;
  3355.  
  3356.          TYPE ParamRec = RECORD
  3357.                             MaxIter, MaxRad, YMax, XMax: WORD;
  3358.                             Qmax, Qmin, Pmax, Pmin: DOUBLE;
  3359.                             FastMod: WORD;
  3360.                             PlotFkt: POINTER;
  3361.                             FLOPS:LONGINT;
  3362.                          END;
  3363.  
  3364.          VAR Param: ParamRec;
  3365.              Start: LONGINT;
  3366.  
  3367.  
  3368.          {$L APFELM4.OBJ}
  3369.  
  3370.          PROCEDURE Apple87 (VAR Param: ParamRec);     EXTERNAL;
  3371.  
  3372.  
  3373.          BEGIN
  3374.             WITH Param DO BEGIN
  3375.                MaxIter:= 50;
  3376.                MaxRad := 30;
  3377.                YMax   := 30;
  3378.                XMax   := 30;
  3379.                Pmin   :=-2.1;
  3380.                Pmax   := 1.1;
  3381.                Qmin   :=-1.2;
  3382.                Qmax   := 1.2;
  3383.                FastMod:= Word (FALSE);
  3384.                PlotFkt:= NIL;
  3385.                Flops  := 0;
  3386.             END;
  3387.             Start := Clock;
  3388.             Apple87 (Param);         { executes 104002 FLOP }
  3389.             Start := Clock - Start;  { elapsed time in milliseconds }
  3390.             WriteLn ('Peak-MFLOPS: ', 104.002 / Start);
  3391.          END.
  3392.  
  3393.          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3394.  
  3395.          ; FILE: M4X4.ASM
  3396.          ;
  3397.          ; assemble with TASM /e M4X4 or MASM /e M4X4
  3398.  
  3399.          CODE      SEGMENT BYTE PUBLIC 'CODE'
  3400.  
  3401.                    ASSUME  CS:CODE
  3402.  
  3403.                    PUBLIC  MUL_4x4
  3404.                    PUBLIC  IIT_MUL_4x4
  3405.  
  3406.  
  3407.          FSBP0     EQU     DB  0DBh, 0E8h        ; declare special IIT
  3408.          FSBP1     EQU     DB  0DBh, 0EBh        ;  instructions
  3409.          FSBP2     EQU     DB  0DBh, 0EAh
  3410.          F4X4      EQU     DB  0DBh, 0F1h
  3411.  
  3412.  
  3413.          ;---------------------------------------------------------------------
  3414.          ;
  3415.          ; MUL_4x4 multiplicates a four-by-four matrix by an array of four
  3416.          ; dimensional vectors. This operation is needed for 3D transformations
  3417.          ; in graphics data processing. There are arrays for each component of
  3418.          ; a vector. Thus there is an ; array containing all the x components,
  3419.          ; another containing all the y components and so on. Each component is
  3420.          ; an 8 byte IEEE floating point number. Two indices into the array of
  3421.          ; vectors are given. The first is the index of the vector that will be
  3422.          ; processed first, the second is the index of the vector processed
  3423.          ; last.
  3424.          ;
  3425.          ;---------------------------------------------------------------------
  3426.  
  3427.          MUL_4x4   PROC    NEAR
  3428.  
  3429.                    AddrX   EQU DWORD PTR [BP+24] ; address of X component array
  3430.                    AddrY   EQU DWORD PTR [BP+20] ; address of Y component array
  3431.                    AddrZ   EQU DWORD PTR [BP+16] ; address of Z component array
  3432.                    AddrW   EQU DWORD PTR [BP+12] ; address of W component array
  3433.                    AddrT   EQU DWORD PTR [BP+8]  ; addr. of 4x4 transform. mat.
  3434.                    F       EQU WORD  PTR [BP+6]  ; first vector to process
  3435.                    K       EQU WORD  PTR [BP+4]  ; last vector to process
  3436.                    RetAddr EQU WORD  PTR [BP+2]  ; return address saved by call
  3437.                    SavdBP  EQU WORD  PTR [BP+0]  ; saved frame pointer
  3438.                    SavdDS  EQU WORD  PTR [BP-2]  ; caller's data segment
  3439.  
  3440.                    PUSH    BP                    ; save TURBO-Pascal frame pointer
  3441.                    MOV     BP, SP                ; new frame pointer
  3442.                    PUSH    DS                    ; save TURBO-Pascal data segment
  3443.  
  3444.                    MOV     CX, K                 ; final index
  3445.                    SUB     CX, F                 ; final index - start index
  3446.                    JNC     $ok                   ; must not
  3447.                    JMP     $nothing              ;  be negative
  3448.          $ok:      INC     CX                    ; number of elements
  3449.  
  3450.                    MOV     SI, F                 ; init offset into arrays
  3451.                    SHL     SI, 1                 ; each
  3452.                    SHL     SI, 1                 ;  element
  3453.                    SHL     SI, 1                 ;   has 8 bytes
  3454.  
  3455.                    LDS     DI, AddrT             ; addr. of transformation mat.
  3456.                    FLD     QWORD PTR [DI]        ; load a[0,0]   = R7
  3457.                    FLD     QWORD PTR [DI+8]      ; load a[0,1]   = R6
  3458.  
  3459.          $mat_mul: LES     BX, AddrX             ; addr. of x component array
  3460.                    FLD     QWORD PTR ES:[BX+SI]  ; load x[a]     = R5
  3461.                    LES     BX, AddrY             ; addr. of y component array
  3462.                    FLD     QWORD PTR ES:[BX+SI]  ; load y[a]     = R4
  3463.                    LES     BX, AddrZ             ; addr. of z component array
  3464.                    FLD     QWORD PTR ES:[BX+SI]  ; load z[a]     = R3
  3465.                    LES     BX, AddrW             ; addr. of w component array
  3466.                    FLD     QWORD PTR ES:[BX+SI]  ; load w[a]     = R2
  3467.  
  3468.                    FLD     ST(5)                 ; load a[0,0]   = R1
  3469.                    FMUL    ST, ST(4)             ; a[0,0] * x[a] = R1
  3470.                    FLD     ST(5)                 ; load a[0,1]   = R0
  3471.                    FMUL    ST, ST(4)             ; a[0,1] * y[a] = R0
  3472.                    FADDP   ST(1), ST             ; a[0,0]*x[a]+a[0,1]*y[a]=R1
  3473.                    FLD     QWORD PTR [DI+16]     ; load a[0,2]   = R0
  3474.                    FMUL    ST, ST(3)             ; a[0,2] * z[a] = R0
  3475.                    FADDP   ST(1), ST             ; a[0,0]*x[a]...a[0,2]*z[a]=R1
  3476.                    FLD     QWORD PTR [DI+24]     ; load a[0,3]   = R0
  3477.                    FMUL    ST, ST(2)             ; a[0,3] * w[a] = R0
  3478.                    FADDP   ST(1), ST             ; a[0,0]*x[a]...a[0,3]*w[a]=R1
  3479.                    LES     BX, AddrX             ; get address of x vector
  3480.                    FSTP    QWORD PTR ES:[BX+SI]  ; write new x[a]
  3481.  
  3482.                    FLD     QWORD PTR [DI+32]     ; load a[1,0]   = R1
  3483.                    FMUL    ST, ST(4)             ; a[1,0] * x[a] = R1
  3484.                    FLD     QWORD PTR [DI+40]     ; load a[1,1]   = R0
  3485.                    FMUL    ST, ST(4)             ; a[1,1] * y[a] = R0
  3486.                    FADDP   ST(1), ST             ; a[1,0]*x[a]+a[1,1]*y[a]=R1
  3487.                    FLD     QWORD PTR [DI+48]     ; load a[1,2]   = R0
  3488.                    FMUL    ST, ST(3)             ; a[1,2] * z[a] = R0
  3489.                    FADDP   ST(1), ST             ; a[1,0]*x[a]...a[1,2]*z[a]=R1
  3490.                    FLD     QWORD PTR [DI+56]     ; load a[1,3]   = R0
  3491.                    FMUL    ST, ST(2)             ; a[1,3] * w[a] = R0
  3492.                    FADDP   ST(1), ST             ; a[1,0]*x[a]...a[1,3]*w[a]=R1
  3493.                    LES     BX, AddrY             ; get address of y vector
  3494.                    FSTP    QWORD PTR ES:[BX+SI]  ; write new y[a]
  3495.  
  3496.                    FLD     QWORD PTR [DI+64]     ; load a[2,0]   = R1
  3497.                    FMUL    ST, ST(4)             ; a[2,0] * x[a] = R1
  3498.                    FLD     QWORD PTR [DI+72]     ; load a[2,1]   = R0
  3499.                    FMUL    ST, ST(4)             ; a[2,1] * y[a] = R0
  3500.                    FADDP   ST(1), ST             ; a[2,0]*x[a]+a[2,1]*y[a]=R1
  3501.                    FLD     QWORD PTR [DI+80]     ; load a[2,2]   = R0
  3502.                    FMUL    ST, ST(3)             ; a[2,2] * z[a] = R0
  3503.                    FADDP   ST(1), ST             ; a[2,0]*x[a]...a[2,2]*z[a]=R1
  3504.                    FLD     QWORD PTR [DI+88]     ; load a[2,3]   = R0
  3505.                    FMUL    ST, ST(2)             ; a[2,3] * w[a] = R0
  3506.                    FADDP   ST(1), ST             ; a[2,0]*x[a]...a[2,3]*w[a]=R1
  3507.                    LES     BX, AddrZ             ; get address of z vector
  3508.                    FSTP    QWORD PTR ES:[BX+SI]  ; write new z[a]
  3509.  
  3510.                    FLD     QWORD PTR [DI+96]     ; load a[3,0]   = R1
  3511.                    FMULP   ST(4), ST             ; a[3,0] * x[a] = R5
  3512.                    FLD     QWORD PTR [DI+104]    ; load a[3,1]   = R1
  3513.                    FMULP   ST(3), ST             ; a[3,1] * y[a] = R4
  3514.                    FLD     QWORD PTR [DI+112]    ; load a[3,2]   = R1
  3515.                    FMULP   ST(2), ST             ; a[3,2] * z[a] = R3
  3516.                    FLD     QWORD PTR [DI+120]    ; load a[3,3]   = R1
  3517.                    FMULP   ST(1), ST             ; a[3,3] * w[a] = R2
  3518.                    FADDP   ST(1), ST             ; a[3,3]*w[a]+a[3,2]*z[a]=R3
  3519.                    FADDP   ST(1), ST             ; a[3,3]*w[a]...a[3,1]*y[a]=R4
  3520.                    FADDP   ST(1), ST             ; a[3,3]*w[a]...a[3,0]*x[a]=R5
  3521.                    LES     BX, AddrW             ; get address of w vector
  3522.                    FSTP    QWORD PTR ES:[BX+SI]  ; write new w[a]
  3523.  
  3524.                    ADD     SI, 8                 ; new offset into arrays
  3525.                    DEC     CX                    ; decrement element counter
  3526.                    JZ      $done                 ; no elements left, done
  3527.                    JMP     $mat_mul              ; transform next vector
  3528.  
  3529.          $done:    FSTP     ST(0)                ; clear
  3530.                    FSTP     ST(0)                ;  FPU stack
  3531.          $nothing: POP      DS                   ; restore TP data segment
  3532.                    POP      BP                   ; restore TP frame pointer
  3533.                    RET      24                   ; pop parameters and return
  3534.  
  3535.          MUL_4X4   ENDP
  3536.  
  3537.  
  3538.          ;---------------------------------------------------------------------
  3539.          ;
  3540.          ; IIT_MUL_4x4 multiplicates a four-by-four matrix by an array of four
  3541.          ; dimensional vectors. This operation is needed for 3D transformations
  3542.          ; in graphics data processing. There are arrays for each component of
  3543.          ; a vector.  Thus there is an array containing all the x components,
  3544.          ; another containing all the y components and so on. Each component is
  3545.          ; an 8 byte IEEE floating point number. Two indices into the array of
  3546.          ; vectors are given. The first is the index of the vector that will be
  3547.          ; processed first, the second is the index of the vector processed
  3548.          ; last. This subroutine uses the special instructions only available
  3549.          ; on IIT coprocessors to provide fast matrix multiply capabilities.
  3550.          ; So make sure to use it only on IIT coprocessors.
  3551.          ;
  3552.          ;---------------------------------------------------------------------
  3553.  
  3554.          IIT_MUL_4x4   PROC    NEAR
  3555.  
  3556.                    AddrX   EQU DWORD PTR [BP+24] ; address of X component array
  3557.                    AddrY   EQU DWORD PTR [BP+20] ; address of Y component array
  3558.                    AddrZ   EQU DWORD PTR [BP+16] ; address of Z component array
  3559.                    AddrW   EQU DWORD PTR [BP+12] ; address of W component array
  3560.                    AddrT   EQU DWORD PTR [BP+8]  ; addr. of 4x4 transf. matrix
  3561.                    F       EQU WORD  PTR [BP+6]  ; first vector to process
  3562.                    K       EQU WORD  PTR [BP+4]  ; last vector to process
  3563.                    RetAddr EQU WORD  PTR [BP+2]  ; return address saved by call
  3564.                    SavdBP  EQU WORD  PTR [BP+0]  ; saved frame pointer
  3565.                    SavdDS  EQU WORD  PTR [BP-2]  ; caller's data segment
  3566.                    Ctrl87  EQU WORD  PTR [BP-4]  ; caller's 80x87 control word
  3567.  
  3568.                    PUSH    BP                    ; save TURBO-Pascal frame ptr
  3569.                    MOV     BP, SP                ; new frame pointer
  3570.                    PUSH    DS                    ; save TURBO-Pascal data seg.
  3571.                    SUB     SP, 2                 ; make local variabe
  3572.                    FSTCW   [Ctrl87]              ; save 80x87 ctrl word
  3573.                    LES     SI, AddrT             ; ptr to transformation matrix
  3574.                    FINIT                         ; initialize coprocessor
  3575.                    FSBP2                         ; set register bank 2
  3576.                    FLD     QWORD PTR ES:[SI]     ; load a[0,0]
  3577.                    FLD     QWORD PTR ES:[SI+32]  ; load a[1,0]
  3578.                    FLD     QWORD PTR ES:[SI+64]  ; load a[2,0]
  3579.                    FLD     QWORD PTR ES:[SI+96]  ; load a[3,0]
  3580.                    FLD     QWORD PTR ES:[SI+8]   ; load a[0,1]
  3581.                    FLD     QWORD PTR ES:[SI+40]  ; load a[1,1]
  3582.                    FLD     QWORD PTR ES:[SI+72]  ; load a[2,1]
  3583.                    FLD     QWORD PTR ES:[SI+104] ; load a[3,1]
  3584.                    FINIT                         ; initialize coprocessor
  3585.                    FSBP1                         ; set register bank 1
  3586.                    FLD     QWORD PTR ES:[SI+16]  ; load a[0,2]
  3587.                    FLD     QWORD PTR ES:[SI+48]  ; load a[1,2]
  3588.                    FLD     QWORD PTR ES:[SI+80]  ; load a[2,2]
  3589.                    FLD     QWORD PTR ES:[SI+112] ; load a[3,2]
  3590.                    FLD     QWORD PTR ES:[SI+24]  ; load a[0,3]
  3591.                    FLD     QWORD PTR ES:[SI+56]  ; load a[1,3]
  3592.                    FLD     QWORD PTR ES:[SI+88]  ; load a[2,3]
  3593.                    FLD     QWORD PTR ES:[SI+120] ; load a[3,3]
  3594.  
  3595.                                         ; transformation matrix loaded
  3596.  
  3597.                    MOV     AX, F                 ; index of first vector
  3598.                    MOV     DX, K                 ; index of last vector
  3599.  
  3600.                    MOV     BX, AX                ; index 1st vector to process
  3601.                    MOV     CL, 3                 ; component has 8 (2**3) bytes
  3602.                    SHL     BX, CL                ; compute offset into arrays
  3603.  
  3604.                    FINIT                         ; initialize coprocessor
  3605.                    FSBP0                         ; set register bank 0
  3606.  
  3607.          $mat_loop:LES     SI, AddrW             ; addr. of W component array
  3608.                    FLD     QWORD PTR ES:[SI+BX]  ; W component current vector
  3609.                    LES     SI, AddrZ             ; addr. of Z component array
  3610.                    FLD     QWORD PTR ES:[SI+BX]  ; Z component current vector
  3611.                    LES     SI, AddrY             ; addr. of Y component array
  3612.                    FLD     QWORD PTR ES:[SI+BX]  ; Y component current vector
  3613.                    LES     SI, AddrX             ; addr. of X component array
  3614.                    FLD     QWORD PTR ES:[SI+BX]  ; X component current vector
  3615.                    F4X4                          ; mul 4x4 matrix by 4x1 vector
  3616.                    INC     AX                    ; next vector
  3617.                    MOV     DI, AX                ; next vector
  3618.                    SHL     DI, CL                ; offset of vector into arrays
  3619.  
  3620.                    FSTP    QWORD PTR ES:[SI+BX]  ; store X comp. of curr. vect.
  3621.                    LES     SI, AddrY             ; address of Y component array
  3622.                    FSTP    QWORD PTR ES:[SI+BX]  ; store Y comp. of curr. vect.
  3623.                    LES     SI, AddrZ             ; address of Z component array
  3624.                    FSTP    QWORD PTR ES:[SI+BX]  ; store Z comp. of curr. vect.
  3625.                    LES     SI, AddrW             ; address of W component array
  3626.                    FSTP    QWORD PTR ES:[SI+BX]  ; store W comp. of curr. vect.
  3627.  
  3628.                    MOV     BX, DI                ; ofs nxt vect. in comp. arrays
  3629.                    CMP     AX, DX                ; nxt vector past upper bound?
  3630.                    JLE     $mat_loop             ; no, transform next vector
  3631.                    FLDCW   [Ctrl87]              ; restore orig 80x87 ctrl word
  3632.  
  3633.                    ADD      SP, 2                ; get rid of local variable
  3634.                    POP      DS                   ; restore TP data segment
  3635.                    POP      BP                   ; restore TP frame pointer
  3636.                    RET      24                   ; pop parameters and return
  3637.          IIT_MUL_4x4   ENDP
  3638.  
  3639.          CODE      ENDS
  3640.  
  3641.                    END
  3642.  
  3643.          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3644.  
  3645.          {$N+,E+}
  3646.  
  3647.          PROGRAM Trnsform;
  3648.  
  3649.          USES Time;
  3650.  
  3651.          CONST VectorLen = 8190;
  3652.  
  3653.          TYPE  Vector    = ARRAY [0..VectorLen] OF DOUBLE;
  3654.                VectorPtr = ^Vector;
  3655.                Mat4      = ARRAY [1..4, 1..4] OF DOUBLE;
  3656.  
  3657.          VAR   X: VectorPtr;
  3658.                Y: VectorPtr;
  3659.                Z: VectorPtr;
  3660.                W: VectorPtr;
  3661.                T: Mat4;
  3662.                K: INTEGER;
  3663.                L: INTEGER;
  3664.                First: INTEGER;
  3665.                Last:  INTEGER;
  3666.                Start: LONGINT;
  3667.                Elapsed:LONGINT;
  3668.  
  3669.          PROCEDURE MUL_4X4     (X, Y, Z, W: VectorPtr;
  3670.                                 VAR T: Mat4; First, Last: INTEGER); EXTERNAL;
  3671.          PROCEDURE IIT_MUL_4X4 (X, Y, Z, W: VectorPtr;
  3672.                                 VAR T: Mat4; First, Last: INTEGER); EXTERNAL;
  3673.  
  3674.          {$L M4X4.OBJ}
  3675.  
  3676.          BEGIN
  3677.             WriteLn ('Test8087 = ', Test8087);
  3678.             New (X);
  3679.             New (Y);
  3680.             New (Z);
  3681.             New (W);
  3682.             FOR L := 1 TO VectorLen DO BEGIN
  3683.                X^ [L] := Random;
  3684.                Y^ [L] := Random;
  3685.                Z^ [L] := Random;
  3686.                W^ [L] := Random;
  3687.             END;
  3688.             X^ [0] := 1;
  3689.             Y^ [0] := 1;
  3690.             Z^ [0] := 1;
  3691.             W^ [0] := 1;
  3692.             FOR K := 1 TO 4 DO BEGIN
  3693.                FOR L := 1 TO 4 DO BEGIN
  3694.                   T [K, L] := (K-1)*4 + L;
  3695.                END;
  3696.             END;
  3697.             First := 0;
  3698.             Last  := 8190;
  3699.             Start := Clock;
  3700.             MUL_4X4 (X, Y, Z, W, T, First, Last);
  3701.             { IIT_MUL_4X4 (X, Y, Z, W, T, First, Last); }
  3702.             Elapsed := Clock - Start;
  3703.             WriteLn ('Number of vectors: ', Last-First+1);
  3704.             WriteLn ('Time: ', Elapsed, ' ms');
  3705.             WriteLn ('Equivalent to ', (28.0*(Last-First+1)/1e6)/
  3706.                      (Elapsed*1e-3):0:4, ' MFLOPS');
  3707.             WriteLn;
  3708.             WriteLn ('Last vector:');
  3709.             WriteLn;
  3710.             WriteLn (X^[Last]);
  3711.             WriteLn (Y^[Last]);
  3712.             WriteLn (Z^[Last]);
  3713.             WriteLn (W^[Last]);
  3714.          END.
  3715.