|
|
1.1 root 1: * $NetBSD: README,v 1.6 2013/04/20 03:26:11 isaki Exp $
2: * NetBSD/m68k FPE (floating point emulation) README file
3: * Created Oct/??/95 by [email protected] (Ken Nakata)
4: * Last updated Oct/15/2011 by tsutsui
5:
6: 1. INSTALLATION AND COMPILATION
7:
8: To compile a kernel with FPE built-in, do the following:
9:
10: 1) Add a line "options FPU_EMULATE" to your config file. If you are
11: going to use the resulted kernel on a machine with an FPU for
12: debugging purpose, add "options DEBUG_WITH_FPU" as well.
13:
14: 2) Follow the usual procedure to build a new kernel.
15:
16: NOTE: If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as
17: emulated FPU. You will need a modified gas that generates cpID=6 for
18: floating point instructions, instead of normal cpID=1. Mount unionfs
19: or 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:
41: Also, with the DEBUG_WITH_FPU option, you will be able to run only ONE
42: process that uses FPE at once to get correct results.
43:
44:
45: 2. MISSING PARTS
46:
47: For missing instructions, refer to the Section 3. Other than that,
48: there is one thing that is missing from this version of FPE: packed
49: BCD support.
50:
51: I have no plan to support it since it's rarely used. However, all we
52: need to support it is explosion/implosion functions between the
53: internal FP representation and the m68k PBCD format, so you are more
54: than welcome to write such functions if you wish to.
55:
56:
57: 3. IMPLEMENTED INSTRUCTIONS
58:
59: This is the list of implemented and unimplemented FPU instructions.
60: All 040's directly supported type 0 instructions are already
61: implemented except FSGLDIV and FSGLMUL.
62:
63: Type field = bit 8-6 of opcode word
64:
65: * Implemented Instructions
66:
67: Type=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: FCOSH, FSINH, FTANH, FCOS, FSIN, FTAN, FSINCOS,
72: FETOX, FETOXM1, FTENTOX, FTWOTOX, FATANH, FACOS, FASIN, FATAN
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: none
90:
91: Type=1: none
92:
93: Type=2: none
94:
95: Type=3: none
96:
97: Type=4: FSAVE
98:
99: Type=5: FRESTORE
100:
101:
102: 4. HOW TO ADD A NEW INSTRUCTION SUPPORT
103:
104: Since we need not support FSAVE and FRESTORE operations, all
105: instructions we have to implement are type 0, all of which are
106: arithmetic operations. It is particularly easy to add a new
107: arithmetic instruction to the existing ones (not that it is easy to
108: write a "stable" function to perform floating point operation. That's
109: entirely another matter). In "fpu_emulate.c", there's a function
110: fpu_emul_arith() which calls emulation functions for all arithmetic
111: operations. In it, there's a large switch() { case ... } which
112: dispatches each instruction emulator. An emulation function of any
113: type 0 arithmetic instruction follows this prototype:
114:
115: struct fpn *fpu_op(struct fpemu *fe);
116:
117: Where fe is a pointer to a struct fpemu in which frame, fpframe, and
118: fetched operands are accessible. That's right, you don't have to
119: fetch the operands by yourself in your emulation funtion. For
120: instance, the parts calling FSQRT, FSUB, FADD and FTST look like:
121:
122: switch(word1 & 0x3F) {
123: [...]
124: case 0x04: /* fsqrt */
125: res = fpu_sqrt(fe);
126: break;
127: [...]
128: case 0x28: /* fsub */
129: fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
130: case 0x22: /* fadd */
131: res = fpu_add(fe);
132: break;
133: [...]
134: case 0x3A: /* ftst */
135: res = &fe->fe_f2;
136: no_store = 1;
137: break;
138: [...]
139: default:
140: sig = SIGILL;
141: } /* switch */
142:
143: Here, fe->fe_f1 and fe->fe_f2 are fetched operands. You can use
144: fe->fe_f3 for storing the result, or you can return a pointer to
145: either operand if you want to. At any rate, you have to follow
146: the following rules:
147:
148: 1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2.
149: 2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1).
150: 3) Must return a pointer to struct fpn where the result is stored,
151: and assign the pointer to the variable "res".
152: 4) If exceptions are detected, set corresponding bits in fe->fe_fpsr.
153: The rest is taken care of in fpu_emul_arith().
154: 5) Condition code need not be calculated. It's taken care of in
155: fpu_emul_arith().
156:
157: Actually, after above was written, stubs for the missing functions were
158: added to the source, so you do not have to change fpu_emul_arith() at
159: all. Function names and prototypes are in fpu_arith_proto.h, and all
160: except fpu_sincos() follow the rules above. fpu_sincos() is declared
161: as
162:
163: struct fpn *fpu_sincos(struct fpemu *fe, int cosreg);
164:
165: where cosreg is the FP register number to which cosine of the argument
166: is calculated and assigned. Sine of the argument is stored into the
167: destination register in the same manner as the other arithmetic
168: functions.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.