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