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 CoprocessorA 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 68030in 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 ModeWhen 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 ModeUtilizing 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:
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 );
}