Home | History | Annotate | Line # | Download | only in fpe
      1 * $NetBSD: README,v 1.7 2021/08/21 23:00:31 andvar 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 	FETOX, FETOXM1, FTENTOX, FTWOTOX, FATANH, FACOS, FASIN, FATAN
     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: none
     90 
     91 Type=1: none
     92 
     93 Type=2: none
     94 
     95 Type=3: none
     96 
     97 Type=4: FSAVE
     98 
     99 Type=5: FRESTORE
    100 
    101 
    102 4. HOW TO ADD A NEW INSTRUCTION SUPPORT
    103 
    104 Since we need not support FSAVE and FRESTORE operations, all
    105 instructions we have to implement are type 0, all of which are
    106 arithmetic operations.  It is particularly easy to add a new
    107 arithmetic instruction to the existing ones (not that it is easy to
    108 write a "stable" function to perform floating point operation. That's
    109 entirely another matter).  In "fpu_emulate.c", there's a function
    110 fpu_emul_arith() which calls emulation functions for all arithmetic
    111 operations.  In it, there's a large switch() { case ... } which
    112 dispatches each instruction emulator.  An emulation function of any
    113 type 0 arithmetic instruction follows this prototype:
    114 
    115 	struct fpn *fpu_op(struct fpemu *fe);
    116 
    117 Where fe is a pointer to a struct fpemu in which frame, fpframe, and
    118 fetched operands are accessible.  That's right, you don't have to
    119 fetch the operands by yourself in your emulation function.  For
    120 instance, the parts calling FSQRT, FSUB, FADD and FTST look like:
    121 
    122 	switch(word1 & 0x3F) {
    123 [...]
    124 	case 0x04:	/* fsqrt */
    125 		res = fpu_sqrt(fe);
    126 		break;
    127 [...]
    128 	case 0x28:	/* fsub */
    129 		fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
    130 	case 0x22:	/* fadd */
    131 		res = fpu_add(fe);
    132 		break;
    133 [...]
    134 	case 0x3A:	/* ftst */
    135 		res = &fe->fe_f2;
    136 		no_store = 1;
    137 		break;
    138 [...]
    139 	default:
    140 		sig = SIGILL;
    141 	} /* switch */
    142 
    143 Here, fe->fe_f1 and fe->fe_f2 are fetched operands.  You can use
    144 fe->fe_f3 for storing the result, or you can return a pointer to
    145 either operand if you want to.  At any rate, you have to follow
    146 the following rules:
    147 
    148 	1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2.
    149 	2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1).
    150 	3) Must return a pointer to struct fpn where the result is stored,
    151 	and assign the pointer to the variable "res".
    152 	4) If exceptions are detected, set corresponding bits in fe->fe_fpsr.
    153 	The rest is taken care of in fpu_emul_arith().
    154 	5) Condition code need not be calculated.  It's taken care of in
    155 	fpu_emul_arith().
    156 
    157 Actually, after above was written, stubs for the missing functions were
    158 added to the source, so you do not have to change fpu_emul_arith() at
    159 all.  Function names and prototypes are in fpu_arith_proto.h, and all
    160 except fpu_sincos() follow the rules above.  fpu_sincos() is declared
    161 as
    162 
    163 	struct fpn *fpu_sincos(struct fpemu *fe, int cosreg);
    164 
    165 where cosreg is the FP register number to which cosine of the argument
    166 is calculated and assigned.  Sine of the argument is stored into the
    167 destination register in the same manner as the other arithmetic
    168 functions.
    169