Annotation of nono/fpe/README, revision 1.1.1.1

1.1       root        1: * $NetBSD: README,v 1.6 2013/04/20 03:26:11 isaki Exp $
                      2: * NetBSD/m68k FPE (floating point emulation) README file
                      3: * Created Oct/??/95 by [email protected] (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 funtion.  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.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.