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