fpudispatch.c revision 1.2 1 1.2 lukem /* $NetBSD: fpudispatch.c,v 1.2 2003/07/15 02:29:42 lukem Exp $ */
2 1.1 fredette
3 1.1 fredette /*
4 1.1 fredette * (c) Copyright 1991 HEWLETT-PACKARD COMPANY
5 1.1 fredette *
6 1.1 fredette * To anyone who acknowledges that this file is provided "AS IS"
7 1.1 fredette * without any express or implied warranty:
8 1.1 fredette * permission to use, copy, modify, and distribute this file
9 1.1 fredette * for any purpose is hereby granted without fee, provided that
10 1.1 fredette * the above copyright notice and this notice appears in all
11 1.1 fredette * copies, and that the name of Hewlett-Packard Company not be
12 1.1 fredette * used in advertising or publicity pertaining to distribution
13 1.1 fredette * of the software without specific, written prior permission.
14 1.1 fredette * Hewlett-Packard Company makes no representations about the
15 1.1 fredette * suitability of this software for any purpose.
16 1.1 fredette */
17 1.1 fredette
18 1.1 fredette /* Source: /n/schirf/u/baford/CVS/mach4-parisc/kernel/parisc/fpudispatch.c,v
19 1.1 fredette * Revision: 1.4 Author: mike
20 1.1 fredette * State: Exp Locker:
21 1.1 fredette * Date: 1994/07/21 17:36:35
22 1.1 fredette */
23 1.2 lukem
24 1.2 lukem #include <sys/cdefs.h>
25 1.2 lukem __KERNEL_RCSID(0, "$NetBSD: fpudispatch.c,v 1.2 2003/07/15 02:29:42 lukem Exp $");
26 1.1 fredette
27 1.1 fredette #include <sys/types.h>
28 1.1 fredette #include <sys/systm.h>
29 1.1 fredette
30 1.1 fredette #include "../spmath/float.h"
31 1.1 fredette /*
32 1.1 fredette * XXX fredette - hack to glue the bulk of
33 1.1 fredette * the spmath library to this dispatcher.
34 1.1 fredette */
35 1.1 fredette #define dbl_integer unsigned
36 1.1 fredette #define sgl_floating_point unsigned
37 1.1 fredette #define dbl_floating_point unsigned
38 1.1 fredette #include "../spmath/sgl_float.h"
39 1.1 fredette #include "../spmath/dbl_float.h"
40 1.1 fredette #include "../spmath/cnv_float.h"
41 1.1 fredette #include "../spmath/md.h"
42 1.1 fredette #include "../spmath/fpudispatch.h"
43 1.1 fredette
44 1.1 fredette /*
45 1.1 fredette * version of EMULATION software for COPR,0,0 instruction
46 1.1 fredette */
47 1.1 fredette #define EMULATION_VERSION 3
48 1.1 fredette #define COPR_INST 0x30000000
49 1.1 fredette
50 1.1 fredette /*
51 1.1 fredette * definition of extru macro. If pos and len are constants, the compiler
52 1.1 fredette * will generate an extru instruction when optimized
53 1.1 fredette */
54 1.1 fredette #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
55 1.1 fredette /* definitions of bit field locations in the instruction */
56 1.1 fredette #define fpmajorpos 5
57 1.1 fredette #define fpr1pos 10
58 1.1 fredette #define fpr2pos 15
59 1.1 fredette #define fptpos 31
60 1.1 fredette #define fpsubpos 18
61 1.1 fredette #define fpclass1subpos 16
62 1.1 fredette #define fpclasspos 22
63 1.1 fredette #define fpfmtpos 20
64 1.1 fredette #define fpdfpos 18
65 1.1 fredette /*
66 1.1 fredette * the following are the extra bits for the 0E major op
67 1.1 fredette */
68 1.1 fredette #define fpxr1pos 24
69 1.1 fredette #define fpxr2pos 19
70 1.1 fredette #define fpxtpos 25
71 1.1 fredette #define fpxpos 23
72 1.1 fredette #define fp0efmtpos 20
73 1.1 fredette /*
74 1.1 fredette * the following are for the multi-ops
75 1.1 fredette */
76 1.1 fredette #define fprm1pos 10
77 1.1 fredette #define fprm2pos 15
78 1.1 fredette #define fptmpos 31
79 1.1 fredette #define fprapos 25
80 1.1 fredette #define fptapos 20
81 1.1 fredette #define fpmultifmt 26
82 1.1 fredette
83 1.1 fredette /*
84 1.1 fredette * offset to constant zero in the FP emulation registers
85 1.1 fredette */
86 1.1 fredette #define fpzeroreg (32*sizeof(double)/sizeof(unsigned))
87 1.1 fredette
88 1.1 fredette /*
89 1.1 fredette * extract the major opcode from the instruction
90 1.1 fredette */
91 1.1 fredette #define get_major(op) extru(op,fpmajorpos,6)
92 1.1 fredette /*
93 1.1 fredette * extract the two bit class field from the FP instruction. The class is at bit
94 1.1 fredette * positions 21-22
95 1.1 fredette */
96 1.1 fredette #define get_class(op) extru(op,fpclasspos,2)
97 1.1 fredette /*
98 1.1 fredette * extract the 3 bit subop field. For all but class 1 instructions, it is
99 1.1 fredette * located at bit positions 16-18
100 1.1 fredette */
101 1.1 fredette #define get_subop(op) extru(op,fpsubpos,3)
102 1.1 fredette /*
103 1.1 fredette * extract the 2 bit subop field from class 1 instructions. It is located
104 1.1 fredette * at bit positions 15-16
105 1.1 fredette */
106 1.1 fredette #define get_subop1(op) extru(op,fpclass1subpos,2)
107 1.1 fredette
108 1.1 fredette /* definitions of unimplemented exceptions */
109 1.1 fredette #define MAJOR_0C_EXCP UNIMPLEMENTEDEXCEPTION
110 1.1 fredette #define MAJOR_0E_EXCP UNIMPLEMENTEDEXCEPTION
111 1.1 fredette #define MAJOR_06_EXCP UNIMPLEMENTEDEXCEPTION
112 1.1 fredette #define MAJOR_26_EXCP UNIMPLEMENTEDEXCEPTION
113 1.1 fredette #define PA83_UNIMP_EXCP UNIMPLEMENTEDEXCEPTION
114 1.1 fredette
115 1.1 fredette int
116 1.1 fredette decode_0c(ir,class,subop,fpregs)
117 1.1 fredette unsigned ir,class,subop;
118 1.1 fredette unsigned fpregs[];
119 1.1 fredette {
120 1.1 fredette unsigned r1,r2,t; /* operand register offsets */
121 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */
122 1.1 fredette unsigned df; /* for class 1 conversions */
123 1.1 fredette unsigned *status;
124 1.1 fredette
125 1.1 fredette if (ir == COPR_INST) {
126 1.1 fredette fpregs[0] = EMULATION_VERSION << 11;
127 1.1 fredette return(NOEXCEPTION);
128 1.1 fredette }
129 1.1 fredette status = &fpregs[0]; /* fp status register */
130 1.1 fredette r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(unsigned);
131 1.1 fredette if (r1 == 0) /* map fr0 source to constant zero */
132 1.1 fredette r1 = fpzeroreg;
133 1.1 fredette t = extru(ir,fptpos,5) * sizeof(double)/sizeof(unsigned);
134 1.1 fredette if (t == 0 && class != 2) /* don't allow fr0 as a dest */
135 1.1 fredette return(MAJOR_0C_EXCP);
136 1.1 fredette fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
137 1.1 fredette
138 1.1 fredette switch (class) {
139 1.1 fredette case 0:
140 1.1 fredette switch (subop) {
141 1.1 fredette case 0: /* COPR 0,0 emulated above*/
142 1.1 fredette case 1:
143 1.1 fredette case 6:
144 1.1 fredette case 7:
145 1.1 fredette return(MAJOR_0C_EXCP);
146 1.1 fredette case 2: /* FCPY */
147 1.1 fredette switch (fmt) {
148 1.1 fredette case 2: /* illegal */
149 1.1 fredette return(MAJOR_0C_EXCP);
150 1.1 fredette case 3: /* quad */
151 1.1 fredette fpregs[t+3] = fpregs[r1+3];
152 1.1 fredette fpregs[t+2] = fpregs[r1+2];
153 1.1 fredette case 1: /* double */
154 1.1 fredette fpregs[t+1] = fpregs[r1+1];
155 1.1 fredette case 0: /* single */
156 1.1 fredette fpregs[t] = fpregs[r1];
157 1.1 fredette return(NOEXCEPTION);
158 1.1 fredette }
159 1.1 fredette case 3: /* FABS */
160 1.1 fredette switch (fmt) {
161 1.1 fredette case 2: /* illegal */
162 1.1 fredette return(MAJOR_0C_EXCP);
163 1.1 fredette case 3: /* quad */
164 1.1 fredette fpregs[t+3] = fpregs[r1+3];
165 1.1 fredette fpregs[t+2] = fpregs[r1+2];
166 1.1 fredette case 1: /* double */
167 1.1 fredette fpregs[t+1] = fpregs[r1+1];
168 1.1 fredette case 0: /* single */
169 1.1 fredette /* copy and clear sign bit */
170 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff;
171 1.1 fredette return(NOEXCEPTION);
172 1.1 fredette }
173 1.1 fredette case 4: /* FSQRT */
174 1.1 fredette switch (fmt) {
175 1.1 fredette case 0:
176 1.1 fredette return(sgl_fsqrt(&fpregs[r1],
177 1.1 fredette &fpregs[t],status));
178 1.1 fredette case 1:
179 1.1 fredette return(dbl_fsqrt(&fpregs[r1],
180 1.1 fredette &fpregs[t],status));
181 1.1 fredette case 2:
182 1.1 fredette case 3: /* quad not implemented */
183 1.1 fredette return(MAJOR_0C_EXCP);
184 1.1 fredette }
185 1.1 fredette case 5: /* FRND */
186 1.1 fredette switch (fmt) {
187 1.1 fredette case 0:
188 1.1 fredette return(sgl_frnd(&fpregs[r1],
189 1.1 fredette &fpregs[t],status));
190 1.1 fredette case 1:
191 1.1 fredette return(dbl_frnd(&fpregs[r1],
192 1.1 fredette &fpregs[t],status));
193 1.1 fredette case 2:
194 1.1 fredette case 3: /* quad not implemented */
195 1.1 fredette return(MAJOR_0C_EXCP);
196 1.1 fredette }
197 1.1 fredette } /* end of switch (subop) */
198 1.1 fredette
199 1.1 fredette case 1: /* class 1 */
200 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */
201 1.1 fredette if ((df & 2) || (fmt & 2)) {
202 1.1 fredette /*
203 1.1 fredette * fmt's 2 and 3 are illegal of not implemented
204 1.1 fredette * quad conversions
205 1.1 fredette */
206 1.1 fredette return(MAJOR_0C_EXCP);
207 1.1 fredette }
208 1.1 fredette /*
209 1.1 fredette * encode source and dest formats into 2 bits.
210 1.1 fredette * high bit is source, low bit is dest.
211 1.1 fredette * bit = 1 --> double precision
212 1.1 fredette */
213 1.1 fredette fmt = (fmt << 1) | df;
214 1.1 fredette switch (subop) {
215 1.1 fredette case 0: /* FCNVFF */
216 1.1 fredette switch(fmt) {
217 1.1 fredette case 0: /* sgl/sgl */
218 1.1 fredette return(MAJOR_0C_EXCP);
219 1.1 fredette case 1: /* sgl/dbl */
220 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1],
221 1.1 fredette &fpregs[t],status));
222 1.1 fredette case 2: /* dbl/sgl */
223 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1],
224 1.1 fredette &fpregs[t],status));
225 1.1 fredette case 3: /* dbl/dbl */
226 1.1 fredette return(MAJOR_0C_EXCP);
227 1.1 fredette }
228 1.1 fredette case 1: /* FCNVXF */
229 1.1 fredette switch(fmt) {
230 1.1 fredette case 0: /* sgl/sgl */
231 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1],
232 1.1 fredette &fpregs[t],status));
233 1.1 fredette case 1: /* sgl/dbl */
234 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1],
235 1.1 fredette &fpregs[t],status));
236 1.1 fredette case 2: /* dbl/sgl */
237 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1],
238 1.1 fredette &fpregs[t],status));
239 1.1 fredette case 3: /* dbl/dbl */
240 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1],
241 1.1 fredette &fpregs[t],status));
242 1.1 fredette }
243 1.1 fredette case 2: /* FCNVFX */
244 1.1 fredette switch(fmt) {
245 1.1 fredette case 0: /* sgl/sgl */
246 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1],
247 1.1 fredette &fpregs[t],status));
248 1.1 fredette case 1: /* sgl/dbl */
249 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1],
250 1.1 fredette &fpregs[t],status));
251 1.1 fredette case 2: /* dbl/sgl */
252 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1],
253 1.1 fredette &fpregs[t],status));
254 1.1 fredette case 3: /* dbl/dbl */
255 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1],
256 1.1 fredette &fpregs[t],status));
257 1.1 fredette }
258 1.1 fredette case 3: /* FCNVFXT */
259 1.1 fredette switch(fmt) {
260 1.1 fredette case 0: /* sgl/sgl */
261 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
262 1.1 fredette &fpregs[t],status));
263 1.1 fredette case 1: /* sgl/dbl */
264 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
265 1.1 fredette &fpregs[t],status));
266 1.1 fredette case 2: /* dbl/sgl */
267 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
268 1.1 fredette &fpregs[t],status));
269 1.1 fredette case 3: /* dbl/dbl */
270 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
271 1.1 fredette &fpregs[t],status));
272 1.1 fredette }
273 1.1 fredette } /* end of switch subop */
274 1.1 fredette
275 1.1 fredette case 2: /* class 2 */
276 1.1 fredette r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(unsigned);
277 1.1 fredette if (r2 == 0)
278 1.1 fredette r2 = fpzeroreg;
279 1.1 fredette switch (subop) {
280 1.1 fredette case 2:
281 1.1 fredette case 3:
282 1.1 fredette case 4:
283 1.1 fredette case 5:
284 1.1 fredette case 6:
285 1.1 fredette case 7:
286 1.1 fredette return(MAJOR_0C_EXCP);
287 1.1 fredette case 0: /* FCMP */
288 1.1 fredette switch (fmt) {
289 1.1 fredette case 0:
290 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
291 1.1 fredette extru(ir,fptpos,5),status));
292 1.1 fredette case 1:
293 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
294 1.1 fredette extru(ir,fptpos,5),status));
295 1.1 fredette case 2: /* illegal */
296 1.1 fredette case 3: /* quad not implemented */
297 1.1 fredette return(MAJOR_0C_EXCP);
298 1.1 fredette }
299 1.1 fredette case 1: /* FTEST */
300 1.1 fredette switch (fmt) {
301 1.1 fredette case 0:
302 1.1 fredette /*
303 1.1 fredette * arg0 is not used
304 1.1 fredette * second param is the t field used for
305 1.1 fredette * ftest,acc and ftest,rej
306 1.1 fredette */
307 1.1 fredette /* XXX fredette - broken */
308 1.1 fredette #if 0
309 1.1 fredette return(ftest(0,extru(ir,fptpos,5),
310 1.1 fredette &fpregs[0]));
311 1.1 fredette #else
312 1.1 fredette panic("ftest");
313 1.1 fredette #endif
314 1.1 fredette case 1:
315 1.1 fredette case 2:
316 1.1 fredette case 3:
317 1.1 fredette return(MAJOR_0C_EXCP);
318 1.1 fredette }
319 1.1 fredette } /* end if switch for class 2*/
320 1.1 fredette case 3: /* class 3 */
321 1.1 fredette r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(unsigned);
322 1.1 fredette if (r2 == 0)
323 1.1 fredette r2 = fpzeroreg;
324 1.1 fredette switch (subop) {
325 1.1 fredette case 5:
326 1.1 fredette case 6:
327 1.1 fredette case 7:
328 1.1 fredette return(MAJOR_0C_EXCP);
329 1.1 fredette
330 1.1 fredette case 0: /* FADD */
331 1.1 fredette switch (fmt) {
332 1.1 fredette case 0:
333 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2],
334 1.1 fredette &fpregs[t],status));
335 1.1 fredette case 1:
336 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2],
337 1.1 fredette &fpregs[t],status));
338 1.1 fredette case 2: /* illegal */
339 1.1 fredette case 3: /* quad not implemented */
340 1.1 fredette return(MAJOR_0C_EXCP);
341 1.1 fredette }
342 1.1 fredette case 1: /* FSUB */
343 1.1 fredette switch (fmt) {
344 1.1 fredette case 0:
345 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2],
346 1.1 fredette &fpregs[t],status));
347 1.1 fredette case 1:
348 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2],
349 1.1 fredette &fpregs[t],status));
350 1.1 fredette case 2: /* illegal */
351 1.1 fredette case 3: /* quad not implemented */
352 1.1 fredette return(MAJOR_0C_EXCP);
353 1.1 fredette }
354 1.1 fredette case 2: /* FMPY */
355 1.1 fredette switch (fmt) {
356 1.1 fredette case 0:
357 1.1 fredette return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
358 1.1 fredette &fpregs[t],status));
359 1.1 fredette case 1:
360 1.1 fredette return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
361 1.1 fredette &fpregs[t],status));
362 1.1 fredette case 2: /* illegal */
363 1.1 fredette case 3: /* quad not implemented */
364 1.1 fredette return(MAJOR_0C_EXCP);
365 1.1 fredette }
366 1.1 fredette case 3: /* FDIV */
367 1.1 fredette switch (fmt) {
368 1.1 fredette case 0:
369 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
370 1.1 fredette &fpregs[t],status));
371 1.1 fredette case 1:
372 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
373 1.1 fredette &fpregs[t],status));
374 1.1 fredette case 2: /* illegal */
375 1.1 fredette case 3: /* quad not implemented */
376 1.1 fredette return(MAJOR_0C_EXCP);
377 1.1 fredette }
378 1.1 fredette case 4: /* FREM */
379 1.1 fredette switch (fmt) {
380 1.1 fredette case 0:
381 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2],
382 1.1 fredette &fpregs[t],status));
383 1.1 fredette case 1:
384 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2],
385 1.1 fredette &fpregs[t],status));
386 1.1 fredette case 2: /* illegal */
387 1.1 fredette case 3: /* quad not implemented */
388 1.1 fredette return(MAJOR_0C_EXCP);
389 1.1 fredette }
390 1.1 fredette } /* end of class 3 switch */
391 1.1 fredette } /* end of switch(class) */
392 1.1 fredette panic("decode_0c");
393 1.1 fredette }
394 1.1 fredette
395 1.1 fredette int
396 1.1 fredette decode_0e(ir,class,subop,fpregs)
397 1.1 fredette unsigned ir,class,subop;
398 1.1 fredette unsigned fpregs[];
399 1.1 fredette {
400 1.1 fredette unsigned r1,r2,t; /* operand register offsets */
401 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */
402 1.1 fredette unsigned df; /* dest format for class 1 conversions */
403 1.1 fredette unsigned *status;
404 1.1 fredette
405 1.1 fredette status = &fpregs[0];
406 1.1 fredette r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
407 1.1 fredette if (r1 == 0)
408 1.1 fredette r1 = fpzeroreg;
409 1.1 fredette t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
410 1.1 fredette if (t == 0 && class != 2)
411 1.1 fredette return(MAJOR_0E_EXCP);
412 1.1 fredette if (class < 2) /* class 0 or 1 has 2 bit fmt */
413 1.1 fredette fmt = extru(ir,fpfmtpos,2);
414 1.1 fredette else /* class 2 and 3 have 1 bit fmt */
415 1.1 fredette fmt = extru(ir,fp0efmtpos,1);
416 1.1 fredette
417 1.1 fredette switch (class) {
418 1.1 fredette case 0:
419 1.1 fredette switch (subop) {
420 1.1 fredette case 0: /* unimplemented */
421 1.1 fredette case 1:
422 1.1 fredette case 6:
423 1.1 fredette case 7:
424 1.1 fredette return(MAJOR_0E_EXCP);
425 1.1 fredette case 2: /* FCPY */
426 1.1 fredette switch (fmt) {
427 1.1 fredette case 2:
428 1.1 fredette case 3:
429 1.1 fredette return(MAJOR_0E_EXCP);
430 1.1 fredette case 1: /* double */
431 1.1 fredette fpregs[t+1] = fpregs[r1+1];
432 1.1 fredette case 0: /* single */
433 1.1 fredette fpregs[t] = fpregs[r1];
434 1.1 fredette return(NOEXCEPTION);
435 1.1 fredette }
436 1.1 fredette case 3: /* FABS */
437 1.1 fredette switch (fmt) {
438 1.1 fredette case 2:
439 1.1 fredette case 3:
440 1.1 fredette return(MAJOR_0E_EXCP);
441 1.1 fredette case 1: /* double */
442 1.1 fredette fpregs[t+1] = fpregs[r1+1];
443 1.1 fredette case 0: /* single */
444 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff;
445 1.1 fredette return(NOEXCEPTION);
446 1.1 fredette }
447 1.1 fredette case 4: /* FSQRT */
448 1.1 fredette switch (fmt) {
449 1.1 fredette case 0:
450 1.1 fredette return(sgl_fsqrt(&fpregs[r1],
451 1.1 fredette &fpregs[t], status));
452 1.1 fredette case 1:
453 1.1 fredette return(dbl_fsqrt(&fpregs[r1],
454 1.1 fredette &fpregs[t], status));
455 1.1 fredette case 2:
456 1.1 fredette case 3:
457 1.1 fredette return(MAJOR_0E_EXCP);
458 1.1 fredette }
459 1.1 fredette case 5: /* FRMD */
460 1.1 fredette switch (fmt) {
461 1.1 fredette case 0:
462 1.1 fredette return(sgl_frnd(&fpregs[r1],
463 1.1 fredette &fpregs[t], status));
464 1.1 fredette case 1:
465 1.1 fredette return(dbl_frnd(&fpregs[r1],
466 1.1 fredette &fpregs[t], status));
467 1.1 fredette case 2:
468 1.1 fredette case 3:
469 1.1 fredette return(MAJOR_0E_EXCP);
470 1.1 fredette }
471 1.1 fredette } /* end of switch (subop */
472 1.1 fredette
473 1.1 fredette case 1: /* class 1 */
474 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */
475 1.1 fredette if ((df & 2) || (fmt & 2))
476 1.1 fredette return(MAJOR_0E_EXCP);
477 1.1 fredette
478 1.1 fredette fmt = (fmt << 1) | df;
479 1.1 fredette switch (subop) {
480 1.1 fredette case 0: /* FCNVFF */
481 1.1 fredette switch(fmt) {
482 1.1 fredette case 0: /* sgl/sgl */
483 1.1 fredette return(MAJOR_0E_EXCP);
484 1.1 fredette case 1: /* sgl/dbl */
485 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1],
486 1.1 fredette &fpregs[t],status));
487 1.1 fredette case 2: /* dbl/sgl */
488 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1],
489 1.1 fredette &fpregs[t],status));
490 1.1 fredette case 3: /* dbl/dbl */
491 1.1 fredette return(MAJOR_0E_EXCP);
492 1.1 fredette }
493 1.1 fredette case 1: /* FCNVXF */
494 1.1 fredette switch(fmt) {
495 1.1 fredette case 0: /* sgl/sgl */
496 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1],
497 1.1 fredette &fpregs[t],status));
498 1.1 fredette case 1: /* sgl/dbl */
499 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1],
500 1.1 fredette &fpregs[t],status));
501 1.1 fredette case 2: /* dbl/sgl */
502 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1],
503 1.1 fredette &fpregs[t],status));
504 1.1 fredette case 3: /* dbl/dbl */
505 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1],
506 1.1 fredette &fpregs[t],status));
507 1.1 fredette }
508 1.1 fredette case 2: /* FCNVFX */
509 1.1 fredette switch(fmt) {
510 1.1 fredette case 0: /* sgl/sgl */
511 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1],
512 1.1 fredette &fpregs[t],status));
513 1.1 fredette case 1: /* sgl/dbl */
514 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1],
515 1.1 fredette &fpregs[t],status));
516 1.1 fredette case 2: /* dbl/sgl */
517 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1],
518 1.1 fredette &fpregs[t],status));
519 1.1 fredette case 3: /* dbl/dbl */
520 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1],
521 1.1 fredette &fpregs[t],status));
522 1.1 fredette }
523 1.1 fredette case 3: /* FCNVFXT */
524 1.1 fredette switch(fmt) {
525 1.1 fredette case 0: /* sgl/sgl */
526 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
527 1.1 fredette &fpregs[t],status));
528 1.1 fredette case 1: /* sgl/dbl */
529 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
530 1.1 fredette &fpregs[t],status));
531 1.1 fredette case 2: /* dbl/sgl */
532 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
533 1.1 fredette &fpregs[t],status));
534 1.1 fredette case 3: /* dbl/dbl */
535 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
536 1.1 fredette &fpregs[t],status));
537 1.1 fredette }
538 1.1 fredette } /* end of switch subop */
539 1.1 fredette case 2: /* class 2 */
540 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
541 1.1 fredette if (r2 == 0)
542 1.1 fredette r2 = fpzeroreg;
543 1.1 fredette switch (subop) {
544 1.1 fredette case 1:
545 1.1 fredette case 2:
546 1.1 fredette case 3:
547 1.1 fredette case 4:
548 1.1 fredette case 5:
549 1.1 fredette case 6:
550 1.1 fredette case 7:
551 1.1 fredette return(MAJOR_0E_EXCP);
552 1.1 fredette case 0: /* FCMP */
553 1.1 fredette switch (fmt) {
554 1.1 fredette /*
555 1.1 fredette * fmt is only 1 bit long
556 1.1 fredette */
557 1.1 fredette case 0:
558 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
559 1.1 fredette extru(ir,fptpos,5),status));
560 1.1 fredette case 1:
561 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
562 1.1 fredette extru(ir,fptpos,5),status));
563 1.1 fredette }
564 1.1 fredette } /* end of switch for class 2 */
565 1.1 fredette case 3: /* class 3 */
566 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
567 1.1 fredette if (r2 == 0)
568 1.1 fredette r2 = fpzeroreg;
569 1.1 fredette switch (subop) {
570 1.1 fredette case 5:
571 1.1 fredette case 6:
572 1.1 fredette case 7:
573 1.1 fredette return(MAJOR_0E_EXCP);
574 1.1 fredette
575 1.1 fredette /*
576 1.1 fredette * Note that fmt is only 1 bit for class 3 */
577 1.1 fredette case 0: /* FADD */
578 1.1 fredette switch (fmt) {
579 1.1 fredette case 0:
580 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2],
581 1.1 fredette &fpregs[t],status));
582 1.1 fredette case 1:
583 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2],
584 1.1 fredette &fpregs[t],status));
585 1.1 fredette }
586 1.1 fredette case 1: /* FSUB */
587 1.1 fredette switch (fmt) {
588 1.1 fredette case 0:
589 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2],
590 1.1 fredette &fpregs[t],status));
591 1.1 fredette case 1:
592 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2],
593 1.1 fredette &fpregs[t],status));
594 1.1 fredette }
595 1.1 fredette case 2: /* FMPY or XMPYU */
596 1.1 fredette /*
597 1.1 fredette * check for integer multiply (x bit set)
598 1.1 fredette */
599 1.1 fredette if (extru(ir,fpxpos,1)) {
600 1.1 fredette /*
601 1.1 fredette * emulate XMPYU
602 1.1 fredette */
603 1.1 fredette switch (fmt) {
604 1.1 fredette case 0:
605 1.1 fredette /*
606 1.1 fredette * bad instruction if t specifies
607 1.1 fredette * the right half of a register
608 1.1 fredette */
609 1.1 fredette if (t & 1)
610 1.1 fredette return(MAJOR_0E_EXCP);
611 1.1 fredette /* XXX fredette - broken. */
612 1.1 fredette #if 0
613 1.1 fredette impyu(&fpregs[r1],&fpregs[r2],
614 1.1 fredette &fpregs[t]);
615 1.1 fredette return(NOEXCEPTION);
616 1.1 fredette #else
617 1.1 fredette panic("impyu");
618 1.1 fredette #endif
619 1.1 fredette case 1:
620 1.1 fredette return(MAJOR_0E_EXCP);
621 1.1 fredette }
622 1.1 fredette }
623 1.1 fredette else { /* FMPY */
624 1.1 fredette switch (fmt) {
625 1.1 fredette case 0:
626 1.1 fredette return(sgl_fmpy(&fpregs[r1],
627 1.1 fredette &fpregs[r2],&fpregs[t],status));
628 1.1 fredette case 1:
629 1.1 fredette return(dbl_fmpy(&fpregs[r1],
630 1.1 fredette &fpregs[r2],&fpregs[t],status));
631 1.1 fredette }
632 1.1 fredette }
633 1.1 fredette case 3: /* FDIV */
634 1.1 fredette switch (fmt) {
635 1.1 fredette case 0:
636 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
637 1.1 fredette &fpregs[t],status));
638 1.1 fredette case 1:
639 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
640 1.1 fredette &fpregs[t],status));
641 1.1 fredette }
642 1.1 fredette case 4: /* FREM */
643 1.1 fredette switch (fmt) {
644 1.1 fredette case 0:
645 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2],
646 1.1 fredette &fpregs[t],status));
647 1.1 fredette case 1:
648 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2],
649 1.1 fredette &fpregs[t],status));
650 1.1 fredette }
651 1.1 fredette } /* end of class 3 switch */
652 1.1 fredette } /* end of switch(class) */
653 1.1 fredette panic("decode_0e");
654 1.1 fredette }
655 1.1 fredette
656 1.1 fredette
657 1.1 fredette /*
658 1.1 fredette * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
659 1.1 fredette */
660 1.1 fredette int
661 1.1 fredette decode_06(ir,fpregs)
662 1.1 fredette unsigned ir;
663 1.1 fredette unsigned fpregs[];
664 1.1 fredette {
665 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */
666 1.1 fredette unsigned fmt;
667 1.1 fredette unsigned error = 0;
668 1.1 fredette unsigned status;
669 1.1 fredette union {
670 1.1 fredette double dbl;
671 1.1 fredette float flt;
672 1.1 fredette struct { unsigned i1; unsigned i2; } ints;
673 1.1 fredette } mtmp, atmp;
674 1.1 fredette
675 1.1 fredette
676 1.1 fredette status = fpregs[0]; /* use a local copy of status reg */
677 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
678 1.1 fredette if (fmt == 0) { /* DBL */
679 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
680 1.1 fredette if (rm1 == 0)
681 1.1 fredette rm1 = fpzeroreg;
682 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
683 1.1 fredette if (rm2 == 0)
684 1.1 fredette rm2 = fpzeroreg;
685 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
686 1.1 fredette if (tm == 0)
687 1.1 fredette return(MAJOR_06_EXCP);
688 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
689 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
690 1.1 fredette if (ta == 0)
691 1.1 fredette return(MAJOR_06_EXCP);
692 1.1 fredette
693 1.1 fredette #ifdef TIMEX
694 1.1 fredette if (ra == 0) {
695 1.1 fredette /* special case FMPYCFXT */
696 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
697 1.1 fredette &status))
698 1.1 fredette error = 1;
699 1.1 fredette if (dbl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
700 1.1 fredette (unsigned *) &atmp,&status))
701 1.1 fredette error = 1;
702 1.1 fredette }
703 1.1 fredette else {
704 1.1 fredette #else
705 1.1 fredette if (ra == 0)
706 1.1 fredette ra = fpzeroreg;
707 1.1 fredette #endif
708 1.1 fredette
709 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
710 1.1 fredette &status))
711 1.1 fredette error = 1;
712 1.1 fredette if (dbl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
713 1.1 fredette &status))
714 1.1 fredette error = 1;
715 1.1 fredette #ifdef TIMEX
716 1.1 fredette }
717 1.1 fredette #endif
718 1.1 fredette if (error)
719 1.1 fredette return(MAJOR_06_EXCP);
720 1.1 fredette else {
721 1.1 fredette /* copy results */
722 1.1 fredette fpregs[tm] = mtmp.ints.i1;
723 1.1 fredette fpregs[tm+1] = mtmp.ints.i2;
724 1.1 fredette fpregs[ta] = atmp.ints.i1;
725 1.1 fredette fpregs[ta+1] = atmp.ints.i2;
726 1.1 fredette fpregs[0] = status;
727 1.1 fredette return(NOEXCEPTION);
728 1.1 fredette }
729 1.1 fredette }
730 1.1 fredette else { /* SGL */
731 1.1 fredette /*
732 1.1 fredette * calculate offsets for single precision numbers
733 1.1 fredette * See table 6-14 in PA-89 architecture for mapping
734 1.1 fredette */
735 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
736 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
737 1.1 fredette
738 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
739 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
740 1.1 fredette
741 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
742 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */
743 1.1 fredette
744 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
745 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */
746 1.1 fredette
747 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
748 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */
749 1.1 fredette
750 1.1 fredette if (ra == 0x20) { /* special case FMPYCFXT (really 0) */
751 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
752 1.1 fredette &status))
753 1.1 fredette error = 1;
754 1.1 fredette /* XXX fredette - this is broken */
755 1.1 fredette #if 0
756 1.1 fredette if (sgl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
757 1.1 fredette (unsigned *) &atmp,&status))
758 1.1 fredette error = 1;
759 1.1 fredette #else
760 1.1 fredette panic("FMPYADD");
761 1.1 fredette #endif
762 1.1 fredette }
763 1.1 fredette else {
764 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
765 1.1 fredette &status))
766 1.1 fredette error = 1;
767 1.1 fredette if (sgl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
768 1.1 fredette &status))
769 1.1 fredette error = 1;
770 1.1 fredette }
771 1.1 fredette if (error)
772 1.1 fredette return(MAJOR_06_EXCP);
773 1.1 fredette else {
774 1.1 fredette /* copy results */
775 1.1 fredette fpregs[tm] = mtmp.ints.i1;
776 1.1 fredette fpregs[ta] = atmp.ints.i1;
777 1.1 fredette fpregs[0] = status;
778 1.1 fredette return(NOEXCEPTION);
779 1.1 fredette }
780 1.1 fredette }
781 1.1 fredette }
782 1.1 fredette
783 1.1 fredette /*
784 1.1 fredette * routine to decode the 26 (FMPYSUB) instruction
785 1.1 fredette */
786 1.1 fredette int
787 1.1 fredette decode_26(ir,fpregs)
788 1.1 fredette unsigned ir;
789 1.1 fredette unsigned fpregs[];
790 1.1 fredette {
791 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */
792 1.1 fredette unsigned fmt;
793 1.1 fredette unsigned error = 0;
794 1.1 fredette unsigned status;
795 1.1 fredette union {
796 1.1 fredette double dbl;
797 1.1 fredette float flt;
798 1.1 fredette struct { unsigned i1; unsigned i2; } ints;
799 1.1 fredette } mtmp, atmp;
800 1.1 fredette
801 1.1 fredette
802 1.1 fredette status = fpregs[0];
803 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
804 1.1 fredette if (fmt == 0) { /* DBL */
805 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
806 1.1 fredette if (rm1 == 0)
807 1.1 fredette rm1 = fpzeroreg;
808 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
809 1.1 fredette if (rm2 == 0)
810 1.1 fredette rm2 = fpzeroreg;
811 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
812 1.1 fredette if (tm == 0)
813 1.1 fredette return(MAJOR_26_EXCP);
814 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
815 1.1 fredette if (ra == 0)
816 1.1 fredette return(MAJOR_26_EXCP);
817 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
818 1.1 fredette if (ta == 0)
819 1.1 fredette return(MAJOR_26_EXCP);
820 1.1 fredette
821 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
822 1.1 fredette &status))
823 1.1 fredette error = 1;
824 1.1 fredette if (dbl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
825 1.1 fredette &status))
826 1.1 fredette error = 1;
827 1.1 fredette if (error)
828 1.1 fredette return(MAJOR_26_EXCP);
829 1.1 fredette else {
830 1.1 fredette /* copy results */
831 1.1 fredette fpregs[tm] = mtmp.ints.i1;
832 1.1 fredette fpregs[tm+1] = mtmp.ints.i2;
833 1.1 fredette fpregs[ta] = atmp.ints.i1;
834 1.1 fredette fpregs[ta+1] = atmp.ints.i2;
835 1.1 fredette fpregs[0] = status;
836 1.1 fredette return(NOEXCEPTION);
837 1.1 fredette }
838 1.1 fredette }
839 1.1 fredette else { /* SGL */
840 1.1 fredette /*
841 1.1 fredette * calculate offsets for single precision numbers
842 1.1 fredette * See table 6-14 in PA-89 architecture for mapping
843 1.1 fredette */
844 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
845 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
846 1.1 fredette
847 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
848 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
849 1.1 fredette
850 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
851 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */
852 1.1 fredette
853 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
854 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */
855 1.1 fredette
856 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
857 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */
858 1.1 fredette
859 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
860 1.1 fredette &status))
861 1.1 fredette error = 1;
862 1.1 fredette if (sgl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
863 1.1 fredette &status))
864 1.1 fredette error = 1;
865 1.1 fredette if (error)
866 1.1 fredette return(MAJOR_26_EXCP);
867 1.1 fredette else {
868 1.1 fredette /* copy results */
869 1.1 fredette fpregs[tm] = mtmp.ints.i1;
870 1.1 fredette fpregs[ta] = atmp.ints.i1;
871 1.1 fredette fpregs[0] = status;
872 1.1 fredette return(NOEXCEPTION);
873 1.1 fredette }
874 1.1 fredette }
875 1.1 fredette
876 1.1 fredette }
877