•  Back 
  •  Hardware 
  •  Index 
  •  Tree View 
  •  Cross references 
  •  %About 
  •  Show info about hypertext 
  •  View a new file 
Topic       : The ATARI Compendium
Author      : Scott Sanders / JAY Software
Version     : 1.25 (20/6/2003)
Subject     : Documentation
Nodes       : 1117
Index Size  : 32614
HCP-Version : 6
Compiled on : Atari
@charset    : UTF-8
@lang       : en
@default    : 
@help       : %About
@options    : +g -i -t4 +y +z
@width      : 100
View Ref-File<invalid destination page 1581>

                  The 68881/882 Floating Point Coprocessor


A MC6888x math coprocessor may be installed in a Mega ST, Mega STe, or
a Falcon030. The TT030 has one installed in its standard configuration.

The 6888x is interfaced to the 68000 in peripheral mode and to the 68030
in coprocessor mode. Thus, the TT030 and Falcon030 computers access the
6888x in coprocessor mode while the Mega ST and Mega STe computers access
the 6888x in peripheral mode.

Coprocessor Mode

When the 6888x is interfaced in coprocessor mode, using it is as simple
as placing floating-point instructions in the standard instruction stream
(use a coprocessor ID of 1). The 68030 will properly dispatch the
instruction and respond to exceptions through the following vectors:

Vector Address     Assignment

  0x0000001C       FTRAPcc Instruction

  0x0000002C       F-Line Emulator

  0x00000034       Co-processor Protocol Violation

  0x000000C0       Branch or Set on Unordered Condition

  0x000000C4       Inexact Result

  0x000000C8       Floating-Point Divide by Zero

  0x000000CC       Underflow

  0x000000D0       Operand Error

  0x000000D4       Overflow

  0x000000D8       Signaling NAN

Peripheral Mode

Utilizing an installed math coprocessor interfaced using peripheral mode
requires the use of several hardware registers mapped to special
coprocessor registers. Unlike most hardware registers, these do not have
to be accessed in supervisor mode. Atari computers map the 6888x registers
to the following locations:

  Address   Length  Register   Description

0xFFFFFA40   WORD    FPCIR     Status register

0xFFFFFA42   WORD    FPCTL     Control Register

0xFFFFFA44   WORD    FPSAV     Save Register

0xFFFFFA46   WORD    FPREST    Restore Register

0xFFFFFA48   WORD    FPOPR     Operation word register

0xFFFFFA4A   WORD    FPCMD     Command register

0xFFFFFA4C   WORD    FPRES     Reserved

0xFFFFFA4E   WORD    FPCCR     Condition Code Register

0xFFFFFA50   LONG    FPOP      Operand Register

To execute a floating point instruction, use the following protocol for
communicating data with the 6888x:

1. Wait for the chip to be idle.

2. Write a valid 6888x command to FPCMD.

3. If necessary for the command, write an operand to FPOP.

4. Wait for the status port to indicate the command is complete.

5. Read any return data from FPOP.

Step one is achieved by waiting for a value of 0x0802 to appear in the
status register (after ANDing with 0xBFFF) as follows:

          while( ( FPCIR & 0xBFFF) != 0x0802 ) ;

Steps two and three involve writing the command word to FPCMD and any
necessary operand data to FPOP. A primitive response code will be
generated (and should be read) between each write to either FPCMD or FPOP.

For a listing of primitive response codes returned by the 68881, consult
the MC68881/68882 Floating-Point Coprocessor User's Manual (2nd edition),
Motorola publication MC68881UM/AD rev. 2, ISBN 0-13-567-009-8.

After the operation is complete (step 4), data may be read from the 68881
in FPOP (step 5).

When sending or receiving data in FPOP, the following chart details the
transfer ordering and alignment:

index=997
The following code demonstrates transferring two single precision floating-point numbers to the 68881, multiplying them, and returning the result. /* Number of iterations before an error is triggered */ #define FPCOUNT 0x80 #define FPCIR ((WORD *)(0xFFFFFA40L)) #define FPCMD ((WORD *)(0xFFFFFA4AL)) #define FPOP ((float *)(0xFFFFFA50L)) WORD fpcount, dum; /* fperr() is user-defined */ #define FPwait() { fpcount = FPCOUNT; \ while((*FPCIR & 0xBFFF) != 0x0802) \ if(!(--fpcount)) fperr();} #define FPsglset(r,v) { FPwait(); \ *FPCMD = (0x5400 | ((r) << 7)); \ while((*FPCIR & 0xFFF0) != 0x8C00) \ if(!(--fpcount)) fperr(); \ *FPOP = (v);} #define FPsglmul(r1,r2) { FPwait(); \ *FPCMD = (0x0027 | ((r2) << 10) | ((r1) << 7)); \ dum = *FPCIR + 1;} /* dum = FPCIR +1; forces the status register to be read (we assume the data's good) */ #define FPsglget(r,var) { FPwait(); \ *FPCMD = (0x6400 | ((r) << 7)); \ while(*FPCIR != 0xb104) \ if(!(--fpcount)) fperr(); \ var = *FPOP;} /* * void sglmul( float *f1, float *f2 ); * * Multiplies f1 by f2. Returns result in f1. * */ void sglmul( float &f1, float &f2 ) { FPsglset( 0, *f1 ); FPsglset( 1, *f2 ); FPsglmul( 0, 1 ); FPsglget( 0, *f1 ); }