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