1* $NetBSD: README,v 1.4 1995/11/05 04:23:00 briggs Exp $ 2* NetBSD/m68k FPE (floating point emulation) README file 3* Created Oct/??/95 by kenn@remus.rutgers.edu (Ken Nakata) 4* Last updated Nov/04/95 by kenn 5 61. INSTALLATION AND COMPILATION 7 8To compile a kernel with FPE built-in, do the following: 9 101) Add a line "options FPU_EMULATE" to your config file. If you are 11going to use the resulted kernel on a machine with an FPU for 12debugging purpose, add "options DEBUG_WITH_FPU" as well. 13 142) Follow the usual procedure to build a new kernel. 15 16NOTE: If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as 17emulated FPU. You will need a modified gas that generates cpID=6 for 18floating point instructions, instead of normal cpID=1. Mount unionfs 19or 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 41Also, with the DEBUG_WITH_FPU option, you will be able to run only ONE 42process that uses FPE at once to get correct results. 43 44 452. MISSING PARTS 46 47For missing instructions, refer to the Section 3. Other than that, 48there is one thing that is missing from this version of FPE: packed 49BCD support. 50 51I have no plan to support it since it's rarely used. However, all we 52need to support it is explosion/implosion functions between the 53internal FP representation and the m68k PBCD format, so you are more 54than welcome to write such functions if you wish to. 55 56 573. IMPLEMENTED INSTRUCTIONS 58 59This is the list of implemented and unimplemented FPU instructions. 60All 040's directly supported type 0 instructions are already 61implemented except FSGLDIV and FSGLMUL. 62 63Type field = bit 8-6 of opcode word 64 65* Implemented Instructions 66 67Type=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 72Type=1: FDBcc, FScc, FTRAPcc, 73 74Type=2: FBcc (word, incl. FNOP) 75 76Type=3: FBcc (long) 77 78Type=4: none 79 80Type=5: none 81 82 *: currently FSGLMUL and FSGLDIV are just aliases of 83 FMUL and FDIV, respectively 84 85* Unimplemented Instructions 86 87Type=0: FSINH, FETOXM1, FTANH, FATAN, FASIN, FATANH, FSIN, FTAN, 88 FETOX, FTWOTOX, FTENTOX, FCOSH, FACOS, FCOS, FSINCOS 89 90Type=1: none 91 92Type=2: none 93 94Type=3: none 95 96Type=4: FSAVE 97 98Type=5: FRESTORE 99 100 1014. HOW TO ADD A NEW INSTRUCTION SUPPORT 102 103Since we need not support FSAVE and FRESTORE operations, all 104instructions we have to implement are type 0, all of which are 105arithmetic operations. It is particularly easy to add a new 106arithmetic instruction to the existing ones (not that it is easy to 107write a "stable" function to perform floating point operation. That's 108entirely another matter). In "fpu_emulate.c", there's a function 109fpu_emul_arith() which calls emulation functions for all arithmetic 110operations. In it, there's a large switch() { case ... } which 111dispatches each instruction emulator. An emulation function of any 112type 0 arithmetic instruction follows this prototype: 113 114 struct fpn *fpu_op(struct fpemu *fe); 115 116Where fe is a pointer to a struct fpemu in which frame, fpframe, and 117fetched operands are accessible. That's right, you don't have to 118fetch the operands by yourself in your emulation funtion. For 119instance, 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 142Here, fe->fe_f1 and fe->fe_f2 are fetched operands. You can use 143fe->fe_f3 for storing the result, or you can return a pointer to 144either operand if you want to. At any rate, you have to follow 145the 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 156Actually, after above was written, stubs for the missing functions were 157added to the source, so you do not have to change fpu_emul_arith() at 158all. Function names and prototypes are in fpu_arith_proto.h, and all 159except fpu_sincos() follow the rules above. fpu_sincos() is declared 160as 161 162 struct fpn *fpu_sincos(struct fpemu *fe, int cosreg); 163 164where cosreg is the FP register number to which cosine of the argument 165is calculated and assigned. Sine of the argument is stored into the 166destination register in the same manner as the other arithmetic 167functions. 168