README revision 1.1 1 * NetBSD/m68k FPE (floating point emulation) README file
2 * Created Oct/??/95 by kenn (a] romulus.rutgers.edu (Ken Nakata)
3 * Last updated Nov/02/95 by kenn
4
5 1. INSTALLATION AND COMPILATION
6
7 To compile a kernel with FPE built-in, do the following:
8
9 1) Extract all files in the directory ${MYSYS}/arch/m68k/fpe
10
11 2) Add a line "options FPU_EMULATE" to your config file. If you are
12 going to use the resulted kernel on a machine with an FPU for
13 debugging purpose, add "options DEBUG_WITH_FPU" as well.
14
15 3) Follow the usual procedure to build a new kernel.
16
17 NOTE: If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as
18 emulated FPU. You will need a modified gas that generates cpID=6 for
19 floating point instructions, instead of normal cpID=1. Mount unionfs
20 or copy the gas source directory as you did with the kernel source tree,
21 and apply the following patch:
22
23 *** /usr/src/gnu/usr.bin/gas/config/tc-m68k.c Mon Nov 21 16:30:41 1994
24 --- gas/config/tc-m68k.c Fri Sep 29 07:59:06 1995
25 ***************
26 *** 1275,1281 ****
27 /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
28 memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
29 the_ins.operands[0].mode=MSCR;
30 ! the_ins.operands[0].reg=COPNUM; /* COP #1 */
31 opsfound++;
32 }
33
34 --- 1275,1281 ----
35 /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
36 memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
37 the_ins.operands[0].mode=MSCR;
38 ! the_ins.operands[0].reg=COP5; /* COP #6 */
39 opsfound++;
40 }
41
42
43 Also, with the DEBUG_WITH_FPU option, you will be able to run only ONE
44 process that uses FPE at once to get correct results.
45
46
47 2. MISSING PARTS
48
49 For missing instructions, refer to the Section 3. Other than that,
50 there is one thing that is missing from this version of FPE: packed
51 BCD support.
52
53 I have no plan to support it since it's rarely used. However, all we
54 need to support it is explosion/implosion functions between the
55 internal FP representation and the m68k PBCD format, so you are more
56 than welcome to write such functions if you wish to.
57
58
59 3. IMPLEMENTED INSTRUCTIONS
60
61 This is the list of implemented and unimplemented FPU instructions.
62 Most 040's directly supported type 0 instructions are already
63 implemented except FSGLDIV, FSGLMUL, FMOVE(M) FPcr, and FMOVECR.
64
65 Type field = bit 8-6 of opcode word
66
67 * Implemented Instructions
68
69 Type=0: FMOVE (mem->FPr), FINT, FINTRZ, FSQRT, FABS, FNEG, FGETEXP,
70 FGETMAN, FDIV, FADD, FMUL, FSGLDIV, FSCALE, FSGLMUL, FSUB,
71 FCMP, FTST, FMOVE (FPr->mem), FMOVEM (FPr), FMOVEM (FPcr),
72 FMOVECR, FLOGNP1, FLOGN, FLOG10, FLOG2, FMOD, FREM
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: FSINH, FETOXM1, FTANH, FATAN, FASIN, FATANH, FSIN, FTAN,
90 FETOX, FTWOTOX, FTENTOX, FCOSH, FACOS, FCOS, FSINCOS
91
92 Type=1: none
93
94 Type=2: none
95
96 Type=3: none
97
98 Type=4: FSAVE
99
100 Type=5: FRESTORE
101
102
103 4. HOW TO ADD A NEW INSTRUCTION SUPPORT
104
105 Since we need not support FSAVE and FRESTORE operations, all
106 instructions we have to implement are type 0, all of which are
107 arithmetic operations. It is particularly easy to add a new
108 arithmetic instruction to the existing ones (not that it is easy to
109 write a "stable" function to perform floating point operation. That's
110 entirely another matter). In "fpu_emulate.c", there's a function
111 fpu_emul_arith() which calls emulation functions for all arithmetic
112 operations. In it, there's a large switch() { case ... } which
113 dispatches each instruction emulator. An emulation function of any
114 type 0 arithmetic instruction follows this prototype:
115
116 struct fpn *fpu_op(struct fpemu *fe);
117
118 Where fe is a pointer to a struct fpemu in which frame, fpframe, and
119 fetched operands are accessible. That's right, you don't have to
120 fetch the operands by yourself in your emulation funtion. For
121 instance, the parts calling FSQRT, FSUB, FADD and FTST look like:
122
123 switch(word1 & 0x3F) {
124 [...]
125 case 0x04: /* fsqrt */
126 res = fpu_sqrt(fe);
127 break;
128 [...]
129 case 0x28: /* fsub */
130 fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
131 case 0x22: /* fadd */
132 res = fpu_add(fe);
133 break;
134 [...]
135 case 0x3A: /* ftst */
136 res = &fe->fe_f2;
137 no_store = 1;
138 break;
139 [...]
140 default:
141 sig = SIGILL;
142 } /* switch */
143
144 Here, fe->fe_f1 and fe->fe_f2 are fetched operands. You can use
145 fe->fe_f3 for storing the result, or you can return a pointer to
146 either operand if you want to. At any rate, you have to follow
147 the following rules:
148
149 1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2.
150 2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1).
151 3) Must return a pointer to struct fpn where the result is stored,
152 and assign the pointer to the variable "res".
153 4) If exceptions are detected, set corresponding bits in fe->fe_fpsr.
154 The rest is taken care of in fpu_emul_arith().
155 5) Condition code need not be calculated. It's taken care of in
156 fpu_emul_arith().
157
158 It's easy to interface, isn't it?
159
160 * Actually, after above was written, stubs for the missing functions
161 are added to the source, so you do not have to change fpu_emul_arith()
162 at all. Function names and prototypes are in fpu_arith_proto.h, and
163 all (except fpu_sincos()) follows the rules above.
164
165