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