Home | History | Annotate | Line # | Download | only in fpe
README revision 1.1
      1 * NetBSD/m68k FPE (floating point emulation) README file
      2 * Created Oct/??/95 by kenn (a] romulus.rutgers.edu (Ken Nakata)
      3 * Last updated Nov/02/95 by kenn
      4 
      5 1. INSTALLATION AND COMPILATION
      6 
      7 To compile a kernel with FPE built-in, do the following:
      8 
      9 1) Extract all files in the directory ${MYSYS}/arch/m68k/fpe
     10 
     11 2) Add a line "options FPU_EMULATE" to your config file.  If you are
     12 going to use the resulted kernel on a machine with an FPU for
     13 debugging purpose, add "options DEBUG_WITH_FPU" as well.
     14 
     15 3) Follow the usual procedure to build a new kernel.
     16 
     17 NOTE:  If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as
     18 emulated FPU.  You will need a modified gas that generates cpID=6 for
     19 floating point instructions, instead of normal cpID=1.  Mount unionfs
     20 or copy the gas source directory as you did with the kernel source tree,
     21 and apply the following patch:
     22 
     23 *** /usr/src/gnu/usr.bin/gas/config/tc-m68k.c   Mon Nov 21 16:30:41 1994
     24 --- gas/config/tc-m68k.c    Fri Sep 29 07:59:06 1995
     25 ***************
     26 *** 1275,1281 ****
     27                 /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
     28                 memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
     29                 the_ins.operands[0].mode=MSCR;
     30 !               the_ins.operands[0].reg=COPNUM;         /* COP #1 */
     31                 opsfound++;
     32         }
     33   
     34 --- 1275,1281 ----
     35                 /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
     36                 memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
     37                 the_ins.operands[0].mode=MSCR;
     38 !               the_ins.operands[0].reg=COP5;           /* COP #6 */
     39                 opsfound++;
     40         }
     41   
     42 
     43 Also, with the DEBUG_WITH_FPU option, you will be able to run only ONE
     44 process that uses FPE at once to get correct results.
     45 
     46 
     47 2. MISSING PARTS
     48 
     49 For missing instructions, refer to the Section 3.  Other than that,
     50 there is one thing that is missing from this version of FPE: packed
     51 BCD support.
     52 
     53 I have no plan to support it since it's rarely used.  However, all we
     54 need to support it is explosion/implosion functions between the
     55 internal FP representation and the m68k PBCD format, so you are more
     56 than welcome to write such functions if you wish to.
     57 
     58 
     59 3. IMPLEMENTED INSTRUCTIONS
     60 
     61 This is the list of implemented and unimplemented FPU instructions.
     62 Most 040's directly supported type 0 instructions are already
     63 implemented except FSGLDIV, FSGLMUL, FMOVE(M) FPcr, and FMOVECR.
     64 
     65 Type field = bit 8-6 of opcode word
     66 
     67 * Implemented Instructions
     68 
     69 Type=0: FMOVE (mem->FPr), FINT, FINTRZ, FSQRT, FABS, FNEG, FGETEXP,
     70 	FGETMAN, FDIV, FADD, FMUL, FSGLDIV, FSCALE, FSGLMUL, FSUB,
     71 	FCMP, FTST, FMOVE (FPr->mem), FMOVEM (FPr), FMOVEM (FPcr),
     72 	FMOVECR, FLOGNP1, FLOGN, FLOG10, FLOG2, FMOD, FREM
     73 
     74 Type=1: FDBcc, FScc, FTRAPcc,
     75 
     76 Type=2: FBcc (word, incl. FNOP)
     77 
     78 Type=3: FBcc (long)
     79 
     80 Type=4: none
     81 
     82 Type=5: none
     83 
     84 	*: currently FSGLMUL and FSGLDIV are just aliases of
     85 	   FMUL and FDIV, respectively
     86 
     87 * Unimplemented Instructions
     88 
     89 Type=0: FSINH, FETOXM1, FTANH, FATAN, FASIN, FATANH, FSIN, FTAN,
     90 	FETOX, FTWOTOX, FTENTOX, FCOSH, FACOS, FCOS, FSINCOS
     91 
     92 Type=1: none
     93 
     94 Type=2: none
     95 
     96 Type=3: none
     97 
     98 Type=4: FSAVE
     99 
    100 Type=5: FRESTORE
    101 
    102 
    103 4. HOW TO ADD A NEW INSTRUCTION SUPPORT
    104 
    105 Since we need not support FSAVE and FRESTORE operations, all
    106 instructions we have to implement are type 0, all of which are
    107 arithmetic operations.  It is particularly easy to add a new
    108 arithmetic instruction to the existing ones (not that it is easy to
    109 write a "stable" function to perform floating point operation. That's
    110 entirely another matter).  In "fpu_emulate.c", there's a function
    111 fpu_emul_arith() which calls emulation functions for all arithmetic
    112 operations.  In it, there's a large switch() { case ... } which
    113 dispatches each instruction emulator.  An emulation function of any
    114 type 0 arithmetic instruction follows this prototype:
    115 
    116 	struct fpn *fpu_op(struct fpemu *fe);
    117 
    118 Where fe is a pointer to a struct fpemu in which frame, fpframe, and
    119 fetched operands are accessible.  That's right, you don't have to
    120 fetch the operands by yourself in your emulation funtion.  For
    121 instance, the parts calling FSQRT, FSUB, FADD and FTST look like:
    122 
    123 	switch(word1 & 0x3F) {
    124 [...]
    125 	case 0x04:	/* fsqrt */
    126 		res = fpu_sqrt(fe);
    127 		break;
    128 [...]
    129 	case 0x28:	/* fsub */
    130 		fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
    131 	case 0x22:	/* fadd */
    132 		res = fpu_add(fe);
    133 		break;
    134 [...]
    135 	case 0x3A:	/* ftst */
    136 		res = &fe->fe_f2;
    137 		no_store = 1;
    138 		break;
    139 [...]
    140 	default:
    141 		sig = SIGILL;
    142 	} /* switch */
    143 
    144 Here, fe->fe_f1 and fe->fe_f2 are fetched operands.  You can use
    145 fe->fe_f3 for storing the result, or you can return a pointer to
    146 either operand if you want to.  At any rate, you have to follow
    147 the following rules:
    148 
    149 	1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2.
    150 	2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1).
    151 	3) Must return a pointer to struct fpn where the result is stored,
    152 	and assign the pointer to the variable "res".
    153 	4) If exceptions are detected, set corresponding bits in fe->fe_fpsr.
    154 	The rest is taken care of in fpu_emul_arith().
    155 	5) Condition code need not be calculated.  It's taken care of in
    156 	fpu_emul_arith().
    157 
    158 It's easy to interface, isn't it?
    159 
    160 * Actually, after above was written, stubs for the missing functions
    161 are added to the source, so you do not have to change fpu_emul_arith()
    162 at all.  Function names and prototypes are in fpu_arith_proto.h, and
    163 all (except fpu_sincos()) follows the rules above.
    164 
    165