|
|
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.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.