FPSAVE Version 1.18 3rd November 1998 PURPOSE The suite of files FPSAVE_BIN, FPSP_81, FPSP_82, FPSP_40, FPSP_60, REAL_XXX_TXT, VER_BIN and FP2_EQU_ASM is designed to enable a Floating Point Unit (FPU) to be used in a multi-tasking environment under QDOS or related operating systems. This will only work if the CPU is 68020+ and an FPU is present. INSTALLATION The program FPSAVE_BIN should be LRESPR'd. This installs an appropriate FPSP and alters the operating system to save and restore the FPU along with the Integer Unit registers. The effect is that any program (including SuperBASIC) can use the FPU without regard to its use by other programs currently running. The program will abort if $D8(sys vars) is non zero. This prevents the program being loaded more than once, or if $D8(sys vars) is in use. If $D0(sys vars) or $D1(sys vars) is non zero FPSAVE aborts with the message 'not implemented' if either value is wrong. This allows these variables to be set before FPSAVE is activated. METHOD OF USE If a 68881 or 68882 is present then all FP instructions are implemented by hardware. If the FPU is part of a 68040 or 68060 then some FP instructions are emulated by the FPSP. A programmer wishing to use one of these unimplemented instructions must call a routine in the FPSP. The address of the FPSP is found by branching to the subroutine whose address is given at $D8(sys vars). On entry: A0 = 0 or the address of a set of user exception routines. (See Appendix1) On a good exit: D0 = 0 and A1 = the address of the FPSP. bad exit: D0 = error code. An example of how this might be used is given in Appendix2 The various subroutines in the FPSP return the required value as indicated below. In general for each floating point instruction there are three entry points one for each of the sizes X, D and S. The file FP2_EQU_ASM consists of a set of EQUates giving the offsets of the various FP instructions from the start of the FPSP. (The offsets are the same for all FPSP's.) INcluding the file in a program to be assembled enables the instructions to be called by name. The appropriate offset is given by the name of the instruction immediately follwed by X, D or S as shown in the examples below. Before calling the routine where necessary the argument(s) must be put on the stack which must be tidied afterwards. The answer(s) appear(s) in FP0 (and FP1) or in one case D0 and D1. There are four types of instruction, FMOVECR, Monadic, Dyadic and Conversion. Examples of their use is given below: 1. FMOVECR FMOVECR #$34,FP0 becomes MOVE.L #$34,-(A7) JSR FMOVECR(A1) ADDQ.L #4,A7 2. MONADIC FSIN.X FP0 becomes FMOVE.X FP0,-(A7) JSR FSINX(A1) note that FSIN becomes FSINX LEA 12(A7),A7 3. DYADIC FREM.S D0,FP0 becomes MOVE.L D0,-(A7) FMOVE.S FP0,-(A7) note that both operands must be the same size JSR FREMS(A1) note that FREM has become FREMS ADDQ.L #8,A7 4. CONVERSION Two routines I_TO_Q and Q_TO_I are provided on later versions of FPSP to enable conversion between QDOS fp and IEEE format. (The minimum version numbers required are 1.1 for FPSP_81/2, 1.3 for FPSP_40 and 1.2 for FPSP_60. The user must satisfy himself that an appropriate FPSP is loaded before attempting to use these routines to avoid a nasty accident.) I_TO_Q converts the number in FP0 into QDOS fp format. On exit D0.L contains the exponent and D1.L the mantissa. If the number in FP0 is either a NAN or is too large to be represented as a QDOS fp, D0.L = -18 and D1.L = 0. Q_TO_I converts the 6-byte fp number on the stack to an extended format number in FP0. The 'overflow' error is returned in D0.L if the 6 bytes on stack do not form a valid QDOS fp number. Otherwise D0.L is 0. On return the stack must be tidied as for the FP instructions proper. Apart from FMOVECR, I_TO_Q and Q_TO_I all the other FP instructions have three forms ending in X, D or S which stand for the three FP sizes. All instructions except FSINCOS and I_TO_Q produce an answer in FP0. FSINCOS produces two answers, SIN in FP0 and COS in FP1. CONFIG In FPSAVE_BIN the FPSP files have the names "FPSP_x" where x = 81, 82, 40 and 60. FPSAVE searches for the file with its given name then, if this fails, with the device set by DATA_USE added at the front and, finally, with that set by PROG_USE. Use of Config allows the names to be altered. VERSIONS of FPSP From time to time updated versions of the FPSPs may be released. The version number of an FPSP may be found by EXECing VER_BIN with the FPSP filename given as a parameter string. FPSAVE checks the version number of the FPSP presented for loading and aborts if it is too low. Currently the minimum version number is 1.1 for all FPSPs of the correct format. VER_BIN version 1.4 also checks that the type of FPSP file is 1 (which is needed for correct operation of FSAVE. TECHNICAL NOTES It is not necessary to know the contents of this section to use FPSAVE - it is for interest only. Each program (including SuperBASIC) which uses the FPU for the first time springs a trap set by causing an enabled Divide by Zero (DZ) exception. The exception routine sets up a save area for the program and resets the FPU. The existence of the save area is sufficient to cause a routine linked into the scheduler list to save the FPU state when a program is temporarily stopped and to arrange for it to be restored when the program is reactivated. The save area contains the true values of the program's A0 and PC which are temporarily altered as part of the save/restore process. Calling the routine at $D8(sys vars) causes a save area to be set up if one does not already exist. It is necessary to do this because the value of A0 (the address of a user's exception routines) is stored in the save area. Otherwise it would have been possible to wait for the springing of the trap before setting up the area. The following use is made of the 16 bytes of sys vars from $D0. SYS_FPU $D0 byte Type of FPU (see below) 1 SYS_MMU $D1 byte Type of MMU " 1 SYS_FPZS $D2 word Maximum length of FSAVE area 1 SYS_FPSL $D4 long word Address of save area list 2 SYS_CLFP $D8 long word Address to access the FPSP 1 $DC long word Unused at present Notes 1. Set by FPSAVE 2. Set when the FPU is first used or when the FPSP is accessed Code Type of FPU (SYS_FPU) Type of MMU (SYS_MMU) -1 No FPU present No MMU present 1 68881 + No FPSP 68851 2 68882 " - 3 - 68030 4 68040 " 68040 or 68LC040 5 - - 6 68060 " 68060 or 68LC060 7 - - 9 68881 + FPSP (Library version) loaded - 10 68882 " " - 12 68040 " " - 14 68060 " " - The value of SYS_PTYP, $A1(sys vars), is set by FPSAVE unless it has already been set. The values are $x0 for 680x0. If SYS_FPU is non zero FPSAVE checks that its value is correct assuming no FPSP. If so it adds 8 for 'FPSP loaded'. If not FPSAVE aborts. If SYS_MMU is non zero FPSAVE checks that its value is correct else it aborts. There are two versions of the FPSP for the 68040 and 68060, library and kernel. The library version (which is used here) consists of routines which have to be called to implement the instructions not in the hardware. The kernel version enables programs to be written as for the 68881/2. An unimplemented instruction causes an F-line exception whose vector points to the FPSP which emulates the instruction. This process makes for easier programming but is very wasteful of time which is why we use the library version here. If a program is written as for a 68040 or 68060 with FPSP it can be run without modification or significant speed loss on a 68881/2 using the FPSP_81/2 provided. This is because the FPSP_81/2 consists of very short routines using the 68881/2 instructions directly. The trap to catch programs using the FPU depends on a forced exception, as described above. The vector to which this goes has an offset of $C8. In order that this can work it is essential that the Vector Base Register (VBR) be relocated otherwise the exception will branch to the combined word addresses of the QDOS vectors UT_SCR and UT_ERR0 and cause an instant crash. FPSAVE does indeed relocate the VBR. This has the awkward consequence that current versions of the debugging aid QMON cannot be used since it has the annoying habit of resetting the VBR to zero! Since it might theoretically be possible for the FPU to contain a pending exception at the time when FPSAVE is LRESPR'd it arranges for the FPU to be reset if needed. APPENDIX1 - EXCEPTION ROUTINES By default no Floating Point exceptions are enabled. If they are enabled by a program a set of default routines which exist in the FPSP will be used. These do the minimum to allow processing to continue. Anyone wanting anything else must supply his own routines. The address of a related table must be set in A0 when the routine pointed to by SYS_CLFP is called to access the FPSP. This table must consist of a set of word offsets of each routine from the start of the table. The order of exceptions is DZ, INEX, OVFL, UNFL, SNAN, OPERR, BSUN, F-line, Unsupported data type and TRACE. It is a fairly complicated matter to produce valid exception routines for all the occurrences and, unfortunately, there is not space here to give details. However the file REAL_XXX_TXT shows what the routines are for FPSP_40. APPENDIX2 The code to set the address of the FPSP in A1 might be as follows: MOVEQ #MT_INF,D0 MT_INF = 0 TRAP #1 A0 = sys vars MOVE.L SYS_CLFP(A0),D0 SYS_CLFP = $D8 BEQ ERROR ----> SUBA.L A0,A0 signal "no user exception routines" JSR (D0.L) TST.L D0 OK? . . . BNE ERROR ----> . . . no ; ; A1 now contains the address of FPSP ; ACKNOWLEDGMENTS The FPSP_40 is derived from Motorola's MC68040 FPSP Rel 2.3 - 27th August 1993 and Motorola retain the copyright. No change of substance has been made but, where necessary, absolute addresses have been replaced by PC relative ones with corresponding alteration to code. Also the routines FMOVECR and FSINCOS (missing from the library version) were added. The suggested user exception or 'real_xxx' routines were made even shorter and are listed in the file REAL_XXX_TXT. The FPSP_81/2 were written by me. The FPSP_60 was obtained from Simon Goodwin and amended by me by the addition of branches at the beginning, the routines FMOVECR, I_TO_Q and Q_TO_I and the substitution of address register A5 for A6 throughout. George Gwilt 39 Oxgangs Road Edinburgh EH10 7BE TEL/FAX +44 (0)131 445 1266 e-mail geo.gwilt@argonet.co.uk