README revision 1.5
11.5Stsutsui* $NetBSD: README,v 1.5 2011/10/15 15:24:28 tsutsui Exp $ 21.1Sbriggs* NetBSD/m68k FPE (floating point emulation) README file 31.4Sbriggs* Created Oct/??/95 by kenn@remus.rutgers.edu (Ken Nakata) 41.5Stsutsui* Last updated Oct/15/2011 by tsutsui 51.1Sbriggs 61.1Sbriggs1. INSTALLATION AND COMPILATION 71.1Sbriggs 81.1SbriggsTo compile a kernel with FPE built-in, do the following: 91.1Sbriggs 101.2Sbriggs1) Add a line "options FPU_EMULATE" to your config file. If you are 111.1Sbriggsgoing to use the resulted kernel on a machine with an FPU for 121.1Sbriggsdebugging purpose, add "options DEBUG_WITH_FPU" as well. 131.1Sbriggs 141.2Sbriggs2) Follow the usual procedure to build a new kernel. 151.1Sbriggs 161.1SbriggsNOTE: If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as 171.1Sbriggsemulated FPU. You will need a modified gas that generates cpID=6 for 181.1Sbriggsfloating point instructions, instead of normal cpID=1. Mount unionfs 191.4Sbriggsor copy the gas source directory and apply the following patch: 201.1Sbriggs 211.1Sbriggs*** /usr/src/gnu/usr.bin/gas/config/tc-m68k.c Mon Nov 21 16:30:41 1994 221.1Sbriggs--- gas/config/tc-m68k.c Fri Sep 29 07:59:06 1995 231.1Sbriggs*************** 241.1Sbriggs*** 1275,1281 **** 251.1Sbriggs /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */ 261.1Sbriggs memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0])); 271.1Sbriggs the_ins.operands[0].mode=MSCR; 281.1Sbriggs! the_ins.operands[0].reg=COPNUM; /* COP #1 */ 291.1Sbriggs opsfound++; 301.1Sbriggs } 311.1Sbriggs 321.1Sbriggs--- 1275,1281 ---- 331.1Sbriggs /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */ 341.1Sbriggs memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0])); 351.1Sbriggs the_ins.operands[0].mode=MSCR; 361.1Sbriggs! the_ins.operands[0].reg=COP5; /* COP #6 */ 371.1Sbriggs opsfound++; 381.1Sbriggs } 391.1Sbriggs 401.1Sbriggs 411.1SbriggsAlso, with the DEBUG_WITH_FPU option, you will be able to run only ONE 421.1Sbriggsprocess that uses FPE at once to get correct results. 431.1Sbriggs 441.1Sbriggs 451.1Sbriggs2. MISSING PARTS 461.1Sbriggs 471.1SbriggsFor missing instructions, refer to the Section 3. Other than that, 481.1Sbriggsthere is one thing that is missing from this version of FPE: packed 491.1SbriggsBCD support. 501.1Sbriggs 511.1SbriggsI have no plan to support it since it's rarely used. However, all we 521.1Sbriggsneed to support it is explosion/implosion functions between the 531.1Sbriggsinternal FP representation and the m68k PBCD format, so you are more 541.1Sbriggsthan welcome to write such functions if you wish to. 551.1Sbriggs 561.1Sbriggs 571.1Sbriggs3. IMPLEMENTED INSTRUCTIONS 581.1Sbriggs 591.1SbriggsThis is the list of implemented and unimplemented FPU instructions. 601.4SbriggsAll 040's directly supported type 0 instructions are already 611.4Sbriggsimplemented except FSGLDIV and FSGLMUL. 621.1Sbriggs 631.1SbriggsType field = bit 8-6 of opcode word 641.1Sbriggs 651.1Sbriggs* Implemented Instructions 661.1Sbriggs 671.1SbriggsType=0: FMOVE (mem->FPr), FINT, FINTRZ, FSQRT, FABS, FNEG, FGETEXP, 681.4Sbriggs FGETMAN, FDIV, FADD, FMUL, FSGLDIV(*), FSCALE, FSGLMUL(*), FSUB, 691.1Sbriggs FCMP, FTST, FMOVE (FPr->mem), FMOVEM (FPr), FMOVEM (FPcr), 701.5Stsutsui FMOVECR, FLOGNP1, FLOGN, FLOG10, FLOG2, FMOD, FREM, 711.5Stsutsui FCOSH, FSINH, FTANH, FCOS, FSIN, FTAN, FSINCOS 721.1Sbriggs 731.1SbriggsType=1: FDBcc, FScc, FTRAPcc, 741.1Sbriggs 751.1SbriggsType=2: FBcc (word, incl. FNOP) 761.1Sbriggs 771.1SbriggsType=3: FBcc (long) 781.1Sbriggs 791.1SbriggsType=4: none 801.1Sbriggs 811.1SbriggsType=5: none 821.1Sbriggs 831.1Sbriggs *: currently FSGLMUL and FSGLDIV are just aliases of 841.1Sbriggs FMUL and FDIV, respectively 851.1Sbriggs 861.1Sbriggs* Unimplemented Instructions 871.1Sbriggs 881.5StsutsuiType=0: FETOX, FETOXM1, FTENTOX, FTWOTOX, FATANH, FACOS, FASIN, FATAN 891.1Sbriggs 901.1SbriggsType=1: none 911.1Sbriggs 921.1SbriggsType=2: none 931.1Sbriggs 941.1SbriggsType=3: none 951.1Sbriggs 961.1SbriggsType=4: FSAVE 971.1Sbriggs 981.1SbriggsType=5: FRESTORE 991.1Sbriggs 1001.1Sbriggs 1011.1Sbriggs4. HOW TO ADD A NEW INSTRUCTION SUPPORT 1021.1Sbriggs 1031.1SbriggsSince we need not support FSAVE and FRESTORE operations, all 1041.1Sbriggsinstructions we have to implement are type 0, all of which are 1051.1Sbriggsarithmetic operations. It is particularly easy to add a new 1061.1Sbriggsarithmetic instruction to the existing ones (not that it is easy to 1071.1Sbriggswrite a "stable" function to perform floating point operation. That's 1081.1Sbriggsentirely another matter). In "fpu_emulate.c", there's a function 1091.1Sbriggsfpu_emul_arith() which calls emulation functions for all arithmetic 1101.1Sbriggsoperations. In it, there's a large switch() { case ... } which 1111.1Sbriggsdispatches each instruction emulator. An emulation function of any 1121.1Sbriggstype 0 arithmetic instruction follows this prototype: 1131.1Sbriggs 1141.1Sbriggs struct fpn *fpu_op(struct fpemu *fe); 1151.1Sbriggs 1161.1SbriggsWhere fe is a pointer to a struct fpemu in which frame, fpframe, and 1171.1Sbriggsfetched operands are accessible. That's right, you don't have to 1181.1Sbriggsfetch the operands by yourself in your emulation funtion. For 1191.1Sbriggsinstance, the parts calling FSQRT, FSUB, FADD and FTST look like: 1201.1Sbriggs 1211.1Sbriggs switch(word1 & 0x3F) { 1221.1Sbriggs[...] 1231.1Sbriggs case 0x04: /* fsqrt */ 1241.1Sbriggs res = fpu_sqrt(fe); 1251.1Sbriggs break; 1261.1Sbriggs[...] 1271.1Sbriggs case 0x28: /* fsub */ 1281.1Sbriggs fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */ 1291.1Sbriggs case 0x22: /* fadd */ 1301.1Sbriggs res = fpu_add(fe); 1311.1Sbriggs break; 1321.1Sbriggs[...] 1331.1Sbriggs case 0x3A: /* ftst */ 1341.1Sbriggs res = &fe->fe_f2; 1351.1Sbriggs no_store = 1; 1361.1Sbriggs break; 1371.1Sbriggs[...] 1381.1Sbriggs default: 1391.1Sbriggs sig = SIGILL; 1401.1Sbriggs } /* switch */ 1411.1Sbriggs 1421.1SbriggsHere, fe->fe_f1 and fe->fe_f2 are fetched operands. You can use 1431.1Sbriggsfe->fe_f3 for storing the result, or you can return a pointer to 1441.1Sbriggseither operand if you want to. At any rate, you have to follow 1451.1Sbriggsthe following rules: 1461.1Sbriggs 1471.1Sbriggs 1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2. 1481.1Sbriggs 2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1). 1491.1Sbriggs 3) Must return a pointer to struct fpn where the result is stored, 1501.1Sbriggs and assign the pointer to the variable "res". 1511.1Sbriggs 4) If exceptions are detected, set corresponding bits in fe->fe_fpsr. 1521.1Sbriggs The rest is taken care of in fpu_emul_arith(). 1531.1Sbriggs 5) Condition code need not be calculated. It's taken care of in 1541.1Sbriggs fpu_emul_arith(). 1551.1Sbriggs 1561.4SbriggsActually, after above was written, stubs for the missing functions were 1571.4Sbriggsadded to the source, so you do not have to change fpu_emul_arith() at 1581.4Sbriggsall. Function names and prototypes are in fpu_arith_proto.h, and all 1591.4Sbriggsexcept fpu_sincos() follow the rules above. fpu_sincos() is declared 1601.4Sbriggsas 1611.4Sbriggs 1621.4Sbriggs struct fpn *fpu_sincos(struct fpemu *fe, int cosreg); 1631.4Sbriggs 1641.4Sbriggswhere cosreg is the FP register number to which cosine of the argument 1651.4Sbriggsis calculated and assigned. Sine of the argument is stored into the 1661.4Sbriggsdestination register in the same manner as the other arithmetic 1671.4Sbriggsfunctions. 168