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