1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Floating-point emulation code
6*4882a593Smuzhiyun * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * BEGIN_DESC
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * File:
12*4882a593Smuzhiyun * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Purpose:
15*4882a593Smuzhiyun * <<please update with a synopsis of the functionality provided by this file>>
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * External Interfaces:
18*4882a593Smuzhiyun * <<the following list was autogenerated, please review>>
19*4882a593Smuzhiyun * emfpudispatch(ir, dummy1, dummy2, fpregs)
20*4882a593Smuzhiyun * fpudispatch(ir, excp_code, holder, fpregs)
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Internal Interfaces:
23*4882a593Smuzhiyun * <<the following list was autogenerated, please review>>
24*4882a593Smuzhiyun * static u_int decode_06(u_int, u_int *)
25*4882a593Smuzhiyun * static u_int decode_0c(u_int, u_int, u_int, u_int *)
26*4882a593Smuzhiyun * static u_int decode_0e(u_int, u_int, u_int, u_int *)
27*4882a593Smuzhiyun * static u_int decode_26(u_int, u_int *)
28*4882a593Smuzhiyun * static u_int decode_2e(u_int, u_int *)
29*4882a593Smuzhiyun * static void update_status_cbit(u_int *, u_int, u_int, u_int)
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * Theory:
32*4882a593Smuzhiyun * <<please update with a overview of the operation of this file>>
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * END_DESC
35*4882a593Smuzhiyun */
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define FPUDEBUG 0
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include "float.h"
40*4882a593Smuzhiyun #include <linux/bug.h>
41*4882a593Smuzhiyun #include <linux/kernel.h>
42*4882a593Smuzhiyun #include <asm/processor.h>
43*4882a593Smuzhiyun /* #include <sys/debug.h> */
44*4882a593Smuzhiyun /* #include <machine/sys/mdep_private.h> */
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define COPR_INST 0x30000000
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun * definition of extru macro. If pos and len are constants, the compiler
50*4882a593Smuzhiyun * will generate an extru instruction when optimized
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
53*4882a593Smuzhiyun /* definitions of bit field locations in the instruction */
54*4882a593Smuzhiyun #define fpmajorpos 5
55*4882a593Smuzhiyun #define fpr1pos 10
56*4882a593Smuzhiyun #define fpr2pos 15
57*4882a593Smuzhiyun #define fptpos 31
58*4882a593Smuzhiyun #define fpsubpos 18
59*4882a593Smuzhiyun #define fpclass1subpos 16
60*4882a593Smuzhiyun #define fpclasspos 22
61*4882a593Smuzhiyun #define fpfmtpos 20
62*4882a593Smuzhiyun #define fpdfpos 18
63*4882a593Smuzhiyun #define fpnulpos 26
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun * the following are the extra bits for the 0E major op
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun #define fpxr1pos 24
68*4882a593Smuzhiyun #define fpxr2pos 19
69*4882a593Smuzhiyun #define fpxtpos 25
70*4882a593Smuzhiyun #define fpxpos 23
71*4882a593Smuzhiyun #define fp0efmtpos 20
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * the following are for the multi-ops
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun #define fprm1pos 10
76*4882a593Smuzhiyun #define fprm2pos 15
77*4882a593Smuzhiyun #define fptmpos 31
78*4882a593Smuzhiyun #define fprapos 25
79*4882a593Smuzhiyun #define fptapos 20
80*4882a593Smuzhiyun #define fpmultifmt 26
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun * the following are for the fused FP instructions
83*4882a593Smuzhiyun */
84*4882a593Smuzhiyun /* fprm1pos 10 */
85*4882a593Smuzhiyun /* fprm2pos 15 */
86*4882a593Smuzhiyun #define fpraupos 18
87*4882a593Smuzhiyun #define fpxrm2pos 19
88*4882a593Smuzhiyun /* fpfmtpos 20 */
89*4882a593Smuzhiyun #define fpralpos 23
90*4882a593Smuzhiyun #define fpxrm1pos 24
91*4882a593Smuzhiyun /* fpxtpos 25 */
92*4882a593Smuzhiyun #define fpfusedsubop 26
93*4882a593Smuzhiyun /* fptpos 31 */
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * offset to constant zero in the FP emulation registers
97*4882a593Smuzhiyun */
98*4882a593Smuzhiyun #define fpzeroreg (32*sizeof(double)/sizeof(u_int))
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * extract the major opcode from the instruction
102*4882a593Smuzhiyun */
103*4882a593Smuzhiyun #define get_major(op) extru(op,fpmajorpos,6)
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun * extract the two bit class field from the FP instruction. The class is at bit
106*4882a593Smuzhiyun * positions 21-22
107*4882a593Smuzhiyun */
108*4882a593Smuzhiyun #define get_class(op) extru(op,fpclasspos,2)
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun * extract the 3 bit subop field. For all but class 1 instructions, it is
111*4882a593Smuzhiyun * located at bit positions 16-18
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun #define get_subop(op) extru(op,fpsubpos,3)
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * extract the 2 or 3 bit subop field from class 1 instructions. It is located
116*4882a593Smuzhiyun * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
117*4882a593Smuzhiyun */
118*4882a593Smuzhiyun #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
119*4882a593Smuzhiyun #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* definitions of unimplemented exceptions */
122*4882a593Smuzhiyun #define MAJOR_0C_EXCP 0x09
123*4882a593Smuzhiyun #define MAJOR_0E_EXCP 0x0b
124*4882a593Smuzhiyun #define MAJOR_06_EXCP 0x03
125*4882a593Smuzhiyun #define MAJOR_26_EXCP 0x23
126*4882a593Smuzhiyun #define MAJOR_2E_EXCP 0x2b
127*4882a593Smuzhiyun #define PA83_UNIMP_EXCP 0x01
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /*
130*4882a593Smuzhiyun * Special Defines for TIMEX specific code
131*4882a593Smuzhiyun */
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
134*4882a593Smuzhiyun #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * Static function definitions
138*4882a593Smuzhiyun */
139*4882a593Smuzhiyun #define _PROTOTYPES
140*4882a593Smuzhiyun #if defined(_PROTOTYPES) || defined(_lint)
141*4882a593Smuzhiyun static u_int decode_0c(u_int, u_int, u_int, u_int *);
142*4882a593Smuzhiyun static u_int decode_0e(u_int, u_int, u_int, u_int *);
143*4882a593Smuzhiyun static u_int decode_06(u_int, u_int *);
144*4882a593Smuzhiyun static u_int decode_26(u_int, u_int *);
145*4882a593Smuzhiyun static u_int decode_2e(u_int, u_int *);
146*4882a593Smuzhiyun static void update_status_cbit(u_int *, u_int, u_int, u_int);
147*4882a593Smuzhiyun #else /* !_PROTOTYPES&&!_lint */
148*4882a593Smuzhiyun static u_int decode_0c();
149*4882a593Smuzhiyun static u_int decode_0e();
150*4882a593Smuzhiyun static u_int decode_06();
151*4882a593Smuzhiyun static u_int decode_26();
152*4882a593Smuzhiyun static u_int decode_2e();
153*4882a593Smuzhiyun static void update_status_cbit();
154*4882a593Smuzhiyun #endif /* _PROTOTYPES&&!_lint */
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun #define VASSERT(x)
157*4882a593Smuzhiyun
parisc_linux_get_fpu_type(u_int fpregs[])158*4882a593Smuzhiyun static void parisc_linux_get_fpu_type(u_int fpregs[])
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun /* on pa-linux the fpu type is not filled in by the
161*4882a593Smuzhiyun * caller; it is constructed here
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun if (boot_cpu_data.cpu_type == pcxs)
164*4882a593Smuzhiyun fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
165*4882a593Smuzhiyun else if (boot_cpu_data.cpu_type == pcxt ||
166*4882a593Smuzhiyun boot_cpu_data.cpu_type == pcxt_)
167*4882a593Smuzhiyun fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
168*4882a593Smuzhiyun else if (boot_cpu_data.cpu_type >= pcxu)
169*4882a593Smuzhiyun fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /*
173*4882a593Smuzhiyun * this routine will decode the excepting floating point instruction and
174*4882a593Smuzhiyun * call the appropriate emulation routine.
175*4882a593Smuzhiyun * It is called by decode_fpu with the following parameters:
176*4882a593Smuzhiyun * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
177*4882a593Smuzhiyun * where current_ir is the instruction to be emulated,
178*4882a593Smuzhiyun * unimplemented_code is the exception_code that the hardware generated
179*4882a593Smuzhiyun * and &Fpu_register is the address of emulated FP reg 0.
180*4882a593Smuzhiyun */
181*4882a593Smuzhiyun u_int
fpudispatch(u_int ir,u_int excp_code,u_int holder,u_int fpregs[])182*4882a593Smuzhiyun fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun u_int class, subop;
185*4882a593Smuzhiyun u_int fpu_type_flags;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /* All FP emulation code assumes that ints are 4-bytes in length */
188*4882a593Smuzhiyun VASSERT(sizeof(int) == 4);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun parisc_linux_get_fpu_type(fpregs);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun class = get_class(ir);
195*4882a593Smuzhiyun if (class == 1) {
196*4882a593Smuzhiyun if (fpu_type_flags & PA2_0_FPU_FLAG)
197*4882a593Smuzhiyun subop = get_subop1_PA2_0(ir);
198*4882a593Smuzhiyun else
199*4882a593Smuzhiyun subop = get_subop1_PA1_1(ir);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun else
202*4882a593Smuzhiyun subop = get_subop(ir);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun switch (excp_code) {
207*4882a593Smuzhiyun case MAJOR_0C_EXCP:
208*4882a593Smuzhiyun case PA83_UNIMP_EXCP:
209*4882a593Smuzhiyun return(decode_0c(ir,class,subop,fpregs));
210*4882a593Smuzhiyun case MAJOR_0E_EXCP:
211*4882a593Smuzhiyun return(decode_0e(ir,class,subop,fpregs));
212*4882a593Smuzhiyun case MAJOR_06_EXCP:
213*4882a593Smuzhiyun return(decode_06(ir,fpregs));
214*4882a593Smuzhiyun case MAJOR_26_EXCP:
215*4882a593Smuzhiyun return(decode_26(ir,fpregs));
216*4882a593Smuzhiyun case MAJOR_2E_EXCP:
217*4882a593Smuzhiyun return(decode_2e(ir,fpregs));
218*4882a593Smuzhiyun default:
219*4882a593Smuzhiyun /* "crashme Night Gallery painting nr 2. (asm_crash.s).
220*4882a593Smuzhiyun * This was fixed for multi-user kernels, but
221*4882a593Smuzhiyun * workstation kernels had a panic here. This allowed
222*4882a593Smuzhiyun * any arbitrary user to panic the kernel by executing
223*4882a593Smuzhiyun * setting the FP exception registers to strange values
224*4882a593Smuzhiyun * and generating an emulation trap. The emulation and
225*4882a593Smuzhiyun * exception code must never be able to panic the
226*4882a593Smuzhiyun * kernel.
227*4882a593Smuzhiyun */
228*4882a593Smuzhiyun return(UNIMPLEMENTEDEXCEPTION);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /*
233*4882a593Smuzhiyun * this routine is called by $emulation_trap to emulate a coprocessor
234*4882a593Smuzhiyun * instruction if one doesn't exist
235*4882a593Smuzhiyun */
236*4882a593Smuzhiyun u_int
emfpudispatch(u_int ir,u_int dummy1,u_int dummy2,u_int fpregs[])237*4882a593Smuzhiyun emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun u_int class, subop, major;
240*4882a593Smuzhiyun u_int fpu_type_flags;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* All FP emulation code assumes that ints are 4-bytes in length */
243*4882a593Smuzhiyun VASSERT(sizeof(int) == 4);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun major = get_major(ir);
248*4882a593Smuzhiyun class = get_class(ir);
249*4882a593Smuzhiyun if (class == 1) {
250*4882a593Smuzhiyun if (fpu_type_flags & PA2_0_FPU_FLAG)
251*4882a593Smuzhiyun subop = get_subop1_PA2_0(ir);
252*4882a593Smuzhiyun else
253*4882a593Smuzhiyun subop = get_subop1_PA1_1(ir);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun else
256*4882a593Smuzhiyun subop = get_subop(ir);
257*4882a593Smuzhiyun switch (major) {
258*4882a593Smuzhiyun case 0x0C:
259*4882a593Smuzhiyun return(decode_0c(ir,class,subop,fpregs));
260*4882a593Smuzhiyun case 0x0E:
261*4882a593Smuzhiyun return(decode_0e(ir,class,subop,fpregs));
262*4882a593Smuzhiyun case 0x06:
263*4882a593Smuzhiyun return(decode_06(ir,fpregs));
264*4882a593Smuzhiyun case 0x26:
265*4882a593Smuzhiyun return(decode_26(ir,fpregs));
266*4882a593Smuzhiyun case 0x2E:
267*4882a593Smuzhiyun return(decode_2e(ir,fpregs));
268*4882a593Smuzhiyun default:
269*4882a593Smuzhiyun return(PA83_UNIMP_EXCP);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun static u_int
decode_0c(u_int ir,u_int class,u_int subop,u_int fpregs[])275*4882a593Smuzhiyun decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun u_int r1,r2,t; /* operand register offsets */
278*4882a593Smuzhiyun u_int fmt; /* also sf for class 1 conversions */
279*4882a593Smuzhiyun u_int df; /* for class 1 conversions */
280*4882a593Smuzhiyun u_int *status;
281*4882a593Smuzhiyun u_int retval, local_status;
282*4882a593Smuzhiyun u_int fpu_type_flags;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (ir == COPR_INST) {
285*4882a593Smuzhiyun fpregs[0] = EMULATION_VERSION << 11;
286*4882a593Smuzhiyun return(NOEXCEPTION);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun status = &fpregs[0]; /* fp status register */
289*4882a593Smuzhiyun local_status = fpregs[0]; /* and local copy */
290*4882a593Smuzhiyun r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
291*4882a593Smuzhiyun if (r1 == 0) /* map fr0 source to constant zero */
292*4882a593Smuzhiyun r1 = fpzeroreg;
293*4882a593Smuzhiyun t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
294*4882a593Smuzhiyun if (t == 0 && class != 2) /* don't allow fr0 as a dest */
295*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
296*4882a593Smuzhiyun fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun switch (class) {
299*4882a593Smuzhiyun case 0:
300*4882a593Smuzhiyun switch (subop) {
301*4882a593Smuzhiyun case 0: /* COPR 0,0 emulated above*/
302*4882a593Smuzhiyun case 1:
303*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
304*4882a593Smuzhiyun case 2: /* FCPY */
305*4882a593Smuzhiyun switch (fmt) {
306*4882a593Smuzhiyun case 2: /* illegal */
307*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
308*4882a593Smuzhiyun case 3: /* quad */
309*4882a593Smuzhiyun t &= ~3; /* force to even reg #s */
310*4882a593Smuzhiyun r1 &= ~3;
311*4882a593Smuzhiyun fpregs[t+3] = fpregs[r1+3];
312*4882a593Smuzhiyun fpregs[t+2] = fpregs[r1+2];
313*4882a593Smuzhiyun fallthrough;
314*4882a593Smuzhiyun case 1: /* double */
315*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
316*4882a593Smuzhiyun fallthrough;
317*4882a593Smuzhiyun case 0: /* single */
318*4882a593Smuzhiyun fpregs[t] = fpregs[r1];
319*4882a593Smuzhiyun return(NOEXCEPTION);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun BUG();
322*4882a593Smuzhiyun case 3: /* FABS */
323*4882a593Smuzhiyun switch (fmt) {
324*4882a593Smuzhiyun case 2: /* illegal */
325*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
326*4882a593Smuzhiyun case 3: /* quad */
327*4882a593Smuzhiyun t &= ~3; /* force to even reg #s */
328*4882a593Smuzhiyun r1 &= ~3;
329*4882a593Smuzhiyun fpregs[t+3] = fpregs[r1+3];
330*4882a593Smuzhiyun fpregs[t+2] = fpregs[r1+2];
331*4882a593Smuzhiyun fallthrough;
332*4882a593Smuzhiyun case 1: /* double */
333*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
334*4882a593Smuzhiyun fallthrough;
335*4882a593Smuzhiyun case 0: /* single */
336*4882a593Smuzhiyun /* copy and clear sign bit */
337*4882a593Smuzhiyun fpregs[t] = fpregs[r1] & 0x7fffffff;
338*4882a593Smuzhiyun return(NOEXCEPTION);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun BUG();
341*4882a593Smuzhiyun case 6: /* FNEG */
342*4882a593Smuzhiyun switch (fmt) {
343*4882a593Smuzhiyun case 2: /* illegal */
344*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
345*4882a593Smuzhiyun case 3: /* quad */
346*4882a593Smuzhiyun t &= ~3; /* force to even reg #s */
347*4882a593Smuzhiyun r1 &= ~3;
348*4882a593Smuzhiyun fpregs[t+3] = fpregs[r1+3];
349*4882a593Smuzhiyun fpregs[t+2] = fpregs[r1+2];
350*4882a593Smuzhiyun fallthrough;
351*4882a593Smuzhiyun case 1: /* double */
352*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
353*4882a593Smuzhiyun fallthrough;
354*4882a593Smuzhiyun case 0: /* single */
355*4882a593Smuzhiyun /* copy and invert sign bit */
356*4882a593Smuzhiyun fpregs[t] = fpregs[r1] ^ 0x80000000;
357*4882a593Smuzhiyun return(NOEXCEPTION);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun BUG();
360*4882a593Smuzhiyun case 7: /* FNEGABS */
361*4882a593Smuzhiyun switch (fmt) {
362*4882a593Smuzhiyun case 2: /* illegal */
363*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
364*4882a593Smuzhiyun case 3: /* quad */
365*4882a593Smuzhiyun t &= ~3; /* force to even reg #s */
366*4882a593Smuzhiyun r1 &= ~3;
367*4882a593Smuzhiyun fpregs[t+3] = fpregs[r1+3];
368*4882a593Smuzhiyun fpregs[t+2] = fpregs[r1+2];
369*4882a593Smuzhiyun fallthrough;
370*4882a593Smuzhiyun case 1: /* double */
371*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
372*4882a593Smuzhiyun fallthrough;
373*4882a593Smuzhiyun case 0: /* single */
374*4882a593Smuzhiyun /* copy and set sign bit */
375*4882a593Smuzhiyun fpregs[t] = fpregs[r1] | 0x80000000;
376*4882a593Smuzhiyun return(NOEXCEPTION);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun BUG();
379*4882a593Smuzhiyun case 4: /* FSQRT */
380*4882a593Smuzhiyun switch (fmt) {
381*4882a593Smuzhiyun case 0:
382*4882a593Smuzhiyun return(sgl_fsqrt(&fpregs[r1],0,
383*4882a593Smuzhiyun &fpregs[t],status));
384*4882a593Smuzhiyun case 1:
385*4882a593Smuzhiyun return(dbl_fsqrt(&fpregs[r1],0,
386*4882a593Smuzhiyun &fpregs[t],status));
387*4882a593Smuzhiyun case 2:
388*4882a593Smuzhiyun case 3: /* quad not implemented */
389*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun BUG();
392*4882a593Smuzhiyun case 5: /* FRND */
393*4882a593Smuzhiyun switch (fmt) {
394*4882a593Smuzhiyun case 0:
395*4882a593Smuzhiyun return(sgl_frnd(&fpregs[r1],0,
396*4882a593Smuzhiyun &fpregs[t],status));
397*4882a593Smuzhiyun case 1:
398*4882a593Smuzhiyun return(dbl_frnd(&fpregs[r1],0,
399*4882a593Smuzhiyun &fpregs[t],status));
400*4882a593Smuzhiyun case 2:
401*4882a593Smuzhiyun case 3: /* quad not implemented */
402*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun } /* end of switch (subop) */
405*4882a593Smuzhiyun BUG();
406*4882a593Smuzhiyun case 1: /* class 1 */
407*4882a593Smuzhiyun df = extru(ir,fpdfpos,2); /* get dest format */
408*4882a593Smuzhiyun if ((df & 2) || (fmt & 2)) {
409*4882a593Smuzhiyun /*
410*4882a593Smuzhiyun * fmt's 2 and 3 are illegal of not implemented
411*4882a593Smuzhiyun * quad conversions
412*4882a593Smuzhiyun */
413*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun /*
416*4882a593Smuzhiyun * encode source and dest formats into 2 bits.
417*4882a593Smuzhiyun * high bit is source, low bit is dest.
418*4882a593Smuzhiyun * bit = 1 --> double precision
419*4882a593Smuzhiyun */
420*4882a593Smuzhiyun fmt = (fmt << 1) | df;
421*4882a593Smuzhiyun switch (subop) {
422*4882a593Smuzhiyun case 0: /* FCNVFF */
423*4882a593Smuzhiyun switch(fmt) {
424*4882a593Smuzhiyun case 0: /* sgl/sgl */
425*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
426*4882a593Smuzhiyun case 1: /* sgl/dbl */
427*4882a593Smuzhiyun return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
428*4882a593Smuzhiyun &fpregs[t],status));
429*4882a593Smuzhiyun case 2: /* dbl/sgl */
430*4882a593Smuzhiyun return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
431*4882a593Smuzhiyun &fpregs[t],status));
432*4882a593Smuzhiyun case 3: /* dbl/dbl */
433*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun BUG();
436*4882a593Smuzhiyun case 1: /* FCNVXF */
437*4882a593Smuzhiyun switch(fmt) {
438*4882a593Smuzhiyun case 0: /* sgl/sgl */
439*4882a593Smuzhiyun return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
440*4882a593Smuzhiyun &fpregs[t],status));
441*4882a593Smuzhiyun case 1: /* sgl/dbl */
442*4882a593Smuzhiyun return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
443*4882a593Smuzhiyun &fpregs[t],status));
444*4882a593Smuzhiyun case 2: /* dbl/sgl */
445*4882a593Smuzhiyun return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
446*4882a593Smuzhiyun &fpregs[t],status));
447*4882a593Smuzhiyun case 3: /* dbl/dbl */
448*4882a593Smuzhiyun return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
449*4882a593Smuzhiyun &fpregs[t],status));
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun BUG();
452*4882a593Smuzhiyun case 2: /* FCNVFX */
453*4882a593Smuzhiyun switch(fmt) {
454*4882a593Smuzhiyun case 0: /* sgl/sgl */
455*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
456*4882a593Smuzhiyun &fpregs[t],status));
457*4882a593Smuzhiyun case 1: /* sgl/dbl */
458*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
459*4882a593Smuzhiyun &fpregs[t],status));
460*4882a593Smuzhiyun case 2: /* dbl/sgl */
461*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
462*4882a593Smuzhiyun &fpregs[t],status));
463*4882a593Smuzhiyun case 3: /* dbl/dbl */
464*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
465*4882a593Smuzhiyun &fpregs[t],status));
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun BUG();
468*4882a593Smuzhiyun case 3: /* FCNVFXT */
469*4882a593Smuzhiyun switch(fmt) {
470*4882a593Smuzhiyun case 0: /* sgl/sgl */
471*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
472*4882a593Smuzhiyun &fpregs[t],status));
473*4882a593Smuzhiyun case 1: /* sgl/dbl */
474*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
475*4882a593Smuzhiyun &fpregs[t],status));
476*4882a593Smuzhiyun case 2: /* dbl/sgl */
477*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
478*4882a593Smuzhiyun &fpregs[t],status));
479*4882a593Smuzhiyun case 3: /* dbl/dbl */
480*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
481*4882a593Smuzhiyun &fpregs[t],status));
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun BUG();
484*4882a593Smuzhiyun case 5: /* FCNVUF (PA2.0 only) */
485*4882a593Smuzhiyun switch(fmt) {
486*4882a593Smuzhiyun case 0: /* sgl/sgl */
487*4882a593Smuzhiyun return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
488*4882a593Smuzhiyun &fpregs[t],status));
489*4882a593Smuzhiyun case 1: /* sgl/dbl */
490*4882a593Smuzhiyun return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
491*4882a593Smuzhiyun &fpregs[t],status));
492*4882a593Smuzhiyun case 2: /* dbl/sgl */
493*4882a593Smuzhiyun return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
494*4882a593Smuzhiyun &fpregs[t],status));
495*4882a593Smuzhiyun case 3: /* dbl/dbl */
496*4882a593Smuzhiyun return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
497*4882a593Smuzhiyun &fpregs[t],status));
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun BUG();
500*4882a593Smuzhiyun case 6: /* FCNVFU (PA2.0 only) */
501*4882a593Smuzhiyun switch(fmt) {
502*4882a593Smuzhiyun case 0: /* sgl/sgl */
503*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
504*4882a593Smuzhiyun &fpregs[t],status));
505*4882a593Smuzhiyun case 1: /* sgl/dbl */
506*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
507*4882a593Smuzhiyun &fpregs[t],status));
508*4882a593Smuzhiyun case 2: /* dbl/sgl */
509*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
510*4882a593Smuzhiyun &fpregs[t],status));
511*4882a593Smuzhiyun case 3: /* dbl/dbl */
512*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
513*4882a593Smuzhiyun &fpregs[t],status));
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun BUG();
516*4882a593Smuzhiyun case 7: /* FCNVFUT (PA2.0 only) */
517*4882a593Smuzhiyun switch(fmt) {
518*4882a593Smuzhiyun case 0: /* sgl/sgl */
519*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
520*4882a593Smuzhiyun &fpregs[t],status));
521*4882a593Smuzhiyun case 1: /* sgl/dbl */
522*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
523*4882a593Smuzhiyun &fpregs[t],status));
524*4882a593Smuzhiyun case 2: /* dbl/sgl */
525*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
526*4882a593Smuzhiyun &fpregs[t],status));
527*4882a593Smuzhiyun case 3: /* dbl/dbl */
528*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
529*4882a593Smuzhiyun &fpregs[t],status));
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun BUG();
532*4882a593Smuzhiyun case 4: /* undefined */
533*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
534*4882a593Smuzhiyun } /* end of switch subop */
535*4882a593Smuzhiyun BUG();
536*4882a593Smuzhiyun case 2: /* class 2 */
537*4882a593Smuzhiyun fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
538*4882a593Smuzhiyun r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
539*4882a593Smuzhiyun if (r2 == 0)
540*4882a593Smuzhiyun r2 = fpzeroreg;
541*4882a593Smuzhiyun if (fpu_type_flags & PA2_0_FPU_FLAG) {
542*4882a593Smuzhiyun /* FTEST if nullify bit set, otherwise FCMP */
543*4882a593Smuzhiyun if (extru(ir, fpnulpos, 1)) { /* FTEST */
544*4882a593Smuzhiyun switch (fmt) {
545*4882a593Smuzhiyun case 0:
546*4882a593Smuzhiyun /*
547*4882a593Smuzhiyun * arg0 is not used
548*4882a593Smuzhiyun * second param is the t field used for
549*4882a593Smuzhiyun * ftest,acc and ftest,rej
550*4882a593Smuzhiyun * third param is the subop (y-field)
551*4882a593Smuzhiyun */
552*4882a593Smuzhiyun BUG();
553*4882a593Smuzhiyun /* Unsupported
554*4882a593Smuzhiyun * return(ftest(0L,extru(ir,fptpos,5),
555*4882a593Smuzhiyun * &fpregs[0],subop));
556*4882a593Smuzhiyun */
557*4882a593Smuzhiyun case 1:
558*4882a593Smuzhiyun case 2:
559*4882a593Smuzhiyun case 3:
560*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun } else { /* FCMP */
563*4882a593Smuzhiyun switch (fmt) {
564*4882a593Smuzhiyun case 0:
565*4882a593Smuzhiyun retval = sgl_fcmp(&fpregs[r1],
566*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
567*4882a593Smuzhiyun &local_status);
568*4882a593Smuzhiyun update_status_cbit(status,local_status,
569*4882a593Smuzhiyun fpu_type_flags, subop);
570*4882a593Smuzhiyun return(retval);
571*4882a593Smuzhiyun case 1:
572*4882a593Smuzhiyun retval = dbl_fcmp(&fpregs[r1],
573*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
574*4882a593Smuzhiyun &local_status);
575*4882a593Smuzhiyun update_status_cbit(status,local_status,
576*4882a593Smuzhiyun fpu_type_flags, subop);
577*4882a593Smuzhiyun return(retval);
578*4882a593Smuzhiyun case 2: /* illegal */
579*4882a593Smuzhiyun case 3: /* quad not implemented */
580*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun } /* end of if for PA2.0 */
584*4882a593Smuzhiyun else { /* PA1.0 & PA1.1 */
585*4882a593Smuzhiyun switch (subop) {
586*4882a593Smuzhiyun case 2:
587*4882a593Smuzhiyun case 3:
588*4882a593Smuzhiyun case 4:
589*4882a593Smuzhiyun case 5:
590*4882a593Smuzhiyun case 6:
591*4882a593Smuzhiyun case 7:
592*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
593*4882a593Smuzhiyun case 0: /* FCMP */
594*4882a593Smuzhiyun switch (fmt) {
595*4882a593Smuzhiyun case 0:
596*4882a593Smuzhiyun retval = sgl_fcmp(&fpregs[r1],
597*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
598*4882a593Smuzhiyun &local_status);
599*4882a593Smuzhiyun update_status_cbit(status,local_status,
600*4882a593Smuzhiyun fpu_type_flags, subop);
601*4882a593Smuzhiyun return(retval);
602*4882a593Smuzhiyun case 1:
603*4882a593Smuzhiyun retval = dbl_fcmp(&fpregs[r1],
604*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
605*4882a593Smuzhiyun &local_status);
606*4882a593Smuzhiyun update_status_cbit(status,local_status,
607*4882a593Smuzhiyun fpu_type_flags, subop);
608*4882a593Smuzhiyun return(retval);
609*4882a593Smuzhiyun case 2: /* illegal */
610*4882a593Smuzhiyun case 3: /* quad not implemented */
611*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun BUG();
614*4882a593Smuzhiyun case 1: /* FTEST */
615*4882a593Smuzhiyun switch (fmt) {
616*4882a593Smuzhiyun case 0:
617*4882a593Smuzhiyun /*
618*4882a593Smuzhiyun * arg0 is not used
619*4882a593Smuzhiyun * second param is the t field used for
620*4882a593Smuzhiyun * ftest,acc and ftest,rej
621*4882a593Smuzhiyun * third param is the subop (y-field)
622*4882a593Smuzhiyun */
623*4882a593Smuzhiyun BUG();
624*4882a593Smuzhiyun /* unsupported
625*4882a593Smuzhiyun * return(ftest(0L,extru(ir,fptpos,5),
626*4882a593Smuzhiyun * &fpregs[0],subop));
627*4882a593Smuzhiyun */
628*4882a593Smuzhiyun case 1:
629*4882a593Smuzhiyun case 2:
630*4882a593Smuzhiyun case 3:
631*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun BUG();
634*4882a593Smuzhiyun } /* end of switch subop */
635*4882a593Smuzhiyun } /* end of else for PA1.0 & PA1.1 */
636*4882a593Smuzhiyun BUG();
637*4882a593Smuzhiyun case 3: /* class 3 */
638*4882a593Smuzhiyun r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
639*4882a593Smuzhiyun if (r2 == 0)
640*4882a593Smuzhiyun r2 = fpzeroreg;
641*4882a593Smuzhiyun switch (subop) {
642*4882a593Smuzhiyun case 5:
643*4882a593Smuzhiyun case 6:
644*4882a593Smuzhiyun case 7:
645*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun case 0: /* FADD */
648*4882a593Smuzhiyun switch (fmt) {
649*4882a593Smuzhiyun case 0:
650*4882a593Smuzhiyun return(sgl_fadd(&fpregs[r1],&fpregs[r2],
651*4882a593Smuzhiyun &fpregs[t],status));
652*4882a593Smuzhiyun case 1:
653*4882a593Smuzhiyun return(dbl_fadd(&fpregs[r1],&fpregs[r2],
654*4882a593Smuzhiyun &fpregs[t],status));
655*4882a593Smuzhiyun case 2: /* illegal */
656*4882a593Smuzhiyun case 3: /* quad not implemented */
657*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun BUG();
660*4882a593Smuzhiyun case 1: /* FSUB */
661*4882a593Smuzhiyun switch (fmt) {
662*4882a593Smuzhiyun case 0:
663*4882a593Smuzhiyun return(sgl_fsub(&fpregs[r1],&fpregs[r2],
664*4882a593Smuzhiyun &fpregs[t],status));
665*4882a593Smuzhiyun case 1:
666*4882a593Smuzhiyun return(dbl_fsub(&fpregs[r1],&fpregs[r2],
667*4882a593Smuzhiyun &fpregs[t],status));
668*4882a593Smuzhiyun case 2: /* illegal */
669*4882a593Smuzhiyun case 3: /* quad not implemented */
670*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun BUG();
673*4882a593Smuzhiyun case 2: /* FMPY */
674*4882a593Smuzhiyun switch (fmt) {
675*4882a593Smuzhiyun case 0:
676*4882a593Smuzhiyun return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
677*4882a593Smuzhiyun &fpregs[t],status));
678*4882a593Smuzhiyun case 1:
679*4882a593Smuzhiyun return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
680*4882a593Smuzhiyun &fpregs[t],status));
681*4882a593Smuzhiyun case 2: /* illegal */
682*4882a593Smuzhiyun case 3: /* quad not implemented */
683*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun BUG();
686*4882a593Smuzhiyun case 3: /* FDIV */
687*4882a593Smuzhiyun switch (fmt) {
688*4882a593Smuzhiyun case 0:
689*4882a593Smuzhiyun return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
690*4882a593Smuzhiyun &fpregs[t],status));
691*4882a593Smuzhiyun case 1:
692*4882a593Smuzhiyun return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
693*4882a593Smuzhiyun &fpregs[t],status));
694*4882a593Smuzhiyun case 2: /* illegal */
695*4882a593Smuzhiyun case 3: /* quad not implemented */
696*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun BUG();
699*4882a593Smuzhiyun case 4: /* FREM */
700*4882a593Smuzhiyun switch (fmt) {
701*4882a593Smuzhiyun case 0:
702*4882a593Smuzhiyun return(sgl_frem(&fpregs[r1],&fpregs[r2],
703*4882a593Smuzhiyun &fpregs[t],status));
704*4882a593Smuzhiyun case 1:
705*4882a593Smuzhiyun return(dbl_frem(&fpregs[r1],&fpregs[r2],
706*4882a593Smuzhiyun &fpregs[t],status));
707*4882a593Smuzhiyun case 2: /* illegal */
708*4882a593Smuzhiyun case 3: /* quad not implemented */
709*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun BUG();
712*4882a593Smuzhiyun } /* end of class 3 switch */
713*4882a593Smuzhiyun } /* end of switch(class) */
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun /* If we get here, something is really wrong! */
716*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun static u_int
decode_0e(ir,class,subop,fpregs)720*4882a593Smuzhiyun decode_0e(ir,class,subop,fpregs)
721*4882a593Smuzhiyun u_int ir,class,subop;
722*4882a593Smuzhiyun u_int fpregs[];
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun u_int r1,r2,t; /* operand register offsets */
725*4882a593Smuzhiyun u_int fmt; /* also sf for class 1 conversions */
726*4882a593Smuzhiyun u_int df; /* dest format for class 1 conversions */
727*4882a593Smuzhiyun u_int *status;
728*4882a593Smuzhiyun u_int retval, local_status;
729*4882a593Smuzhiyun u_int fpu_type_flags;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun status = &fpregs[0];
732*4882a593Smuzhiyun local_status = fpregs[0];
733*4882a593Smuzhiyun r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
734*4882a593Smuzhiyun if (r1 == 0)
735*4882a593Smuzhiyun r1 = fpzeroreg;
736*4882a593Smuzhiyun t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
737*4882a593Smuzhiyun if (t == 0 && class != 2)
738*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
739*4882a593Smuzhiyun if (class < 2) /* class 0 or 1 has 2 bit fmt */
740*4882a593Smuzhiyun fmt = extru(ir,fpfmtpos,2);
741*4882a593Smuzhiyun else /* class 2 and 3 have 1 bit fmt */
742*4882a593Smuzhiyun fmt = extru(ir,fp0efmtpos,1);
743*4882a593Smuzhiyun /*
744*4882a593Smuzhiyun * An undefined combination, double precision accessing the
745*4882a593Smuzhiyun * right half of a FPR, can get us into trouble.
746*4882a593Smuzhiyun * Let's just force proper alignment on it.
747*4882a593Smuzhiyun */
748*4882a593Smuzhiyun if (fmt == DBL) {
749*4882a593Smuzhiyun r1 &= ~1;
750*4882a593Smuzhiyun if (class != 1)
751*4882a593Smuzhiyun t &= ~1;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun switch (class) {
755*4882a593Smuzhiyun case 0:
756*4882a593Smuzhiyun switch (subop) {
757*4882a593Smuzhiyun case 0: /* unimplemented */
758*4882a593Smuzhiyun case 1:
759*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
760*4882a593Smuzhiyun case 2: /* FCPY */
761*4882a593Smuzhiyun switch (fmt) {
762*4882a593Smuzhiyun case 2:
763*4882a593Smuzhiyun case 3:
764*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
765*4882a593Smuzhiyun case 1: /* double */
766*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
767*4882a593Smuzhiyun fallthrough;
768*4882a593Smuzhiyun case 0: /* single */
769*4882a593Smuzhiyun fpregs[t] = fpregs[r1];
770*4882a593Smuzhiyun return(NOEXCEPTION);
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun BUG();
773*4882a593Smuzhiyun case 3: /* FABS */
774*4882a593Smuzhiyun switch (fmt) {
775*4882a593Smuzhiyun case 2:
776*4882a593Smuzhiyun case 3:
777*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
778*4882a593Smuzhiyun case 1: /* double */
779*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
780*4882a593Smuzhiyun fallthrough;
781*4882a593Smuzhiyun case 0: /* single */
782*4882a593Smuzhiyun fpregs[t] = fpregs[r1] & 0x7fffffff;
783*4882a593Smuzhiyun return(NOEXCEPTION);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun BUG();
786*4882a593Smuzhiyun case 6: /* FNEG */
787*4882a593Smuzhiyun switch (fmt) {
788*4882a593Smuzhiyun case 2:
789*4882a593Smuzhiyun case 3:
790*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
791*4882a593Smuzhiyun case 1: /* double */
792*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
793*4882a593Smuzhiyun fallthrough;
794*4882a593Smuzhiyun case 0: /* single */
795*4882a593Smuzhiyun fpregs[t] = fpregs[r1] ^ 0x80000000;
796*4882a593Smuzhiyun return(NOEXCEPTION);
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun BUG();
799*4882a593Smuzhiyun case 7: /* FNEGABS */
800*4882a593Smuzhiyun switch (fmt) {
801*4882a593Smuzhiyun case 2:
802*4882a593Smuzhiyun case 3:
803*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
804*4882a593Smuzhiyun case 1: /* double */
805*4882a593Smuzhiyun fpregs[t+1] = fpregs[r1+1];
806*4882a593Smuzhiyun fallthrough;
807*4882a593Smuzhiyun case 0: /* single */
808*4882a593Smuzhiyun fpregs[t] = fpregs[r1] | 0x80000000;
809*4882a593Smuzhiyun return(NOEXCEPTION);
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun BUG();
812*4882a593Smuzhiyun case 4: /* FSQRT */
813*4882a593Smuzhiyun switch (fmt) {
814*4882a593Smuzhiyun case 0:
815*4882a593Smuzhiyun return(sgl_fsqrt(&fpregs[r1],0,
816*4882a593Smuzhiyun &fpregs[t], status));
817*4882a593Smuzhiyun case 1:
818*4882a593Smuzhiyun return(dbl_fsqrt(&fpregs[r1],0,
819*4882a593Smuzhiyun &fpregs[t], status));
820*4882a593Smuzhiyun case 2:
821*4882a593Smuzhiyun case 3:
822*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun BUG();
825*4882a593Smuzhiyun case 5: /* FRMD */
826*4882a593Smuzhiyun switch (fmt) {
827*4882a593Smuzhiyun case 0:
828*4882a593Smuzhiyun return(sgl_frnd(&fpregs[r1],0,
829*4882a593Smuzhiyun &fpregs[t], status));
830*4882a593Smuzhiyun case 1:
831*4882a593Smuzhiyun return(dbl_frnd(&fpregs[r1],0,
832*4882a593Smuzhiyun &fpregs[t], status));
833*4882a593Smuzhiyun case 2:
834*4882a593Smuzhiyun case 3:
835*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun } /* end of switch (subop */
838*4882a593Smuzhiyun BUG();
839*4882a593Smuzhiyun case 1: /* class 1 */
840*4882a593Smuzhiyun df = extru(ir,fpdfpos,2); /* get dest format */
841*4882a593Smuzhiyun /*
842*4882a593Smuzhiyun * Fix Crashme problem (writing to 31R in double precision)
843*4882a593Smuzhiyun * here too.
844*4882a593Smuzhiyun */
845*4882a593Smuzhiyun if (df == DBL) {
846*4882a593Smuzhiyun t &= ~1;
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun if ((df & 2) || (fmt & 2))
849*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun fmt = (fmt << 1) | df;
852*4882a593Smuzhiyun switch (subop) {
853*4882a593Smuzhiyun case 0: /* FCNVFF */
854*4882a593Smuzhiyun switch(fmt) {
855*4882a593Smuzhiyun case 0: /* sgl/sgl */
856*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
857*4882a593Smuzhiyun case 1: /* sgl/dbl */
858*4882a593Smuzhiyun return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
859*4882a593Smuzhiyun &fpregs[t],status));
860*4882a593Smuzhiyun case 2: /* dbl/sgl */
861*4882a593Smuzhiyun return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
862*4882a593Smuzhiyun &fpregs[t],status));
863*4882a593Smuzhiyun case 3: /* dbl/dbl */
864*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun BUG();
867*4882a593Smuzhiyun case 1: /* FCNVXF */
868*4882a593Smuzhiyun switch(fmt) {
869*4882a593Smuzhiyun case 0: /* sgl/sgl */
870*4882a593Smuzhiyun return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
871*4882a593Smuzhiyun &fpregs[t],status));
872*4882a593Smuzhiyun case 1: /* sgl/dbl */
873*4882a593Smuzhiyun return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
874*4882a593Smuzhiyun &fpregs[t],status));
875*4882a593Smuzhiyun case 2: /* dbl/sgl */
876*4882a593Smuzhiyun return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
877*4882a593Smuzhiyun &fpregs[t],status));
878*4882a593Smuzhiyun case 3: /* dbl/dbl */
879*4882a593Smuzhiyun return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
880*4882a593Smuzhiyun &fpregs[t],status));
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun BUG();
883*4882a593Smuzhiyun case 2: /* FCNVFX */
884*4882a593Smuzhiyun switch(fmt) {
885*4882a593Smuzhiyun case 0: /* sgl/sgl */
886*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
887*4882a593Smuzhiyun &fpregs[t],status));
888*4882a593Smuzhiyun case 1: /* sgl/dbl */
889*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
890*4882a593Smuzhiyun &fpregs[t],status));
891*4882a593Smuzhiyun case 2: /* dbl/sgl */
892*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
893*4882a593Smuzhiyun &fpregs[t],status));
894*4882a593Smuzhiyun case 3: /* dbl/dbl */
895*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
896*4882a593Smuzhiyun &fpregs[t],status));
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun BUG();
899*4882a593Smuzhiyun case 3: /* FCNVFXT */
900*4882a593Smuzhiyun switch(fmt) {
901*4882a593Smuzhiyun case 0: /* sgl/sgl */
902*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
903*4882a593Smuzhiyun &fpregs[t],status));
904*4882a593Smuzhiyun case 1: /* sgl/dbl */
905*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
906*4882a593Smuzhiyun &fpregs[t],status));
907*4882a593Smuzhiyun case 2: /* dbl/sgl */
908*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
909*4882a593Smuzhiyun &fpregs[t],status));
910*4882a593Smuzhiyun case 3: /* dbl/dbl */
911*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
912*4882a593Smuzhiyun &fpregs[t],status));
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun BUG();
915*4882a593Smuzhiyun case 5: /* FCNVUF (PA2.0 only) */
916*4882a593Smuzhiyun switch(fmt) {
917*4882a593Smuzhiyun case 0: /* sgl/sgl */
918*4882a593Smuzhiyun return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
919*4882a593Smuzhiyun &fpregs[t],status));
920*4882a593Smuzhiyun case 1: /* sgl/dbl */
921*4882a593Smuzhiyun return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
922*4882a593Smuzhiyun &fpregs[t],status));
923*4882a593Smuzhiyun case 2: /* dbl/sgl */
924*4882a593Smuzhiyun return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
925*4882a593Smuzhiyun &fpregs[t],status));
926*4882a593Smuzhiyun case 3: /* dbl/dbl */
927*4882a593Smuzhiyun return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
928*4882a593Smuzhiyun &fpregs[t],status));
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun BUG();
931*4882a593Smuzhiyun case 6: /* FCNVFU (PA2.0 only) */
932*4882a593Smuzhiyun switch(fmt) {
933*4882a593Smuzhiyun case 0: /* sgl/sgl */
934*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
935*4882a593Smuzhiyun &fpregs[t],status));
936*4882a593Smuzhiyun case 1: /* sgl/dbl */
937*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
938*4882a593Smuzhiyun &fpregs[t],status));
939*4882a593Smuzhiyun case 2: /* dbl/sgl */
940*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
941*4882a593Smuzhiyun &fpregs[t],status));
942*4882a593Smuzhiyun case 3: /* dbl/dbl */
943*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
944*4882a593Smuzhiyun &fpregs[t],status));
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun BUG();
947*4882a593Smuzhiyun case 7: /* FCNVFUT (PA2.0 only) */
948*4882a593Smuzhiyun switch(fmt) {
949*4882a593Smuzhiyun case 0: /* sgl/sgl */
950*4882a593Smuzhiyun return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
951*4882a593Smuzhiyun &fpregs[t],status));
952*4882a593Smuzhiyun case 1: /* sgl/dbl */
953*4882a593Smuzhiyun return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
954*4882a593Smuzhiyun &fpregs[t],status));
955*4882a593Smuzhiyun case 2: /* dbl/sgl */
956*4882a593Smuzhiyun return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
957*4882a593Smuzhiyun &fpregs[t],status));
958*4882a593Smuzhiyun case 3: /* dbl/dbl */
959*4882a593Smuzhiyun return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
960*4882a593Smuzhiyun &fpregs[t],status));
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun BUG();
963*4882a593Smuzhiyun case 4: /* undefined */
964*4882a593Smuzhiyun return(MAJOR_0C_EXCP);
965*4882a593Smuzhiyun } /* end of switch subop */
966*4882a593Smuzhiyun BUG();
967*4882a593Smuzhiyun case 2: /* class 2 */
968*4882a593Smuzhiyun /*
969*4882a593Smuzhiyun * Be careful out there.
970*4882a593Smuzhiyun * Crashme can generate cases where FR31R is specified
971*4882a593Smuzhiyun * as the source or target of a double precision operation.
972*4882a593Smuzhiyun * Since we just pass the address of the floating-point
973*4882a593Smuzhiyun * register to the emulation routines, this can cause
974*4882a593Smuzhiyun * corruption of fpzeroreg.
975*4882a593Smuzhiyun */
976*4882a593Smuzhiyun if (fmt == DBL)
977*4882a593Smuzhiyun r2 = (extru(ir,fpr2pos,5)<<1);
978*4882a593Smuzhiyun else
979*4882a593Smuzhiyun r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
980*4882a593Smuzhiyun fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
981*4882a593Smuzhiyun if (r2 == 0)
982*4882a593Smuzhiyun r2 = fpzeroreg;
983*4882a593Smuzhiyun if (fpu_type_flags & PA2_0_FPU_FLAG) {
984*4882a593Smuzhiyun /* FTEST if nullify bit set, otherwise FCMP */
985*4882a593Smuzhiyun if (extru(ir, fpnulpos, 1)) { /* FTEST */
986*4882a593Smuzhiyun /* not legal */
987*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
988*4882a593Smuzhiyun } else { /* FCMP */
989*4882a593Smuzhiyun switch (fmt) {
990*4882a593Smuzhiyun /*
991*4882a593Smuzhiyun * fmt is only 1 bit long
992*4882a593Smuzhiyun */
993*4882a593Smuzhiyun case 0:
994*4882a593Smuzhiyun retval = sgl_fcmp(&fpregs[r1],
995*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
996*4882a593Smuzhiyun &local_status);
997*4882a593Smuzhiyun update_status_cbit(status,local_status,
998*4882a593Smuzhiyun fpu_type_flags, subop);
999*4882a593Smuzhiyun return(retval);
1000*4882a593Smuzhiyun case 1:
1001*4882a593Smuzhiyun retval = dbl_fcmp(&fpregs[r1],
1002*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
1003*4882a593Smuzhiyun &local_status);
1004*4882a593Smuzhiyun update_status_cbit(status,local_status,
1005*4882a593Smuzhiyun fpu_type_flags, subop);
1006*4882a593Smuzhiyun return(retval);
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun } /* end of if for PA2.0 */
1010*4882a593Smuzhiyun else { /* PA1.0 & PA1.1 */
1011*4882a593Smuzhiyun switch (subop) {
1012*4882a593Smuzhiyun case 1:
1013*4882a593Smuzhiyun case 2:
1014*4882a593Smuzhiyun case 3:
1015*4882a593Smuzhiyun case 4:
1016*4882a593Smuzhiyun case 5:
1017*4882a593Smuzhiyun case 6:
1018*4882a593Smuzhiyun case 7:
1019*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
1020*4882a593Smuzhiyun case 0: /* FCMP */
1021*4882a593Smuzhiyun switch (fmt) {
1022*4882a593Smuzhiyun /*
1023*4882a593Smuzhiyun * fmt is only 1 bit long
1024*4882a593Smuzhiyun */
1025*4882a593Smuzhiyun case 0:
1026*4882a593Smuzhiyun retval = sgl_fcmp(&fpregs[r1],
1027*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
1028*4882a593Smuzhiyun &local_status);
1029*4882a593Smuzhiyun update_status_cbit(status,local_status,
1030*4882a593Smuzhiyun fpu_type_flags, subop);
1031*4882a593Smuzhiyun return(retval);
1032*4882a593Smuzhiyun case 1:
1033*4882a593Smuzhiyun retval = dbl_fcmp(&fpregs[r1],
1034*4882a593Smuzhiyun &fpregs[r2],extru(ir,fptpos,5),
1035*4882a593Smuzhiyun &local_status);
1036*4882a593Smuzhiyun update_status_cbit(status,local_status,
1037*4882a593Smuzhiyun fpu_type_flags, subop);
1038*4882a593Smuzhiyun return(retval);
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun } /* end of switch subop */
1041*4882a593Smuzhiyun } /* end of else for PA1.0 & PA1.1 */
1042*4882a593Smuzhiyun BUG();
1043*4882a593Smuzhiyun case 3: /* class 3 */
1044*4882a593Smuzhiyun /*
1045*4882a593Smuzhiyun * Be careful out there.
1046*4882a593Smuzhiyun * Crashme can generate cases where FR31R is specified
1047*4882a593Smuzhiyun * as the source or target of a double precision operation.
1048*4882a593Smuzhiyun * Since we just pass the address of the floating-point
1049*4882a593Smuzhiyun * register to the emulation routines, this can cause
1050*4882a593Smuzhiyun * corruption of fpzeroreg.
1051*4882a593Smuzhiyun */
1052*4882a593Smuzhiyun if (fmt == DBL)
1053*4882a593Smuzhiyun r2 = (extru(ir,fpr2pos,5)<<1);
1054*4882a593Smuzhiyun else
1055*4882a593Smuzhiyun r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
1056*4882a593Smuzhiyun if (r2 == 0)
1057*4882a593Smuzhiyun r2 = fpzeroreg;
1058*4882a593Smuzhiyun switch (subop) {
1059*4882a593Smuzhiyun case 5:
1060*4882a593Smuzhiyun case 6:
1061*4882a593Smuzhiyun case 7:
1062*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun /*
1065*4882a593Smuzhiyun * Note that fmt is only 1 bit for class 3 */
1066*4882a593Smuzhiyun case 0: /* FADD */
1067*4882a593Smuzhiyun switch (fmt) {
1068*4882a593Smuzhiyun case 0:
1069*4882a593Smuzhiyun return(sgl_fadd(&fpregs[r1],&fpregs[r2],
1070*4882a593Smuzhiyun &fpregs[t],status));
1071*4882a593Smuzhiyun case 1:
1072*4882a593Smuzhiyun return(dbl_fadd(&fpregs[r1],&fpregs[r2],
1073*4882a593Smuzhiyun &fpregs[t],status));
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun BUG();
1076*4882a593Smuzhiyun case 1: /* FSUB */
1077*4882a593Smuzhiyun switch (fmt) {
1078*4882a593Smuzhiyun case 0:
1079*4882a593Smuzhiyun return(sgl_fsub(&fpregs[r1],&fpregs[r2],
1080*4882a593Smuzhiyun &fpregs[t],status));
1081*4882a593Smuzhiyun case 1:
1082*4882a593Smuzhiyun return(dbl_fsub(&fpregs[r1],&fpregs[r2],
1083*4882a593Smuzhiyun &fpregs[t],status));
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun BUG();
1086*4882a593Smuzhiyun case 2: /* FMPY or XMPYU */
1087*4882a593Smuzhiyun /*
1088*4882a593Smuzhiyun * check for integer multiply (x bit set)
1089*4882a593Smuzhiyun */
1090*4882a593Smuzhiyun if (extru(ir,fpxpos,1)) {
1091*4882a593Smuzhiyun /*
1092*4882a593Smuzhiyun * emulate XMPYU
1093*4882a593Smuzhiyun */
1094*4882a593Smuzhiyun switch (fmt) {
1095*4882a593Smuzhiyun case 0:
1096*4882a593Smuzhiyun /*
1097*4882a593Smuzhiyun * bad instruction if t specifies
1098*4882a593Smuzhiyun * the right half of a register
1099*4882a593Smuzhiyun */
1100*4882a593Smuzhiyun if (t & 1)
1101*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
1102*4882a593Smuzhiyun BUG();
1103*4882a593Smuzhiyun /* unsupported
1104*4882a593Smuzhiyun * impyu(&fpregs[r1],&fpregs[r2],
1105*4882a593Smuzhiyun * &fpregs[t]);
1106*4882a593Smuzhiyun */
1107*4882a593Smuzhiyun return(NOEXCEPTION);
1108*4882a593Smuzhiyun case 1:
1109*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun else { /* FMPY */
1113*4882a593Smuzhiyun switch (fmt) {
1114*4882a593Smuzhiyun case 0:
1115*4882a593Smuzhiyun return(sgl_fmpy(&fpregs[r1],
1116*4882a593Smuzhiyun &fpregs[r2],&fpregs[t],status));
1117*4882a593Smuzhiyun case 1:
1118*4882a593Smuzhiyun return(dbl_fmpy(&fpregs[r1],
1119*4882a593Smuzhiyun &fpregs[r2],&fpregs[t],status));
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun BUG();
1123*4882a593Smuzhiyun case 3: /* FDIV */
1124*4882a593Smuzhiyun switch (fmt) {
1125*4882a593Smuzhiyun case 0:
1126*4882a593Smuzhiyun return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
1127*4882a593Smuzhiyun &fpregs[t],status));
1128*4882a593Smuzhiyun case 1:
1129*4882a593Smuzhiyun return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
1130*4882a593Smuzhiyun &fpregs[t],status));
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun BUG();
1133*4882a593Smuzhiyun case 4: /* FREM */
1134*4882a593Smuzhiyun switch (fmt) {
1135*4882a593Smuzhiyun case 0:
1136*4882a593Smuzhiyun return(sgl_frem(&fpregs[r1],&fpregs[r2],
1137*4882a593Smuzhiyun &fpregs[t],status));
1138*4882a593Smuzhiyun case 1:
1139*4882a593Smuzhiyun return(dbl_frem(&fpregs[r1],&fpregs[r2],
1140*4882a593Smuzhiyun &fpregs[t],status));
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun } /* end of class 3 switch */
1143*4882a593Smuzhiyun } /* end of switch(class) */
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun /* If we get here, something is really wrong! */
1146*4882a593Smuzhiyun return(MAJOR_0E_EXCP);
1147*4882a593Smuzhiyun }
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun /*
1151*4882a593Smuzhiyun * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
1152*4882a593Smuzhiyun */
1153*4882a593Smuzhiyun static u_int
decode_06(ir,fpregs)1154*4882a593Smuzhiyun decode_06(ir,fpregs)
1155*4882a593Smuzhiyun u_int ir;
1156*4882a593Smuzhiyun u_int fpregs[];
1157*4882a593Smuzhiyun {
1158*4882a593Smuzhiyun u_int rm1, rm2, tm, ra, ta; /* operands */
1159*4882a593Smuzhiyun u_int fmt;
1160*4882a593Smuzhiyun u_int error = 0;
1161*4882a593Smuzhiyun u_int status;
1162*4882a593Smuzhiyun u_int fpu_type_flags;
1163*4882a593Smuzhiyun union {
1164*4882a593Smuzhiyun double dbl;
1165*4882a593Smuzhiyun float flt;
1166*4882a593Smuzhiyun struct { u_int i1; u_int i2; } ints;
1167*4882a593Smuzhiyun } mtmp, atmp;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun status = fpregs[0]; /* use a local copy of status reg */
1171*4882a593Smuzhiyun fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
1172*4882a593Smuzhiyun fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1173*4882a593Smuzhiyun if (fmt == 0) { /* DBL */
1174*4882a593Smuzhiyun rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1175*4882a593Smuzhiyun if (rm1 == 0)
1176*4882a593Smuzhiyun rm1 = fpzeroreg;
1177*4882a593Smuzhiyun rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1178*4882a593Smuzhiyun if (rm2 == 0)
1179*4882a593Smuzhiyun rm2 = fpzeroreg;
1180*4882a593Smuzhiyun tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1181*4882a593Smuzhiyun if (tm == 0)
1182*4882a593Smuzhiyun return(MAJOR_06_EXCP);
1183*4882a593Smuzhiyun ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1184*4882a593Smuzhiyun ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1185*4882a593Smuzhiyun if (ta == 0)
1186*4882a593Smuzhiyun return(MAJOR_06_EXCP);
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun if (ra == 0) {
1191*4882a593Smuzhiyun /* special case FMPYCFXT, see sgl case below */
1192*4882a593Smuzhiyun if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
1193*4882a593Smuzhiyun &mtmp.ints.i1,&status))
1194*4882a593Smuzhiyun error = 1;
1195*4882a593Smuzhiyun if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
1196*4882a593Smuzhiyun &atmp.ints.i1,&atmp.ints.i1,&status))
1197*4882a593Smuzhiyun error = 1;
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun else {
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1202*4882a593Smuzhiyun &status))
1203*4882a593Smuzhiyun error = 1;
1204*4882a593Smuzhiyun if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1205*4882a593Smuzhiyun &status))
1206*4882a593Smuzhiyun error = 1;
1207*4882a593Smuzhiyun }
1208*4882a593Smuzhiyun }
1209*4882a593Smuzhiyun
1210*4882a593Smuzhiyun else
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun {
1213*4882a593Smuzhiyun if (ra == 0)
1214*4882a593Smuzhiyun ra = fpzeroreg;
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1217*4882a593Smuzhiyun &status))
1218*4882a593Smuzhiyun error = 1;
1219*4882a593Smuzhiyun if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1220*4882a593Smuzhiyun &status))
1221*4882a593Smuzhiyun error = 1;
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun }
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun if (error)
1226*4882a593Smuzhiyun return(MAJOR_06_EXCP);
1227*4882a593Smuzhiyun else {
1228*4882a593Smuzhiyun /* copy results */
1229*4882a593Smuzhiyun fpregs[tm] = mtmp.ints.i1;
1230*4882a593Smuzhiyun fpregs[tm+1] = mtmp.ints.i2;
1231*4882a593Smuzhiyun fpregs[ta] = atmp.ints.i1;
1232*4882a593Smuzhiyun fpregs[ta+1] = atmp.ints.i2;
1233*4882a593Smuzhiyun fpregs[0] = status;
1234*4882a593Smuzhiyun return(NOEXCEPTION);
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun }
1237*4882a593Smuzhiyun else { /* SGL */
1238*4882a593Smuzhiyun /*
1239*4882a593Smuzhiyun * calculate offsets for single precision numbers
1240*4882a593Smuzhiyun * See table 6-14 in PA-89 architecture for mapping
1241*4882a593Smuzhiyun */
1242*4882a593Smuzhiyun rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1243*4882a593Smuzhiyun rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1246*4882a593Smuzhiyun rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1249*4882a593Smuzhiyun tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1250*4882a593Smuzhiyun
1251*4882a593Smuzhiyun ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1252*4882a593Smuzhiyun ra |= extru(ir,fprapos-4,1); /* add right word offset */
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1255*4882a593Smuzhiyun ta |= extru(ir,fptapos-4,1); /* add right word offset */
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
1258*4882a593Smuzhiyun /* special case FMPYCFXT (really 0)
1259*4882a593Smuzhiyun * This instruction is only present on the Timex and
1260*4882a593Smuzhiyun * Rolex fpu's in so if it is the special case and
1261*4882a593Smuzhiyun * one of these fpu's we run the FMPYCFXT instruction
1262*4882a593Smuzhiyun */
1263*4882a593Smuzhiyun if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1264*4882a593Smuzhiyun &status))
1265*4882a593Smuzhiyun error = 1;
1266*4882a593Smuzhiyun if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
1267*4882a593Smuzhiyun &atmp.ints.i1,&status))
1268*4882a593Smuzhiyun error = 1;
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun else {
1271*4882a593Smuzhiyun if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1272*4882a593Smuzhiyun &status))
1273*4882a593Smuzhiyun error = 1;
1274*4882a593Smuzhiyun if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1275*4882a593Smuzhiyun &status))
1276*4882a593Smuzhiyun error = 1;
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun if (error)
1279*4882a593Smuzhiyun return(MAJOR_06_EXCP);
1280*4882a593Smuzhiyun else {
1281*4882a593Smuzhiyun /* copy results */
1282*4882a593Smuzhiyun fpregs[tm] = mtmp.ints.i1;
1283*4882a593Smuzhiyun fpregs[ta] = atmp.ints.i1;
1284*4882a593Smuzhiyun fpregs[0] = status;
1285*4882a593Smuzhiyun return(NOEXCEPTION);
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun }
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun /*
1291*4882a593Smuzhiyun * routine to decode the 26 (FMPYSUB) instruction
1292*4882a593Smuzhiyun */
1293*4882a593Smuzhiyun static u_int
decode_26(ir,fpregs)1294*4882a593Smuzhiyun decode_26(ir,fpregs)
1295*4882a593Smuzhiyun u_int ir;
1296*4882a593Smuzhiyun u_int fpregs[];
1297*4882a593Smuzhiyun {
1298*4882a593Smuzhiyun u_int rm1, rm2, tm, ra, ta; /* operands */
1299*4882a593Smuzhiyun u_int fmt;
1300*4882a593Smuzhiyun u_int error = 0;
1301*4882a593Smuzhiyun u_int status;
1302*4882a593Smuzhiyun union {
1303*4882a593Smuzhiyun double dbl;
1304*4882a593Smuzhiyun float flt;
1305*4882a593Smuzhiyun struct { u_int i1; u_int i2; } ints;
1306*4882a593Smuzhiyun } mtmp, atmp;
1307*4882a593Smuzhiyun
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun status = fpregs[0];
1310*4882a593Smuzhiyun fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1311*4882a593Smuzhiyun if (fmt == 0) { /* DBL */
1312*4882a593Smuzhiyun rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1313*4882a593Smuzhiyun if (rm1 == 0)
1314*4882a593Smuzhiyun rm1 = fpzeroreg;
1315*4882a593Smuzhiyun rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1316*4882a593Smuzhiyun if (rm2 == 0)
1317*4882a593Smuzhiyun rm2 = fpzeroreg;
1318*4882a593Smuzhiyun tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1319*4882a593Smuzhiyun if (tm == 0)
1320*4882a593Smuzhiyun return(MAJOR_26_EXCP);
1321*4882a593Smuzhiyun ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1322*4882a593Smuzhiyun if (ra == 0)
1323*4882a593Smuzhiyun return(MAJOR_26_EXCP);
1324*4882a593Smuzhiyun ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1325*4882a593Smuzhiyun if (ta == 0)
1326*4882a593Smuzhiyun return(MAJOR_26_EXCP);
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1329*4882a593Smuzhiyun error = 1;
1330*4882a593Smuzhiyun if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1331*4882a593Smuzhiyun error = 1;
1332*4882a593Smuzhiyun if (error)
1333*4882a593Smuzhiyun return(MAJOR_26_EXCP);
1334*4882a593Smuzhiyun else {
1335*4882a593Smuzhiyun /* copy results */
1336*4882a593Smuzhiyun fpregs[tm] = mtmp.ints.i1;
1337*4882a593Smuzhiyun fpregs[tm+1] = mtmp.ints.i2;
1338*4882a593Smuzhiyun fpregs[ta] = atmp.ints.i1;
1339*4882a593Smuzhiyun fpregs[ta+1] = atmp.ints.i2;
1340*4882a593Smuzhiyun fpregs[0] = status;
1341*4882a593Smuzhiyun return(NOEXCEPTION);
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun else { /* SGL */
1345*4882a593Smuzhiyun /*
1346*4882a593Smuzhiyun * calculate offsets for single precision numbers
1347*4882a593Smuzhiyun * See table 6-14 in PA-89 architecture for mapping
1348*4882a593Smuzhiyun */
1349*4882a593Smuzhiyun rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1350*4882a593Smuzhiyun rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1351*4882a593Smuzhiyun
1352*4882a593Smuzhiyun rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1353*4882a593Smuzhiyun rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1356*4882a593Smuzhiyun tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1359*4882a593Smuzhiyun ra |= extru(ir,fprapos-4,1); /* add right word offset */
1360*4882a593Smuzhiyun
1361*4882a593Smuzhiyun ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1362*4882a593Smuzhiyun ta |= extru(ir,fptapos-4,1); /* add right word offset */
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1365*4882a593Smuzhiyun error = 1;
1366*4882a593Smuzhiyun if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1367*4882a593Smuzhiyun error = 1;
1368*4882a593Smuzhiyun if (error)
1369*4882a593Smuzhiyun return(MAJOR_26_EXCP);
1370*4882a593Smuzhiyun else {
1371*4882a593Smuzhiyun /* copy results */
1372*4882a593Smuzhiyun fpregs[tm] = mtmp.ints.i1;
1373*4882a593Smuzhiyun fpregs[ta] = atmp.ints.i1;
1374*4882a593Smuzhiyun fpregs[0] = status;
1375*4882a593Smuzhiyun return(NOEXCEPTION);
1376*4882a593Smuzhiyun }
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun }
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun /*
1382*4882a593Smuzhiyun * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
1383*4882a593Smuzhiyun */
1384*4882a593Smuzhiyun static u_int
decode_2e(ir,fpregs)1385*4882a593Smuzhiyun decode_2e(ir,fpregs)
1386*4882a593Smuzhiyun u_int ir;
1387*4882a593Smuzhiyun u_int fpregs[];
1388*4882a593Smuzhiyun {
1389*4882a593Smuzhiyun u_int rm1, rm2, ra, t; /* operands */
1390*4882a593Smuzhiyun u_int fmt;
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
1393*4882a593Smuzhiyun if (fmt == DBL) { /* DBL */
1394*4882a593Smuzhiyun rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
1395*4882a593Smuzhiyun if (rm1 == 0)
1396*4882a593Smuzhiyun rm1 = fpzeroreg;
1397*4882a593Smuzhiyun rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
1398*4882a593Smuzhiyun if (rm2 == 0)
1399*4882a593Smuzhiyun rm2 = fpzeroreg;
1400*4882a593Smuzhiyun ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
1401*4882a593Smuzhiyun sizeof(double)/sizeof(u_int);
1402*4882a593Smuzhiyun if (ra == 0)
1403*4882a593Smuzhiyun ra = fpzeroreg;
1404*4882a593Smuzhiyun t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
1405*4882a593Smuzhiyun if (t == 0)
1406*4882a593Smuzhiyun return(MAJOR_2E_EXCP);
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1409*4882a593Smuzhiyun return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1410*4882a593Smuzhiyun &fpregs[ra], &fpregs[0], &fpregs[t]));
1411*4882a593Smuzhiyun } else {
1412*4882a593Smuzhiyun return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1413*4882a593Smuzhiyun &fpregs[ra], &fpregs[0], &fpregs[t]));
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun } /* end DBL */
1416*4882a593Smuzhiyun else { /* SGL */
1417*4882a593Smuzhiyun rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
1418*4882a593Smuzhiyun if (rm1 == 0)
1419*4882a593Smuzhiyun rm1 = fpzeroreg;
1420*4882a593Smuzhiyun rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
1421*4882a593Smuzhiyun if (rm2 == 0)
1422*4882a593Smuzhiyun rm2 = fpzeroreg;
1423*4882a593Smuzhiyun ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
1424*4882a593Smuzhiyun if (ra == 0)
1425*4882a593Smuzhiyun ra = fpzeroreg;
1426*4882a593Smuzhiyun t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
1427*4882a593Smuzhiyun if (t == 0)
1428*4882a593Smuzhiyun return(MAJOR_2E_EXCP);
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1431*4882a593Smuzhiyun return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1432*4882a593Smuzhiyun &fpregs[ra], &fpregs[0], &fpregs[t]));
1433*4882a593Smuzhiyun } else {
1434*4882a593Smuzhiyun return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1435*4882a593Smuzhiyun &fpregs[ra], &fpregs[0], &fpregs[t]));
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun } /* end SGL */
1438*4882a593Smuzhiyun }
1439*4882a593Smuzhiyun
1440*4882a593Smuzhiyun /*
1441*4882a593Smuzhiyun * update_status_cbit
1442*4882a593Smuzhiyun *
1443*4882a593Smuzhiyun * This routine returns the correct FP status register value in
1444*4882a593Smuzhiyun * *status, based on the C-bit & V-bit returned by the FCMP
1445*4882a593Smuzhiyun * emulation routine in new_status. The architecture type
1446*4882a593Smuzhiyun * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
1447*4882a593Smuzhiyun * and the architecture type are used to determine what flavor
1448*4882a593Smuzhiyun * of FCMP is being emulated.
1449*4882a593Smuzhiyun */
1450*4882a593Smuzhiyun static void
update_status_cbit(status,new_status,fpu_type,y_field)1451*4882a593Smuzhiyun update_status_cbit(status, new_status, fpu_type, y_field)
1452*4882a593Smuzhiyun u_int *status, new_status;
1453*4882a593Smuzhiyun u_int fpu_type;
1454*4882a593Smuzhiyun u_int y_field;
1455*4882a593Smuzhiyun {
1456*4882a593Smuzhiyun /*
1457*4882a593Smuzhiyun * For PA89 FPU's which implement the Compare Queue and
1458*4882a593Smuzhiyun * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
1459*4882a593Smuzhiyun * otherwise update the specified bit in the Compare Array.
1460*4882a593Smuzhiyun * Note that the y-field will always be 0 for non-PA2.0 FPU's.
1461*4882a593Smuzhiyun */
1462*4882a593Smuzhiyun if ((fpu_type & TIMEX_EXTEN_FLAG) ||
1463*4882a593Smuzhiyun (fpu_type & ROLEX_EXTEN_FLAG) ||
1464*4882a593Smuzhiyun (fpu_type & PA2_0_FPU_FLAG)) {
1465*4882a593Smuzhiyun if (y_field == 0) {
1466*4882a593Smuzhiyun *status = ((*status & 0x04000000) >> 5) | /* old Cbit */
1467*4882a593Smuzhiyun ((*status & 0x003ff000) >> 1) | /* old CQ */
1468*4882a593Smuzhiyun (new_status & 0xffc007ff); /* all other bits*/
1469*4882a593Smuzhiyun } else {
1470*4882a593Smuzhiyun *status = (*status & 0x04000000) | /* old Cbit */
1471*4882a593Smuzhiyun ((new_status & 0x04000000) >> (y_field+4)) |
1472*4882a593Smuzhiyun (new_status & ~0x04000000 & /* other bits */
1473*4882a593Smuzhiyun ~(0x04000000 >> (y_field+4)));
1474*4882a593Smuzhiyun }
1475*4882a593Smuzhiyun }
1476*4882a593Smuzhiyun /* if PA83, just update the C-bit */
1477*4882a593Smuzhiyun else {
1478*4882a593Smuzhiyun *status = new_status;
1479*4882a593Smuzhiyun }
1480*4882a593Smuzhiyun }
1481