fpudispatch.c revision 1.4 1 1.4 dsl /* $NetBSD: fpudispatch.c,v 1.4 2009/03/14 21:04:10 dsl 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.4 dsl __KERNEL_RCSID(0, "$NetBSD: fpudispatch.c,v 1.4 2009/03/14 21:04:10 dsl 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.4 dsl decode_0c(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])
117 1.1 fredette {
118 1.1 fredette unsigned r1,r2,t; /* operand register offsets */
119 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */
120 1.1 fredette unsigned df; /* for class 1 conversions */
121 1.1 fredette unsigned *status;
122 1.1 fredette
123 1.1 fredette if (ir == COPR_INST) {
124 1.1 fredette fpregs[0] = EMULATION_VERSION << 11;
125 1.1 fredette return(NOEXCEPTION);
126 1.1 fredette }
127 1.1 fredette status = &fpregs[0]; /* fp status register */
128 1.1 fredette r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(unsigned);
129 1.1 fredette if (r1 == 0) /* map fr0 source to constant zero */
130 1.1 fredette r1 = fpzeroreg;
131 1.1 fredette t = extru(ir,fptpos,5) * sizeof(double)/sizeof(unsigned);
132 1.1 fredette if (t == 0 && class != 2) /* don't allow fr0 as a dest */
133 1.1 fredette return(MAJOR_0C_EXCP);
134 1.1 fredette fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
135 1.1 fredette
136 1.1 fredette switch (class) {
137 1.1 fredette case 0:
138 1.1 fredette switch (subop) {
139 1.1 fredette case 0: /* COPR 0,0 emulated above*/
140 1.1 fredette case 1:
141 1.1 fredette case 6:
142 1.1 fredette case 7:
143 1.1 fredette return(MAJOR_0C_EXCP);
144 1.1 fredette case 2: /* FCPY */
145 1.1 fredette switch (fmt) {
146 1.1 fredette case 2: /* illegal */
147 1.1 fredette return(MAJOR_0C_EXCP);
148 1.1 fredette case 3: /* quad */
149 1.1 fredette fpregs[t+3] = fpregs[r1+3];
150 1.1 fredette fpregs[t+2] = fpregs[r1+2];
151 1.1 fredette case 1: /* double */
152 1.1 fredette fpregs[t+1] = fpregs[r1+1];
153 1.1 fredette case 0: /* single */
154 1.1 fredette fpregs[t] = fpregs[r1];
155 1.1 fredette return(NOEXCEPTION);
156 1.1 fredette }
157 1.1 fredette case 3: /* FABS */
158 1.1 fredette switch (fmt) {
159 1.1 fredette case 2: /* illegal */
160 1.1 fredette return(MAJOR_0C_EXCP);
161 1.1 fredette case 3: /* quad */
162 1.1 fredette fpregs[t+3] = fpregs[r1+3];
163 1.1 fredette fpregs[t+2] = fpregs[r1+2];
164 1.1 fredette case 1: /* double */
165 1.1 fredette fpregs[t+1] = fpregs[r1+1];
166 1.1 fredette case 0: /* single */
167 1.1 fredette /* copy and clear sign bit */
168 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff;
169 1.1 fredette return(NOEXCEPTION);
170 1.1 fredette }
171 1.1 fredette case 4: /* FSQRT */
172 1.1 fredette switch (fmt) {
173 1.1 fredette case 0:
174 1.1 fredette return(sgl_fsqrt(&fpregs[r1],
175 1.1 fredette &fpregs[t],status));
176 1.1 fredette case 1:
177 1.1 fredette return(dbl_fsqrt(&fpregs[r1],
178 1.1 fredette &fpregs[t],status));
179 1.1 fredette case 2:
180 1.1 fredette case 3: /* quad not implemented */
181 1.1 fredette return(MAJOR_0C_EXCP);
182 1.1 fredette }
183 1.1 fredette case 5: /* FRND */
184 1.1 fredette switch (fmt) {
185 1.1 fredette case 0:
186 1.1 fredette return(sgl_frnd(&fpregs[r1],
187 1.1 fredette &fpregs[t],status));
188 1.1 fredette case 1:
189 1.1 fredette return(dbl_frnd(&fpregs[r1],
190 1.1 fredette &fpregs[t],status));
191 1.1 fredette case 2:
192 1.1 fredette case 3: /* quad not implemented */
193 1.1 fredette return(MAJOR_0C_EXCP);
194 1.1 fredette }
195 1.1 fredette } /* end of switch (subop) */
196 1.1 fredette
197 1.1 fredette case 1: /* class 1 */
198 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */
199 1.1 fredette if ((df & 2) || (fmt & 2)) {
200 1.1 fredette /*
201 1.1 fredette * fmt's 2 and 3 are illegal of not implemented
202 1.1 fredette * quad conversions
203 1.1 fredette */
204 1.1 fredette return(MAJOR_0C_EXCP);
205 1.1 fredette }
206 1.1 fredette /*
207 1.1 fredette * encode source and dest formats into 2 bits.
208 1.1 fredette * high bit is source, low bit is dest.
209 1.1 fredette * bit = 1 --> double precision
210 1.1 fredette */
211 1.1 fredette fmt = (fmt << 1) | df;
212 1.1 fredette switch (subop) {
213 1.1 fredette case 0: /* FCNVFF */
214 1.1 fredette switch(fmt) {
215 1.1 fredette case 0: /* sgl/sgl */
216 1.1 fredette return(MAJOR_0C_EXCP);
217 1.1 fredette case 1: /* sgl/dbl */
218 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1],
219 1.1 fredette &fpregs[t],status));
220 1.1 fredette case 2: /* dbl/sgl */
221 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1],
222 1.1 fredette &fpregs[t],status));
223 1.1 fredette case 3: /* dbl/dbl */
224 1.1 fredette return(MAJOR_0C_EXCP);
225 1.1 fredette }
226 1.1 fredette case 1: /* FCNVXF */
227 1.1 fredette switch(fmt) {
228 1.1 fredette case 0: /* sgl/sgl */
229 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1],
230 1.1 fredette &fpregs[t],status));
231 1.1 fredette case 1: /* sgl/dbl */
232 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1],
233 1.1 fredette &fpregs[t],status));
234 1.1 fredette case 2: /* dbl/sgl */
235 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1],
236 1.1 fredette &fpregs[t],status));
237 1.1 fredette case 3: /* dbl/dbl */
238 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1],
239 1.1 fredette &fpregs[t],status));
240 1.1 fredette }
241 1.1 fredette case 2: /* FCNVFX */
242 1.1 fredette switch(fmt) {
243 1.1 fredette case 0: /* sgl/sgl */
244 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1],
245 1.1 fredette &fpregs[t],status));
246 1.1 fredette case 1: /* sgl/dbl */
247 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1],
248 1.1 fredette &fpregs[t],status));
249 1.1 fredette case 2: /* dbl/sgl */
250 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1],
251 1.1 fredette &fpregs[t],status));
252 1.1 fredette case 3: /* dbl/dbl */
253 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1],
254 1.1 fredette &fpregs[t],status));
255 1.1 fredette }
256 1.1 fredette case 3: /* FCNVFXT */
257 1.1 fredette switch(fmt) {
258 1.1 fredette case 0: /* sgl/sgl */
259 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
260 1.1 fredette &fpregs[t],status));
261 1.1 fredette case 1: /* sgl/dbl */
262 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
263 1.1 fredette &fpregs[t],status));
264 1.1 fredette case 2: /* dbl/sgl */
265 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
266 1.1 fredette &fpregs[t],status));
267 1.1 fredette case 3: /* dbl/dbl */
268 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
269 1.1 fredette &fpregs[t],status));
270 1.1 fredette }
271 1.1 fredette } /* end of switch subop */
272 1.1 fredette
273 1.1 fredette case 2: /* class 2 */
274 1.1 fredette r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(unsigned);
275 1.1 fredette if (r2 == 0)
276 1.1 fredette r2 = fpzeroreg;
277 1.1 fredette switch (subop) {
278 1.1 fredette case 2:
279 1.1 fredette case 3:
280 1.1 fredette case 4:
281 1.1 fredette case 5:
282 1.1 fredette case 6:
283 1.1 fredette case 7:
284 1.1 fredette return(MAJOR_0C_EXCP);
285 1.1 fredette case 0: /* FCMP */
286 1.1 fredette switch (fmt) {
287 1.1 fredette case 0:
288 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
289 1.1 fredette extru(ir,fptpos,5),status));
290 1.1 fredette case 1:
291 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
292 1.1 fredette extru(ir,fptpos,5),status));
293 1.1 fredette case 2: /* illegal */
294 1.1 fredette case 3: /* quad not implemented */
295 1.1 fredette return(MAJOR_0C_EXCP);
296 1.1 fredette }
297 1.1 fredette case 1: /* FTEST */
298 1.1 fredette switch (fmt) {
299 1.1 fredette case 0:
300 1.1 fredette /*
301 1.1 fredette * arg0 is not used
302 1.1 fredette * second param is the t field used for
303 1.1 fredette * ftest,acc and ftest,rej
304 1.1 fredette */
305 1.1 fredette /* XXX fredette - broken */
306 1.1 fredette #if 0
307 1.1 fredette return(ftest(0,extru(ir,fptpos,5),
308 1.1 fredette &fpregs[0]));
309 1.1 fredette #else
310 1.1 fredette panic("ftest");
311 1.1 fredette #endif
312 1.1 fredette case 1:
313 1.1 fredette case 2:
314 1.1 fredette case 3:
315 1.1 fredette return(MAJOR_0C_EXCP);
316 1.1 fredette }
317 1.1 fredette } /* end if switch for class 2*/
318 1.1 fredette case 3: /* class 3 */
319 1.1 fredette r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(unsigned);
320 1.1 fredette if (r2 == 0)
321 1.1 fredette r2 = fpzeroreg;
322 1.1 fredette switch (subop) {
323 1.1 fredette case 5:
324 1.1 fredette case 6:
325 1.1 fredette case 7:
326 1.1 fredette return(MAJOR_0C_EXCP);
327 1.1 fredette
328 1.1 fredette case 0: /* FADD */
329 1.1 fredette switch (fmt) {
330 1.1 fredette case 0:
331 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2],
332 1.1 fredette &fpregs[t],status));
333 1.1 fredette case 1:
334 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2],
335 1.1 fredette &fpregs[t],status));
336 1.1 fredette case 2: /* illegal */
337 1.1 fredette case 3: /* quad not implemented */
338 1.1 fredette return(MAJOR_0C_EXCP);
339 1.1 fredette }
340 1.1 fredette case 1: /* FSUB */
341 1.1 fredette switch (fmt) {
342 1.1 fredette case 0:
343 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2],
344 1.1 fredette &fpregs[t],status));
345 1.1 fredette case 1:
346 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2],
347 1.1 fredette &fpregs[t],status));
348 1.1 fredette case 2: /* illegal */
349 1.1 fredette case 3: /* quad not implemented */
350 1.1 fredette return(MAJOR_0C_EXCP);
351 1.1 fredette }
352 1.1 fredette case 2: /* FMPY */
353 1.1 fredette switch (fmt) {
354 1.1 fredette case 0:
355 1.1 fredette return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
356 1.1 fredette &fpregs[t],status));
357 1.1 fredette case 1:
358 1.1 fredette return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
359 1.1 fredette &fpregs[t],status));
360 1.1 fredette case 2: /* illegal */
361 1.1 fredette case 3: /* quad not implemented */
362 1.1 fredette return(MAJOR_0C_EXCP);
363 1.1 fredette }
364 1.1 fredette case 3: /* FDIV */
365 1.1 fredette switch (fmt) {
366 1.1 fredette case 0:
367 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
368 1.1 fredette &fpregs[t],status));
369 1.1 fredette case 1:
370 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
371 1.1 fredette &fpregs[t],status));
372 1.1 fredette case 2: /* illegal */
373 1.1 fredette case 3: /* quad not implemented */
374 1.1 fredette return(MAJOR_0C_EXCP);
375 1.1 fredette }
376 1.1 fredette case 4: /* FREM */
377 1.1 fredette switch (fmt) {
378 1.1 fredette case 0:
379 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2],
380 1.1 fredette &fpregs[t],status));
381 1.1 fredette case 1:
382 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2],
383 1.1 fredette &fpregs[t],status));
384 1.1 fredette case 2: /* illegal */
385 1.1 fredette case 3: /* quad not implemented */
386 1.1 fredette return(MAJOR_0C_EXCP);
387 1.1 fredette }
388 1.1 fredette } /* end of class 3 switch */
389 1.1 fredette } /* end of switch(class) */
390 1.1 fredette panic("decode_0c");
391 1.1 fredette }
392 1.1 fredette
393 1.1 fredette int
394 1.4 dsl decode_0e(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])
395 1.1 fredette {
396 1.1 fredette unsigned r1,r2,t; /* operand register offsets */
397 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */
398 1.1 fredette unsigned df; /* dest format for class 1 conversions */
399 1.1 fredette unsigned *status;
400 1.1 fredette
401 1.1 fredette status = &fpregs[0];
402 1.1 fredette r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
403 1.1 fredette if (r1 == 0)
404 1.1 fredette r1 = fpzeroreg;
405 1.1 fredette t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
406 1.1 fredette if (t == 0 && class != 2)
407 1.1 fredette return(MAJOR_0E_EXCP);
408 1.1 fredette if (class < 2) /* class 0 or 1 has 2 bit fmt */
409 1.1 fredette fmt = extru(ir,fpfmtpos,2);
410 1.1 fredette else /* class 2 and 3 have 1 bit fmt */
411 1.1 fredette fmt = extru(ir,fp0efmtpos,1);
412 1.1 fredette
413 1.1 fredette switch (class) {
414 1.1 fredette case 0:
415 1.1 fredette switch (subop) {
416 1.1 fredette case 0: /* unimplemented */
417 1.1 fredette case 1:
418 1.1 fredette case 6:
419 1.1 fredette case 7:
420 1.1 fredette return(MAJOR_0E_EXCP);
421 1.1 fredette case 2: /* FCPY */
422 1.1 fredette switch (fmt) {
423 1.1 fredette case 2:
424 1.1 fredette case 3:
425 1.1 fredette return(MAJOR_0E_EXCP);
426 1.1 fredette case 1: /* double */
427 1.1 fredette fpregs[t+1] = fpregs[r1+1];
428 1.1 fredette case 0: /* single */
429 1.1 fredette fpregs[t] = fpregs[r1];
430 1.1 fredette return(NOEXCEPTION);
431 1.1 fredette }
432 1.1 fredette case 3: /* FABS */
433 1.1 fredette switch (fmt) {
434 1.1 fredette case 2:
435 1.1 fredette case 3:
436 1.1 fredette return(MAJOR_0E_EXCP);
437 1.1 fredette case 1: /* double */
438 1.1 fredette fpregs[t+1] = fpregs[r1+1];
439 1.1 fredette case 0: /* single */
440 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff;
441 1.1 fredette return(NOEXCEPTION);
442 1.1 fredette }
443 1.1 fredette case 4: /* FSQRT */
444 1.1 fredette switch (fmt) {
445 1.1 fredette case 0:
446 1.1 fredette return(sgl_fsqrt(&fpregs[r1],
447 1.1 fredette &fpregs[t], status));
448 1.1 fredette case 1:
449 1.1 fredette return(dbl_fsqrt(&fpregs[r1],
450 1.1 fredette &fpregs[t], status));
451 1.1 fredette case 2:
452 1.1 fredette case 3:
453 1.1 fredette return(MAJOR_0E_EXCP);
454 1.1 fredette }
455 1.1 fredette case 5: /* FRMD */
456 1.1 fredette switch (fmt) {
457 1.1 fredette case 0:
458 1.1 fredette return(sgl_frnd(&fpregs[r1],
459 1.1 fredette &fpregs[t], status));
460 1.1 fredette case 1:
461 1.1 fredette return(dbl_frnd(&fpregs[r1],
462 1.1 fredette &fpregs[t], status));
463 1.1 fredette case 2:
464 1.1 fredette case 3:
465 1.1 fredette return(MAJOR_0E_EXCP);
466 1.1 fredette }
467 1.1 fredette } /* end of switch (subop */
468 1.1 fredette
469 1.1 fredette case 1: /* class 1 */
470 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */
471 1.1 fredette if ((df & 2) || (fmt & 2))
472 1.1 fredette return(MAJOR_0E_EXCP);
473 1.1 fredette
474 1.1 fredette fmt = (fmt << 1) | df;
475 1.1 fredette switch (subop) {
476 1.1 fredette case 0: /* FCNVFF */
477 1.1 fredette switch(fmt) {
478 1.1 fredette case 0: /* sgl/sgl */
479 1.1 fredette return(MAJOR_0E_EXCP);
480 1.1 fredette case 1: /* sgl/dbl */
481 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1],
482 1.1 fredette &fpregs[t],status));
483 1.1 fredette case 2: /* dbl/sgl */
484 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1],
485 1.1 fredette &fpregs[t],status));
486 1.1 fredette case 3: /* dbl/dbl */
487 1.1 fredette return(MAJOR_0E_EXCP);
488 1.1 fredette }
489 1.1 fredette case 1: /* FCNVXF */
490 1.1 fredette switch(fmt) {
491 1.1 fredette case 0: /* sgl/sgl */
492 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1],
493 1.1 fredette &fpregs[t],status));
494 1.1 fredette case 1: /* sgl/dbl */
495 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1],
496 1.1 fredette &fpregs[t],status));
497 1.1 fredette case 2: /* dbl/sgl */
498 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1],
499 1.1 fredette &fpregs[t],status));
500 1.1 fredette case 3: /* dbl/dbl */
501 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1],
502 1.1 fredette &fpregs[t],status));
503 1.1 fredette }
504 1.1 fredette case 2: /* FCNVFX */
505 1.1 fredette switch(fmt) {
506 1.1 fredette case 0: /* sgl/sgl */
507 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1],
508 1.1 fredette &fpregs[t],status));
509 1.1 fredette case 1: /* sgl/dbl */
510 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1],
511 1.1 fredette &fpregs[t],status));
512 1.1 fredette case 2: /* dbl/sgl */
513 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1],
514 1.1 fredette &fpregs[t],status));
515 1.1 fredette case 3: /* dbl/dbl */
516 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1],
517 1.1 fredette &fpregs[t],status));
518 1.1 fredette }
519 1.1 fredette case 3: /* FCNVFXT */
520 1.1 fredette switch(fmt) {
521 1.1 fredette case 0: /* sgl/sgl */
522 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
523 1.1 fredette &fpregs[t],status));
524 1.1 fredette case 1: /* sgl/dbl */
525 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
526 1.1 fredette &fpregs[t],status));
527 1.1 fredette case 2: /* dbl/sgl */
528 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
529 1.1 fredette &fpregs[t],status));
530 1.1 fredette case 3: /* dbl/dbl */
531 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
532 1.1 fredette &fpregs[t],status));
533 1.1 fredette }
534 1.1 fredette } /* end of switch subop */
535 1.1 fredette case 2: /* class 2 */
536 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
537 1.1 fredette if (r2 == 0)
538 1.1 fredette r2 = fpzeroreg;
539 1.1 fredette switch (subop) {
540 1.1 fredette case 1:
541 1.1 fredette case 2:
542 1.1 fredette case 3:
543 1.1 fredette case 4:
544 1.1 fredette case 5:
545 1.1 fredette case 6:
546 1.1 fredette case 7:
547 1.1 fredette return(MAJOR_0E_EXCP);
548 1.1 fredette case 0: /* FCMP */
549 1.1 fredette switch (fmt) {
550 1.1 fredette /*
551 1.1 fredette * fmt is only 1 bit long
552 1.1 fredette */
553 1.1 fredette case 0:
554 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
555 1.1 fredette extru(ir,fptpos,5),status));
556 1.1 fredette case 1:
557 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
558 1.1 fredette extru(ir,fptpos,5),status));
559 1.1 fredette }
560 1.1 fredette } /* end of switch for class 2 */
561 1.1 fredette case 3: /* class 3 */
562 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
563 1.1 fredette if (r2 == 0)
564 1.1 fredette r2 = fpzeroreg;
565 1.1 fredette switch (subop) {
566 1.1 fredette case 5:
567 1.1 fredette case 6:
568 1.1 fredette case 7:
569 1.1 fredette return(MAJOR_0E_EXCP);
570 1.1 fredette
571 1.1 fredette /*
572 1.1 fredette * Note that fmt is only 1 bit for class 3 */
573 1.1 fredette case 0: /* FADD */
574 1.1 fredette switch (fmt) {
575 1.1 fredette case 0:
576 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2],
577 1.1 fredette &fpregs[t],status));
578 1.1 fredette case 1:
579 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2],
580 1.1 fredette &fpregs[t],status));
581 1.1 fredette }
582 1.1 fredette case 1: /* FSUB */
583 1.1 fredette switch (fmt) {
584 1.1 fredette case 0:
585 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2],
586 1.1 fredette &fpregs[t],status));
587 1.1 fredette case 1:
588 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2],
589 1.1 fredette &fpregs[t],status));
590 1.1 fredette }
591 1.1 fredette case 2: /* FMPY or XMPYU */
592 1.1 fredette /*
593 1.1 fredette * check for integer multiply (x bit set)
594 1.1 fredette */
595 1.1 fredette if (extru(ir,fpxpos,1)) {
596 1.1 fredette /*
597 1.1 fredette * emulate XMPYU
598 1.1 fredette */
599 1.1 fredette switch (fmt) {
600 1.1 fredette case 0:
601 1.1 fredette /*
602 1.1 fredette * bad instruction if t specifies
603 1.1 fredette * the right half of a register
604 1.1 fredette */
605 1.1 fredette if (t & 1)
606 1.1 fredette return(MAJOR_0E_EXCP);
607 1.1 fredette /* XXX fredette - broken. */
608 1.1 fredette #if 0
609 1.1 fredette impyu(&fpregs[r1],&fpregs[r2],
610 1.1 fredette &fpregs[t]);
611 1.1 fredette return(NOEXCEPTION);
612 1.1 fredette #else
613 1.1 fredette panic("impyu");
614 1.1 fredette #endif
615 1.1 fredette case 1:
616 1.1 fredette return(MAJOR_0E_EXCP);
617 1.1 fredette }
618 1.1 fredette }
619 1.1 fredette else { /* FMPY */
620 1.1 fredette switch (fmt) {
621 1.1 fredette case 0:
622 1.1 fredette return(sgl_fmpy(&fpregs[r1],
623 1.1 fredette &fpregs[r2],&fpregs[t],status));
624 1.1 fredette case 1:
625 1.1 fredette return(dbl_fmpy(&fpregs[r1],
626 1.1 fredette &fpregs[r2],&fpregs[t],status));
627 1.1 fredette }
628 1.1 fredette }
629 1.1 fredette case 3: /* FDIV */
630 1.1 fredette switch (fmt) {
631 1.1 fredette case 0:
632 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
633 1.1 fredette &fpregs[t],status));
634 1.1 fredette case 1:
635 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
636 1.1 fredette &fpregs[t],status));
637 1.1 fredette }
638 1.1 fredette case 4: /* FREM */
639 1.1 fredette switch (fmt) {
640 1.1 fredette case 0:
641 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2],
642 1.1 fredette &fpregs[t],status));
643 1.1 fredette case 1:
644 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2],
645 1.1 fredette &fpregs[t],status));
646 1.1 fredette }
647 1.1 fredette } /* end of class 3 switch */
648 1.1 fredette } /* end of switch(class) */
649 1.1 fredette panic("decode_0e");
650 1.1 fredette }
651 1.1 fredette
652 1.1 fredette
653 1.1 fredette /*
654 1.1 fredette * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
655 1.1 fredette */
656 1.1 fredette int
657 1.4 dsl decode_06(unsigned ir,unsigned fpregs[])
658 1.1 fredette {
659 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */
660 1.1 fredette unsigned fmt;
661 1.1 fredette unsigned error = 0;
662 1.1 fredette unsigned status;
663 1.1 fredette union {
664 1.1 fredette double dbl;
665 1.1 fredette float flt;
666 1.1 fredette struct { unsigned i1; unsigned i2; } ints;
667 1.1 fredette } mtmp, atmp;
668 1.1 fredette
669 1.1 fredette
670 1.1 fredette status = fpregs[0]; /* use a local copy of status reg */
671 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
672 1.1 fredette if (fmt == 0) { /* DBL */
673 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
674 1.1 fredette if (rm1 == 0)
675 1.1 fredette rm1 = fpzeroreg;
676 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
677 1.1 fredette if (rm2 == 0)
678 1.1 fredette rm2 = fpzeroreg;
679 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
680 1.1 fredette if (tm == 0)
681 1.1 fredette return(MAJOR_06_EXCP);
682 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
683 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
684 1.1 fredette if (ta == 0)
685 1.1 fredette return(MAJOR_06_EXCP);
686 1.1 fredette
687 1.1 fredette #ifdef TIMEX
688 1.1 fredette if (ra == 0) {
689 1.1 fredette /* special case FMPYCFXT */
690 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
691 1.1 fredette &status))
692 1.1 fredette error = 1;
693 1.1 fredette if (dbl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
694 1.1 fredette (unsigned *) &atmp,&status))
695 1.1 fredette error = 1;
696 1.1 fredette }
697 1.1 fredette else {
698 1.1 fredette #else
699 1.1 fredette if (ra == 0)
700 1.1 fredette ra = fpzeroreg;
701 1.1 fredette #endif
702 1.1 fredette
703 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
704 1.1 fredette &status))
705 1.1 fredette error = 1;
706 1.1 fredette if (dbl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
707 1.1 fredette &status))
708 1.1 fredette error = 1;
709 1.1 fredette #ifdef TIMEX
710 1.1 fredette }
711 1.1 fredette #endif
712 1.1 fredette if (error)
713 1.1 fredette return(MAJOR_06_EXCP);
714 1.1 fredette else {
715 1.1 fredette /* copy results */
716 1.1 fredette fpregs[tm] = mtmp.ints.i1;
717 1.1 fredette fpregs[tm+1] = mtmp.ints.i2;
718 1.1 fredette fpregs[ta] = atmp.ints.i1;
719 1.1 fredette fpregs[ta+1] = atmp.ints.i2;
720 1.1 fredette fpregs[0] = status;
721 1.1 fredette return(NOEXCEPTION);
722 1.1 fredette }
723 1.1 fredette }
724 1.1 fredette else { /* SGL */
725 1.1 fredette /*
726 1.1 fredette * calculate offsets for single precision numbers
727 1.1 fredette * See table 6-14 in PA-89 architecture for mapping
728 1.1 fredette */
729 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
730 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
731 1.1 fredette
732 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
733 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
734 1.1 fredette
735 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
736 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */
737 1.1 fredette
738 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
739 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */
740 1.1 fredette
741 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
742 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */
743 1.1 fredette
744 1.1 fredette if (ra == 0x20) { /* special case FMPYCFXT (really 0) */
745 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
746 1.1 fredette &status))
747 1.1 fredette error = 1;
748 1.1 fredette /* XXX fredette - this is broken */
749 1.1 fredette #if 0
750 1.1 fredette if (sgl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
751 1.1 fredette (unsigned *) &atmp,&status))
752 1.1 fredette error = 1;
753 1.1 fredette #else
754 1.1 fredette panic("FMPYADD");
755 1.1 fredette #endif
756 1.1 fredette }
757 1.1 fredette else {
758 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
759 1.1 fredette &status))
760 1.1 fredette error = 1;
761 1.1 fredette if (sgl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
762 1.1 fredette &status))
763 1.1 fredette error = 1;
764 1.1 fredette }
765 1.1 fredette if (error)
766 1.1 fredette return(MAJOR_06_EXCP);
767 1.1 fredette else {
768 1.1 fredette /* copy results */
769 1.1 fredette fpregs[tm] = mtmp.ints.i1;
770 1.1 fredette fpregs[ta] = atmp.ints.i1;
771 1.1 fredette fpregs[0] = status;
772 1.1 fredette return(NOEXCEPTION);
773 1.1 fredette }
774 1.1 fredette }
775 1.1 fredette }
776 1.1 fredette
777 1.1 fredette /*
778 1.1 fredette * routine to decode the 26 (FMPYSUB) instruction
779 1.1 fredette */
780 1.1 fredette int
781 1.4 dsl decode_26(unsigned ir,unsigned fpregs[])
782 1.1 fredette {
783 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */
784 1.1 fredette unsigned fmt;
785 1.1 fredette unsigned error = 0;
786 1.1 fredette unsigned status;
787 1.1 fredette union {
788 1.1 fredette double dbl;
789 1.1 fredette float flt;
790 1.1 fredette struct { unsigned i1; unsigned i2; } ints;
791 1.1 fredette } mtmp, atmp;
792 1.1 fredette
793 1.1 fredette
794 1.1 fredette status = fpregs[0];
795 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
796 1.1 fredette if (fmt == 0) { /* DBL */
797 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
798 1.1 fredette if (rm1 == 0)
799 1.1 fredette rm1 = fpzeroreg;
800 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
801 1.1 fredette if (rm2 == 0)
802 1.1 fredette rm2 = fpzeroreg;
803 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
804 1.1 fredette if (tm == 0)
805 1.1 fredette return(MAJOR_26_EXCP);
806 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
807 1.1 fredette if (ra == 0)
808 1.1 fredette return(MAJOR_26_EXCP);
809 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
810 1.1 fredette if (ta == 0)
811 1.1 fredette return(MAJOR_26_EXCP);
812 1.1 fredette
813 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
814 1.1 fredette &status))
815 1.1 fredette error = 1;
816 1.1 fredette if (dbl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
817 1.1 fredette &status))
818 1.1 fredette error = 1;
819 1.1 fredette if (error)
820 1.1 fredette return(MAJOR_26_EXCP);
821 1.1 fredette else {
822 1.1 fredette /* copy results */
823 1.1 fredette fpregs[tm] = mtmp.ints.i1;
824 1.1 fredette fpregs[tm+1] = mtmp.ints.i2;
825 1.1 fredette fpregs[ta] = atmp.ints.i1;
826 1.1 fredette fpregs[ta+1] = atmp.ints.i2;
827 1.1 fredette fpregs[0] = status;
828 1.1 fredette return(NOEXCEPTION);
829 1.1 fredette }
830 1.1 fredette }
831 1.1 fredette else { /* SGL */
832 1.1 fredette /*
833 1.1 fredette * calculate offsets for single precision numbers
834 1.1 fredette * See table 6-14 in PA-89 architecture for mapping
835 1.1 fredette */
836 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
837 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
838 1.1 fredette
839 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
840 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
841 1.1 fredette
842 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
843 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */
844 1.1 fredette
845 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
846 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */
847 1.1 fredette
848 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
849 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */
850 1.1 fredette
851 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
852 1.1 fredette &status))
853 1.1 fredette error = 1;
854 1.1 fredette if (sgl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
855 1.1 fredette &status))
856 1.1 fredette error = 1;
857 1.1 fredette if (error)
858 1.1 fredette return(MAJOR_26_EXCP);
859 1.1 fredette else {
860 1.1 fredette /* copy results */
861 1.1 fredette fpregs[tm] = mtmp.ints.i1;
862 1.1 fredette fpregs[ta] = atmp.ints.i1;
863 1.1 fredette fpregs[0] = status;
864 1.1 fredette return(NOEXCEPTION);
865 1.1 fredette }
866 1.1 fredette }
867 1.1 fredette
868 1.1 fredette }
869