1660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Floating-point emulation code
61da177e4SLinus Torvalds * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds * BEGIN_DESC
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * File:
121da177e4SLinus Torvalds * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * Purpose:
151da177e4SLinus Torvalds * <<please update with a synopsis of the functionality provided by this file>>
161da177e4SLinus Torvalds *
171da177e4SLinus Torvalds * External Interfaces:
181da177e4SLinus Torvalds * <<the following list was autogenerated, please review>>
191da177e4SLinus Torvalds * emfpudispatch(ir, dummy1, dummy2, fpregs)
201da177e4SLinus Torvalds * fpudispatch(ir, excp_code, holder, fpregs)
211da177e4SLinus Torvalds *
221da177e4SLinus Torvalds * Internal Interfaces:
231da177e4SLinus Torvalds * <<the following list was autogenerated, please review>>
241da177e4SLinus Torvalds * static u_int decode_06(u_int, u_int *)
251da177e4SLinus Torvalds * static u_int decode_0c(u_int, u_int, u_int, u_int *)
261da177e4SLinus Torvalds * static u_int decode_0e(u_int, u_int, u_int, u_int *)
271da177e4SLinus Torvalds * static u_int decode_26(u_int, u_int *)
281da177e4SLinus Torvalds * static u_int decode_2e(u_int, u_int *)
291da177e4SLinus Torvalds * static void update_status_cbit(u_int *, u_int, u_int, u_int)
301da177e4SLinus Torvalds *
311da177e4SLinus Torvalds * Theory:
321da177e4SLinus Torvalds * <<please update with a overview of the operation of this file>>
331da177e4SLinus Torvalds *
341da177e4SLinus Torvalds * END_DESC
351da177e4SLinus Torvalds */
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds #define FPUDEBUG 0
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds #include "float.h"
4050af5eadSPaul Gortmaker #include <linux/bug.h>
411da177e4SLinus Torvalds #include <linux/kernel.h>
421da177e4SLinus Torvalds #include <asm/processor.h>
431da177e4SLinus Torvalds /* #include <sys/debug.h> */
441da177e4SLinus Torvalds /* #include <machine/sys/mdep_private.h> */
451da177e4SLinus Torvalds
461da177e4SLinus Torvalds #define COPR_INST 0x30000000
471da177e4SLinus Torvalds
481da177e4SLinus Torvalds /*
491da177e4SLinus Torvalds * definition of extru macro. If pos and len are constants, the compiler
501da177e4SLinus Torvalds * will generate an extru instruction when optimized
511da177e4SLinus Torvalds */
521da177e4SLinus Torvalds #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
531da177e4SLinus Torvalds /* definitions of bit field locations in the instruction */
541da177e4SLinus Torvalds #define fpmajorpos 5
551da177e4SLinus Torvalds #define fpr1pos 10
561da177e4SLinus Torvalds #define fpr2pos 15
571da177e4SLinus Torvalds #define fptpos 31
581da177e4SLinus Torvalds #define fpsubpos 18
591da177e4SLinus Torvalds #define fpclass1subpos 16
601da177e4SLinus Torvalds #define fpclasspos 22
611da177e4SLinus Torvalds #define fpfmtpos 20
621da177e4SLinus Torvalds #define fpdfpos 18
631da177e4SLinus Torvalds #define fpnulpos 26
641da177e4SLinus Torvalds /*
651da177e4SLinus Torvalds * the following are the extra bits for the 0E major op
661da177e4SLinus Torvalds */
671da177e4SLinus Torvalds #define fpxr1pos 24
681da177e4SLinus Torvalds #define fpxr2pos 19
691da177e4SLinus Torvalds #define fpxtpos 25
701da177e4SLinus Torvalds #define fpxpos 23
711da177e4SLinus Torvalds #define fp0efmtpos 20
721da177e4SLinus Torvalds /*
731da177e4SLinus Torvalds * the following are for the multi-ops
741da177e4SLinus Torvalds */
751da177e4SLinus Torvalds #define fprm1pos 10
761da177e4SLinus Torvalds #define fprm2pos 15
771da177e4SLinus Torvalds #define fptmpos 31
781da177e4SLinus Torvalds #define fprapos 25
791da177e4SLinus Torvalds #define fptapos 20
801da177e4SLinus Torvalds #define fpmultifmt 26
811da177e4SLinus Torvalds /*
821da177e4SLinus Torvalds * the following are for the fused FP instructions
831da177e4SLinus Torvalds */
841da177e4SLinus Torvalds /* fprm1pos 10 */
851da177e4SLinus Torvalds /* fprm2pos 15 */
861da177e4SLinus Torvalds #define fpraupos 18
871da177e4SLinus Torvalds #define fpxrm2pos 19
881da177e4SLinus Torvalds /* fpfmtpos 20 */
891da177e4SLinus Torvalds #define fpralpos 23
901da177e4SLinus Torvalds #define fpxrm1pos 24
911da177e4SLinus Torvalds /* fpxtpos 25 */
921da177e4SLinus Torvalds #define fpfusedsubop 26
931da177e4SLinus Torvalds /* fptpos 31 */
941da177e4SLinus Torvalds
951da177e4SLinus Torvalds /*
961da177e4SLinus Torvalds * offset to constant zero in the FP emulation registers
971da177e4SLinus Torvalds */
981da177e4SLinus Torvalds #define fpzeroreg (32*sizeof(double)/sizeof(u_int))
991da177e4SLinus Torvalds
1001da177e4SLinus Torvalds /*
1011da177e4SLinus Torvalds * extract the major opcode from the instruction
1021da177e4SLinus Torvalds */
1031da177e4SLinus Torvalds #define get_major(op) extru(op,fpmajorpos,6)
1041da177e4SLinus Torvalds /*
1051da177e4SLinus Torvalds * extract the two bit class field from the FP instruction. The class is at bit
1061da177e4SLinus Torvalds * positions 21-22
1071da177e4SLinus Torvalds */
1081da177e4SLinus Torvalds #define get_class(op) extru(op,fpclasspos,2)
1091da177e4SLinus Torvalds /*
1101da177e4SLinus Torvalds * extract the 3 bit subop field. For all but class 1 instructions, it is
1111da177e4SLinus Torvalds * located at bit positions 16-18
1121da177e4SLinus Torvalds */
1131da177e4SLinus Torvalds #define get_subop(op) extru(op,fpsubpos,3)
1141da177e4SLinus Torvalds /*
1151da177e4SLinus Torvalds * extract the 2 or 3 bit subop field from class 1 instructions. It is located
1161da177e4SLinus Torvalds * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
1171da177e4SLinus Torvalds */
1181da177e4SLinus Torvalds #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
1191da177e4SLinus Torvalds #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds /* definitions of unimplemented exceptions */
1221da177e4SLinus Torvalds #define MAJOR_0C_EXCP 0x09
1231da177e4SLinus Torvalds #define MAJOR_0E_EXCP 0x0b
1241da177e4SLinus Torvalds #define MAJOR_06_EXCP 0x03
1251da177e4SLinus Torvalds #define MAJOR_26_EXCP 0x23
1261da177e4SLinus Torvalds #define MAJOR_2E_EXCP 0x2b
1271da177e4SLinus Torvalds #define PA83_UNIMP_EXCP 0x01
1281da177e4SLinus Torvalds
1291da177e4SLinus Torvalds /*
1301da177e4SLinus Torvalds * Special Defines for TIMEX specific code
1311da177e4SLinus Torvalds */
1321da177e4SLinus Torvalds
1331da177e4SLinus Torvalds #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
1341da177e4SLinus Torvalds #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds * Static function definitions
1381da177e4SLinus Torvalds */
1391da177e4SLinus Torvalds #define _PROTOTYPES
1401da177e4SLinus Torvalds #if defined(_PROTOTYPES) || defined(_lint)
1411da177e4SLinus Torvalds static u_int decode_0c(u_int, u_int, u_int, u_int *);
1421da177e4SLinus Torvalds static u_int decode_0e(u_int, u_int, u_int, u_int *);
1431da177e4SLinus Torvalds static u_int decode_06(u_int, u_int *);
1441da177e4SLinus Torvalds static u_int decode_26(u_int, u_int *);
1451da177e4SLinus Torvalds static u_int decode_2e(u_int, u_int *);
1461da177e4SLinus Torvalds static void update_status_cbit(u_int *, u_int, u_int, u_int);
1471da177e4SLinus Torvalds #else /* !_PROTOTYPES&&!_lint */
1481da177e4SLinus Torvalds static u_int decode_0c();
1491da177e4SLinus Torvalds static u_int decode_0e();
1501da177e4SLinus Torvalds static u_int decode_06();
1511da177e4SLinus Torvalds static u_int decode_26();
1521da177e4SLinus Torvalds static u_int decode_2e();
1531da177e4SLinus Torvalds static void update_status_cbit();
1541da177e4SLinus Torvalds #endif /* _PROTOTYPES&&!_lint */
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds #define VASSERT(x)
1571da177e4SLinus Torvalds
parisc_linux_get_fpu_type(u_int fpregs[])1581da177e4SLinus Torvalds static void parisc_linux_get_fpu_type(u_int fpregs[])
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds /* on pa-linux the fpu type is not filled in by the
1611da177e4SLinus Torvalds * caller; it is constructed here
1621da177e4SLinus Torvalds */
1631da177e4SLinus Torvalds if (boot_cpu_data.cpu_type == pcxs)
1641da177e4SLinus Torvalds fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
1651da177e4SLinus Torvalds else if (boot_cpu_data.cpu_type == pcxt ||
1661da177e4SLinus Torvalds boot_cpu_data.cpu_type == pcxt_)
1671da177e4SLinus Torvalds fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
1681da177e4SLinus Torvalds else if (boot_cpu_data.cpu_type >= pcxu)
1691da177e4SLinus Torvalds fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
1701da177e4SLinus Torvalds }
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds /*
1731da177e4SLinus Torvalds * this routine will decode the excepting floating point instruction and
17490afe0a9SAndrea Gelmini * call the appropriate emulation routine.
1751da177e4SLinus Torvalds * It is called by decode_fpu with the following parameters:
1761da177e4SLinus Torvalds * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
1771da177e4SLinus Torvalds * where current_ir is the instruction to be emulated,
1781da177e4SLinus Torvalds * unimplemented_code is the exception_code that the hardware generated
1791da177e4SLinus Torvalds * and &Fpu_register is the address of emulated FP reg 0.
1801da177e4SLinus Torvalds */
1811da177e4SLinus Torvalds u_int
fpudispatch(u_int ir,u_int excp_code,u_int holder,u_int fpregs[])1821da177e4SLinus Torvalds fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
1831da177e4SLinus Torvalds {
1841da177e4SLinus Torvalds u_int class, subop;
1851da177e4SLinus Torvalds u_int fpu_type_flags;
1861da177e4SLinus Torvalds
1871da177e4SLinus Torvalds /* All FP emulation code assumes that ints are 4-bytes in length */
1881da177e4SLinus Torvalds VASSERT(sizeof(int) == 4);
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds parisc_linux_get_fpu_type(fpregs);
1911da177e4SLinus Torvalds
1921da177e4SLinus Torvalds fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
1931da177e4SLinus Torvalds
1941da177e4SLinus Torvalds class = get_class(ir);
1951da177e4SLinus Torvalds if (class == 1) {
1961da177e4SLinus Torvalds if (fpu_type_flags & PA2_0_FPU_FLAG)
1971da177e4SLinus Torvalds subop = get_subop1_PA2_0(ir);
1981da177e4SLinus Torvalds else
1991da177e4SLinus Torvalds subop = get_subop1_PA1_1(ir);
2001da177e4SLinus Torvalds }
2011da177e4SLinus Torvalds else
2021da177e4SLinus Torvalds subop = get_subop(ir);
2031da177e4SLinus Torvalds
2041da177e4SLinus Torvalds if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
2051da177e4SLinus Torvalds
2061da177e4SLinus Torvalds switch (excp_code) {
2071da177e4SLinus Torvalds case MAJOR_0C_EXCP:
2081da177e4SLinus Torvalds case PA83_UNIMP_EXCP:
2091da177e4SLinus Torvalds return(decode_0c(ir,class,subop,fpregs));
2101da177e4SLinus Torvalds case MAJOR_0E_EXCP:
2111da177e4SLinus Torvalds return(decode_0e(ir,class,subop,fpregs));
2121da177e4SLinus Torvalds case MAJOR_06_EXCP:
2131da177e4SLinus Torvalds return(decode_06(ir,fpregs));
2141da177e4SLinus Torvalds case MAJOR_26_EXCP:
2151da177e4SLinus Torvalds return(decode_26(ir,fpregs));
2161da177e4SLinus Torvalds case MAJOR_2E_EXCP:
2171da177e4SLinus Torvalds return(decode_2e(ir,fpregs));
2181da177e4SLinus Torvalds default:
2191da177e4SLinus Torvalds /* "crashme Night Gallery painting nr 2. (asm_crash.s).
2201da177e4SLinus Torvalds * This was fixed for multi-user kernels, but
2211da177e4SLinus Torvalds * workstation kernels had a panic here. This allowed
2221da177e4SLinus Torvalds * any arbitrary user to panic the kernel by executing
2231da177e4SLinus Torvalds * setting the FP exception registers to strange values
2241da177e4SLinus Torvalds * and generating an emulation trap. The emulation and
2251da177e4SLinus Torvalds * exception code must never be able to panic the
2261da177e4SLinus Torvalds * kernel.
2271da177e4SLinus Torvalds */
2281da177e4SLinus Torvalds return(UNIMPLEMENTEDEXCEPTION);
2291da177e4SLinus Torvalds }
2301da177e4SLinus Torvalds }
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds /*
2331da177e4SLinus Torvalds * this routine is called by $emulation_trap to emulate a coprocessor
2341da177e4SLinus Torvalds * instruction if one doesn't exist
2351da177e4SLinus Torvalds */
2361da177e4SLinus Torvalds u_int
emfpudispatch(u_int ir,u_int dummy1,u_int dummy2,u_int fpregs[])2371da177e4SLinus Torvalds emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
2381da177e4SLinus Torvalds {
2391da177e4SLinus Torvalds u_int class, subop, major;
2401da177e4SLinus Torvalds u_int fpu_type_flags;
2411da177e4SLinus Torvalds
2421da177e4SLinus Torvalds /* All FP emulation code assumes that ints are 4-bytes in length */
2431da177e4SLinus Torvalds VASSERT(sizeof(int) == 4);
2441da177e4SLinus Torvalds
2451da177e4SLinus Torvalds fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
2461da177e4SLinus Torvalds
2471da177e4SLinus Torvalds major = get_major(ir);
2481da177e4SLinus Torvalds class = get_class(ir);
2491da177e4SLinus Torvalds if (class == 1) {
2501da177e4SLinus Torvalds if (fpu_type_flags & PA2_0_FPU_FLAG)
2511da177e4SLinus Torvalds subop = get_subop1_PA2_0(ir);
2521da177e4SLinus Torvalds else
2531da177e4SLinus Torvalds subop = get_subop1_PA1_1(ir);
2541da177e4SLinus Torvalds }
2551da177e4SLinus Torvalds else
2561da177e4SLinus Torvalds subop = get_subop(ir);
2571da177e4SLinus Torvalds switch (major) {
2581da177e4SLinus Torvalds case 0x0C:
2591da177e4SLinus Torvalds return(decode_0c(ir,class,subop,fpregs));
2601da177e4SLinus Torvalds case 0x0E:
2611da177e4SLinus Torvalds return(decode_0e(ir,class,subop,fpregs));
2621da177e4SLinus Torvalds case 0x06:
2631da177e4SLinus Torvalds return(decode_06(ir,fpregs));
2641da177e4SLinus Torvalds case 0x26:
2651da177e4SLinus Torvalds return(decode_26(ir,fpregs));
2661da177e4SLinus Torvalds case 0x2E:
2671da177e4SLinus Torvalds return(decode_2e(ir,fpregs));
2681da177e4SLinus Torvalds default:
2691da177e4SLinus Torvalds return(PA83_UNIMP_EXCP);
2701da177e4SLinus Torvalds }
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds static u_int
decode_0c(u_int ir,u_int class,u_int subop,u_int fpregs[])2751da177e4SLinus Torvalds decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
2761da177e4SLinus Torvalds {
2771da177e4SLinus Torvalds u_int r1,r2,t; /* operand register offsets */
2781da177e4SLinus Torvalds u_int fmt; /* also sf for class 1 conversions */
2791da177e4SLinus Torvalds u_int df; /* for class 1 conversions */
2801da177e4SLinus Torvalds u_int *status;
2811da177e4SLinus Torvalds u_int retval, local_status;
2821da177e4SLinus Torvalds u_int fpu_type_flags;
2831da177e4SLinus Torvalds
2841da177e4SLinus Torvalds if (ir == COPR_INST) {
2851da177e4SLinus Torvalds fpregs[0] = EMULATION_VERSION << 11;
2861da177e4SLinus Torvalds return(NOEXCEPTION);
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds status = &fpregs[0]; /* fp status register */
2891da177e4SLinus Torvalds local_status = fpregs[0]; /* and local copy */
2901da177e4SLinus Torvalds r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
2911da177e4SLinus Torvalds if (r1 == 0) /* map fr0 source to constant zero */
2921da177e4SLinus Torvalds r1 = fpzeroreg;
2931da177e4SLinus Torvalds t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
2941da177e4SLinus Torvalds if (t == 0 && class != 2) /* don't allow fr0 as a dest */
2951da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
2961da177e4SLinus Torvalds fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
2971da177e4SLinus Torvalds
2981da177e4SLinus Torvalds switch (class) {
2991da177e4SLinus Torvalds case 0:
3001da177e4SLinus Torvalds switch (subop) {
3011da177e4SLinus Torvalds case 0: /* COPR 0,0 emulated above*/
3021da177e4SLinus Torvalds case 1:
3031da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3041da177e4SLinus Torvalds case 2: /* FCPY */
3051da177e4SLinus Torvalds switch (fmt) {
3061da177e4SLinus Torvalds case 2: /* illegal */
3071da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3081da177e4SLinus Torvalds case 3: /* quad */
3091da177e4SLinus Torvalds t &= ~3; /* force to even reg #s */
3101da177e4SLinus Torvalds r1 &= ~3;
3111da177e4SLinus Torvalds fpregs[t+3] = fpregs[r1+3];
3121da177e4SLinus Torvalds fpregs[t+2] = fpregs[r1+2];
313*6f1fce59SHelge Deller fallthrough;
3141da177e4SLinus Torvalds case 1: /* double */
3151da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
316*6f1fce59SHelge Deller fallthrough;
3171da177e4SLinus Torvalds case 0: /* single */
3181da177e4SLinus Torvalds fpregs[t] = fpregs[r1];
3191da177e4SLinus Torvalds return(NOEXCEPTION);
3201da177e4SLinus Torvalds }
321*6f1fce59SHelge Deller BUG();
3221da177e4SLinus Torvalds case 3: /* FABS */
3231da177e4SLinus Torvalds switch (fmt) {
3241da177e4SLinus Torvalds case 2: /* illegal */
3251da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3261da177e4SLinus Torvalds case 3: /* quad */
3271da177e4SLinus Torvalds t &= ~3; /* force to even reg #s */
3281da177e4SLinus Torvalds r1 &= ~3;
3291da177e4SLinus Torvalds fpregs[t+3] = fpregs[r1+3];
3301da177e4SLinus Torvalds fpregs[t+2] = fpregs[r1+2];
331*6f1fce59SHelge Deller fallthrough;
3321da177e4SLinus Torvalds case 1: /* double */
3331da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
334*6f1fce59SHelge Deller fallthrough;
3351da177e4SLinus Torvalds case 0: /* single */
3361da177e4SLinus Torvalds /* copy and clear sign bit */
3371da177e4SLinus Torvalds fpregs[t] = fpregs[r1] & 0x7fffffff;
3381da177e4SLinus Torvalds return(NOEXCEPTION);
3391da177e4SLinus Torvalds }
340*6f1fce59SHelge Deller BUG();
3411da177e4SLinus Torvalds case 6: /* FNEG */
3421da177e4SLinus Torvalds switch (fmt) {
3431da177e4SLinus Torvalds case 2: /* illegal */
3441da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3451da177e4SLinus Torvalds case 3: /* quad */
3461da177e4SLinus Torvalds t &= ~3; /* force to even reg #s */
3471da177e4SLinus Torvalds r1 &= ~3;
3481da177e4SLinus Torvalds fpregs[t+3] = fpregs[r1+3];
3491da177e4SLinus Torvalds fpregs[t+2] = fpregs[r1+2];
350*6f1fce59SHelge Deller fallthrough;
3511da177e4SLinus Torvalds case 1: /* double */
3521da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
353*6f1fce59SHelge Deller fallthrough;
3541da177e4SLinus Torvalds case 0: /* single */
3551da177e4SLinus Torvalds /* copy and invert sign bit */
3561da177e4SLinus Torvalds fpregs[t] = fpregs[r1] ^ 0x80000000;
3571da177e4SLinus Torvalds return(NOEXCEPTION);
3581da177e4SLinus Torvalds }
359*6f1fce59SHelge Deller BUG();
3601da177e4SLinus Torvalds case 7: /* FNEGABS */
3611da177e4SLinus Torvalds switch (fmt) {
3621da177e4SLinus Torvalds case 2: /* illegal */
3631da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3641da177e4SLinus Torvalds case 3: /* quad */
3651da177e4SLinus Torvalds t &= ~3; /* force to even reg #s */
3661da177e4SLinus Torvalds r1 &= ~3;
3671da177e4SLinus Torvalds fpregs[t+3] = fpregs[r1+3];
3681da177e4SLinus Torvalds fpregs[t+2] = fpregs[r1+2];
369*6f1fce59SHelge Deller fallthrough;
3701da177e4SLinus Torvalds case 1: /* double */
3711da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
372*6f1fce59SHelge Deller fallthrough;
3731da177e4SLinus Torvalds case 0: /* single */
3741da177e4SLinus Torvalds /* copy and set sign bit */
3751da177e4SLinus Torvalds fpregs[t] = fpregs[r1] | 0x80000000;
3761da177e4SLinus Torvalds return(NOEXCEPTION);
3771da177e4SLinus Torvalds }
378*6f1fce59SHelge Deller BUG();
3791da177e4SLinus Torvalds case 4: /* FSQRT */
3801da177e4SLinus Torvalds switch (fmt) {
3811da177e4SLinus Torvalds case 0:
3821da177e4SLinus Torvalds return(sgl_fsqrt(&fpregs[r1],0,
3831da177e4SLinus Torvalds &fpregs[t],status));
3841da177e4SLinus Torvalds case 1:
3851da177e4SLinus Torvalds return(dbl_fsqrt(&fpregs[r1],0,
3861da177e4SLinus Torvalds &fpregs[t],status));
3871da177e4SLinus Torvalds case 2:
3881da177e4SLinus Torvalds case 3: /* quad not implemented */
3891da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
3901da177e4SLinus Torvalds }
391*6f1fce59SHelge Deller BUG();
3921da177e4SLinus Torvalds case 5: /* FRND */
3931da177e4SLinus Torvalds switch (fmt) {
3941da177e4SLinus Torvalds case 0:
3951da177e4SLinus Torvalds return(sgl_frnd(&fpregs[r1],0,
3961da177e4SLinus Torvalds &fpregs[t],status));
3971da177e4SLinus Torvalds case 1:
3981da177e4SLinus Torvalds return(dbl_frnd(&fpregs[r1],0,
3991da177e4SLinus Torvalds &fpregs[t],status));
4001da177e4SLinus Torvalds case 2:
4011da177e4SLinus Torvalds case 3: /* quad not implemented */
4021da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
4031da177e4SLinus Torvalds }
4041da177e4SLinus Torvalds } /* end of switch (subop) */
405*6f1fce59SHelge Deller BUG();
4061da177e4SLinus Torvalds case 1: /* class 1 */
4071da177e4SLinus Torvalds df = extru(ir,fpdfpos,2); /* get dest format */
4081da177e4SLinus Torvalds if ((df & 2) || (fmt & 2)) {
4091da177e4SLinus Torvalds /*
4101da177e4SLinus Torvalds * fmt's 2 and 3 are illegal of not implemented
4111da177e4SLinus Torvalds * quad conversions
4121da177e4SLinus Torvalds */
4131da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
4141da177e4SLinus Torvalds }
4151da177e4SLinus Torvalds /*
4161da177e4SLinus Torvalds * encode source and dest formats into 2 bits.
4171da177e4SLinus Torvalds * high bit is source, low bit is dest.
4181da177e4SLinus Torvalds * bit = 1 --> double precision
4191da177e4SLinus Torvalds */
4201da177e4SLinus Torvalds fmt = (fmt << 1) | df;
4211da177e4SLinus Torvalds switch (subop) {
4221da177e4SLinus Torvalds case 0: /* FCNVFF */
4231da177e4SLinus Torvalds switch(fmt) {
4241da177e4SLinus Torvalds case 0: /* sgl/sgl */
4251da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
4261da177e4SLinus Torvalds case 1: /* sgl/dbl */
4271da177e4SLinus Torvalds return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
4281da177e4SLinus Torvalds &fpregs[t],status));
4291da177e4SLinus Torvalds case 2: /* dbl/sgl */
4301da177e4SLinus Torvalds return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
4311da177e4SLinus Torvalds &fpregs[t],status));
4321da177e4SLinus Torvalds case 3: /* dbl/dbl */
4331da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
4341da177e4SLinus Torvalds }
435*6f1fce59SHelge Deller BUG();
4361da177e4SLinus Torvalds case 1: /* FCNVXF */
4371da177e4SLinus Torvalds switch(fmt) {
4381da177e4SLinus Torvalds case 0: /* sgl/sgl */
4391da177e4SLinus Torvalds return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
4401da177e4SLinus Torvalds &fpregs[t],status));
4411da177e4SLinus Torvalds case 1: /* sgl/dbl */
4421da177e4SLinus Torvalds return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
4431da177e4SLinus Torvalds &fpregs[t],status));
4441da177e4SLinus Torvalds case 2: /* dbl/sgl */
4451da177e4SLinus Torvalds return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
4461da177e4SLinus Torvalds &fpregs[t],status));
4471da177e4SLinus Torvalds case 3: /* dbl/dbl */
4481da177e4SLinus Torvalds return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
4491da177e4SLinus Torvalds &fpregs[t],status));
4501da177e4SLinus Torvalds }
451*6f1fce59SHelge Deller BUG();
4521da177e4SLinus Torvalds case 2: /* FCNVFX */
4531da177e4SLinus Torvalds switch(fmt) {
4541da177e4SLinus Torvalds case 0: /* sgl/sgl */
4551da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
4561da177e4SLinus Torvalds &fpregs[t],status));
4571da177e4SLinus Torvalds case 1: /* sgl/dbl */
4581da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
4591da177e4SLinus Torvalds &fpregs[t],status));
4601da177e4SLinus Torvalds case 2: /* dbl/sgl */
4611da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
4621da177e4SLinus Torvalds &fpregs[t],status));
4631da177e4SLinus Torvalds case 3: /* dbl/dbl */
4641da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
4651da177e4SLinus Torvalds &fpregs[t],status));
4661da177e4SLinus Torvalds }
467*6f1fce59SHelge Deller BUG();
4681da177e4SLinus Torvalds case 3: /* FCNVFXT */
4691da177e4SLinus Torvalds switch(fmt) {
4701da177e4SLinus Torvalds case 0: /* sgl/sgl */
4711da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
4721da177e4SLinus Torvalds &fpregs[t],status));
4731da177e4SLinus Torvalds case 1: /* sgl/dbl */
4741da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
4751da177e4SLinus Torvalds &fpregs[t],status));
4761da177e4SLinus Torvalds case 2: /* dbl/sgl */
4771da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
4781da177e4SLinus Torvalds &fpregs[t],status));
4791da177e4SLinus Torvalds case 3: /* dbl/dbl */
4801da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
4811da177e4SLinus Torvalds &fpregs[t],status));
4821da177e4SLinus Torvalds }
483*6f1fce59SHelge Deller BUG();
4841da177e4SLinus Torvalds case 5: /* FCNVUF (PA2.0 only) */
4851da177e4SLinus Torvalds switch(fmt) {
4861da177e4SLinus Torvalds case 0: /* sgl/sgl */
4871da177e4SLinus Torvalds return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
4881da177e4SLinus Torvalds &fpregs[t],status));
4891da177e4SLinus Torvalds case 1: /* sgl/dbl */
4901da177e4SLinus Torvalds return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
4911da177e4SLinus Torvalds &fpregs[t],status));
4921da177e4SLinus Torvalds case 2: /* dbl/sgl */
4931da177e4SLinus Torvalds return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
4941da177e4SLinus Torvalds &fpregs[t],status));
4951da177e4SLinus Torvalds case 3: /* dbl/dbl */
4961da177e4SLinus Torvalds return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
4971da177e4SLinus Torvalds &fpregs[t],status));
4981da177e4SLinus Torvalds }
499*6f1fce59SHelge Deller BUG();
5001da177e4SLinus Torvalds case 6: /* FCNVFU (PA2.0 only) */
5011da177e4SLinus Torvalds switch(fmt) {
5021da177e4SLinus Torvalds case 0: /* sgl/sgl */
5031da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
5041da177e4SLinus Torvalds &fpregs[t],status));
5051da177e4SLinus Torvalds case 1: /* sgl/dbl */
5061da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
5071da177e4SLinus Torvalds &fpregs[t],status));
5081da177e4SLinus Torvalds case 2: /* dbl/sgl */
5091da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
5101da177e4SLinus Torvalds &fpregs[t],status));
5111da177e4SLinus Torvalds case 3: /* dbl/dbl */
5121da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
5131da177e4SLinus Torvalds &fpregs[t],status));
5141da177e4SLinus Torvalds }
515*6f1fce59SHelge Deller BUG();
5161da177e4SLinus Torvalds case 7: /* FCNVFUT (PA2.0 only) */
5171da177e4SLinus Torvalds switch(fmt) {
5181da177e4SLinus Torvalds case 0: /* sgl/sgl */
5191da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
5201da177e4SLinus Torvalds &fpregs[t],status));
5211da177e4SLinus Torvalds case 1: /* sgl/dbl */
5221da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
5231da177e4SLinus Torvalds &fpregs[t],status));
5241da177e4SLinus Torvalds case 2: /* dbl/sgl */
5251da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
5261da177e4SLinus Torvalds &fpregs[t],status));
5271da177e4SLinus Torvalds case 3: /* dbl/dbl */
5281da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
5291da177e4SLinus Torvalds &fpregs[t],status));
5301da177e4SLinus Torvalds }
531*6f1fce59SHelge Deller BUG();
5321da177e4SLinus Torvalds case 4: /* undefined */
5331da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
5341da177e4SLinus Torvalds } /* end of switch subop */
535*6f1fce59SHelge Deller BUG();
5361da177e4SLinus Torvalds case 2: /* class 2 */
5371da177e4SLinus Torvalds fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
5381da177e4SLinus Torvalds r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
5391da177e4SLinus Torvalds if (r2 == 0)
5401da177e4SLinus Torvalds r2 = fpzeroreg;
5411da177e4SLinus Torvalds if (fpu_type_flags & PA2_0_FPU_FLAG) {
5421da177e4SLinus Torvalds /* FTEST if nullify bit set, otherwise FCMP */
5431da177e4SLinus Torvalds if (extru(ir, fpnulpos, 1)) { /* FTEST */
5441da177e4SLinus Torvalds switch (fmt) {
5451da177e4SLinus Torvalds case 0:
5461da177e4SLinus Torvalds /*
5471da177e4SLinus Torvalds * arg0 is not used
5481da177e4SLinus Torvalds * second param is the t field used for
5491da177e4SLinus Torvalds * ftest,acc and ftest,rej
5501da177e4SLinus Torvalds * third param is the subop (y-field)
5511da177e4SLinus Torvalds */
5521da177e4SLinus Torvalds BUG();
5531da177e4SLinus Torvalds /* Unsupported
5541da177e4SLinus Torvalds * return(ftest(0L,extru(ir,fptpos,5),
5551da177e4SLinus Torvalds * &fpregs[0],subop));
5561da177e4SLinus Torvalds */
5571da177e4SLinus Torvalds case 1:
5581da177e4SLinus Torvalds case 2:
5591da177e4SLinus Torvalds case 3:
5601da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
5611da177e4SLinus Torvalds }
5621da177e4SLinus Torvalds } else { /* FCMP */
5631da177e4SLinus Torvalds switch (fmt) {
5641da177e4SLinus Torvalds case 0:
5651da177e4SLinus Torvalds retval = sgl_fcmp(&fpregs[r1],
5661da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
5671da177e4SLinus Torvalds &local_status);
5681da177e4SLinus Torvalds update_status_cbit(status,local_status,
5691da177e4SLinus Torvalds fpu_type_flags, subop);
5701da177e4SLinus Torvalds return(retval);
5711da177e4SLinus Torvalds case 1:
5721da177e4SLinus Torvalds retval = dbl_fcmp(&fpregs[r1],
5731da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
5741da177e4SLinus Torvalds &local_status);
5751da177e4SLinus Torvalds update_status_cbit(status,local_status,
5761da177e4SLinus Torvalds fpu_type_flags, subop);
5771da177e4SLinus Torvalds return(retval);
5781da177e4SLinus Torvalds case 2: /* illegal */
5791da177e4SLinus Torvalds case 3: /* quad not implemented */
5801da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
5811da177e4SLinus Torvalds }
5821da177e4SLinus Torvalds }
5831da177e4SLinus Torvalds } /* end of if for PA2.0 */
5841da177e4SLinus Torvalds else { /* PA1.0 & PA1.1 */
5851da177e4SLinus Torvalds switch (subop) {
5861da177e4SLinus Torvalds case 2:
5871da177e4SLinus Torvalds case 3:
5881da177e4SLinus Torvalds case 4:
5891da177e4SLinus Torvalds case 5:
5901da177e4SLinus Torvalds case 6:
5911da177e4SLinus Torvalds case 7:
5921da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
5931da177e4SLinus Torvalds case 0: /* FCMP */
5941da177e4SLinus Torvalds switch (fmt) {
5951da177e4SLinus Torvalds case 0:
5961da177e4SLinus Torvalds retval = sgl_fcmp(&fpregs[r1],
5971da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
5981da177e4SLinus Torvalds &local_status);
5991da177e4SLinus Torvalds update_status_cbit(status,local_status,
6001da177e4SLinus Torvalds fpu_type_flags, subop);
6011da177e4SLinus Torvalds return(retval);
6021da177e4SLinus Torvalds case 1:
6031da177e4SLinus Torvalds retval = dbl_fcmp(&fpregs[r1],
6041da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
6051da177e4SLinus Torvalds &local_status);
6061da177e4SLinus Torvalds update_status_cbit(status,local_status,
6071da177e4SLinus Torvalds fpu_type_flags, subop);
6081da177e4SLinus Torvalds return(retval);
6091da177e4SLinus Torvalds case 2: /* illegal */
6101da177e4SLinus Torvalds case 3: /* quad not implemented */
6111da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6121da177e4SLinus Torvalds }
613*6f1fce59SHelge Deller BUG();
6141da177e4SLinus Torvalds case 1: /* FTEST */
6151da177e4SLinus Torvalds switch (fmt) {
6161da177e4SLinus Torvalds case 0:
6171da177e4SLinus Torvalds /*
6181da177e4SLinus Torvalds * arg0 is not used
6191da177e4SLinus Torvalds * second param is the t field used for
6201da177e4SLinus Torvalds * ftest,acc and ftest,rej
6211da177e4SLinus Torvalds * third param is the subop (y-field)
6221da177e4SLinus Torvalds */
6231da177e4SLinus Torvalds BUG();
6241da177e4SLinus Torvalds /* unsupported
6251da177e4SLinus Torvalds * return(ftest(0L,extru(ir,fptpos,5),
6261da177e4SLinus Torvalds * &fpregs[0],subop));
6271da177e4SLinus Torvalds */
6281da177e4SLinus Torvalds case 1:
6291da177e4SLinus Torvalds case 2:
6301da177e4SLinus Torvalds case 3:
6311da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6321da177e4SLinus Torvalds }
633*6f1fce59SHelge Deller BUG();
6341da177e4SLinus Torvalds } /* end of switch subop */
6351da177e4SLinus Torvalds } /* end of else for PA1.0 & PA1.1 */
636*6f1fce59SHelge Deller BUG();
6371da177e4SLinus Torvalds case 3: /* class 3 */
6381da177e4SLinus Torvalds r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
6391da177e4SLinus Torvalds if (r2 == 0)
6401da177e4SLinus Torvalds r2 = fpzeroreg;
6411da177e4SLinus Torvalds switch (subop) {
6421da177e4SLinus Torvalds case 5:
6431da177e4SLinus Torvalds case 6:
6441da177e4SLinus Torvalds case 7:
6451da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6461da177e4SLinus Torvalds
6471da177e4SLinus Torvalds case 0: /* FADD */
6481da177e4SLinus Torvalds switch (fmt) {
6491da177e4SLinus Torvalds case 0:
6501da177e4SLinus Torvalds return(sgl_fadd(&fpregs[r1],&fpregs[r2],
6511da177e4SLinus Torvalds &fpregs[t],status));
6521da177e4SLinus Torvalds case 1:
6531da177e4SLinus Torvalds return(dbl_fadd(&fpregs[r1],&fpregs[r2],
6541da177e4SLinus Torvalds &fpregs[t],status));
6551da177e4SLinus Torvalds case 2: /* illegal */
6561da177e4SLinus Torvalds case 3: /* quad not implemented */
6571da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6581da177e4SLinus Torvalds }
659*6f1fce59SHelge Deller BUG();
6601da177e4SLinus Torvalds case 1: /* FSUB */
6611da177e4SLinus Torvalds switch (fmt) {
6621da177e4SLinus Torvalds case 0:
6631da177e4SLinus Torvalds return(sgl_fsub(&fpregs[r1],&fpregs[r2],
6641da177e4SLinus Torvalds &fpregs[t],status));
6651da177e4SLinus Torvalds case 1:
6661da177e4SLinus Torvalds return(dbl_fsub(&fpregs[r1],&fpregs[r2],
6671da177e4SLinus Torvalds &fpregs[t],status));
6681da177e4SLinus Torvalds case 2: /* illegal */
6691da177e4SLinus Torvalds case 3: /* quad not implemented */
6701da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6711da177e4SLinus Torvalds }
672*6f1fce59SHelge Deller BUG();
6731da177e4SLinus Torvalds case 2: /* FMPY */
6741da177e4SLinus Torvalds switch (fmt) {
6751da177e4SLinus Torvalds case 0:
6761da177e4SLinus Torvalds return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
6771da177e4SLinus Torvalds &fpregs[t],status));
6781da177e4SLinus Torvalds case 1:
6791da177e4SLinus Torvalds return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
6801da177e4SLinus Torvalds &fpregs[t],status));
6811da177e4SLinus Torvalds case 2: /* illegal */
6821da177e4SLinus Torvalds case 3: /* quad not implemented */
6831da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6841da177e4SLinus Torvalds }
685*6f1fce59SHelge Deller BUG();
6861da177e4SLinus Torvalds case 3: /* FDIV */
6871da177e4SLinus Torvalds switch (fmt) {
6881da177e4SLinus Torvalds case 0:
6891da177e4SLinus Torvalds return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
6901da177e4SLinus Torvalds &fpregs[t],status));
6911da177e4SLinus Torvalds case 1:
6921da177e4SLinus Torvalds return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
6931da177e4SLinus Torvalds &fpregs[t],status));
6941da177e4SLinus Torvalds case 2: /* illegal */
6951da177e4SLinus Torvalds case 3: /* quad not implemented */
6961da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
6971da177e4SLinus Torvalds }
698*6f1fce59SHelge Deller BUG();
6991da177e4SLinus Torvalds case 4: /* FREM */
7001da177e4SLinus Torvalds switch (fmt) {
7011da177e4SLinus Torvalds case 0:
7021da177e4SLinus Torvalds return(sgl_frem(&fpregs[r1],&fpregs[r2],
7031da177e4SLinus Torvalds &fpregs[t],status));
7041da177e4SLinus Torvalds case 1:
7051da177e4SLinus Torvalds return(dbl_frem(&fpregs[r1],&fpregs[r2],
7061da177e4SLinus Torvalds &fpregs[t],status));
7071da177e4SLinus Torvalds case 2: /* illegal */
7081da177e4SLinus Torvalds case 3: /* quad not implemented */
7091da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
7101da177e4SLinus Torvalds }
711*6f1fce59SHelge Deller BUG();
7121da177e4SLinus Torvalds } /* end of class 3 switch */
7131da177e4SLinus Torvalds } /* end of switch(class) */
7141da177e4SLinus Torvalds
7151da177e4SLinus Torvalds /* If we get here, something is really wrong! */
7161da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
7171da177e4SLinus Torvalds }
7181da177e4SLinus Torvalds
7191da177e4SLinus Torvalds static u_int
decode_0e(ir,class,subop,fpregs)7201da177e4SLinus Torvalds decode_0e(ir,class,subop,fpregs)
7211da177e4SLinus Torvalds u_int ir,class,subop;
7221da177e4SLinus Torvalds u_int fpregs[];
7231da177e4SLinus Torvalds {
7241da177e4SLinus Torvalds u_int r1,r2,t; /* operand register offsets */
7251da177e4SLinus Torvalds u_int fmt; /* also sf for class 1 conversions */
7261da177e4SLinus Torvalds u_int df; /* dest format for class 1 conversions */
7271da177e4SLinus Torvalds u_int *status;
7281da177e4SLinus Torvalds u_int retval, local_status;
7291da177e4SLinus Torvalds u_int fpu_type_flags;
7301da177e4SLinus Torvalds
7311da177e4SLinus Torvalds status = &fpregs[0];
7321da177e4SLinus Torvalds local_status = fpregs[0];
7331da177e4SLinus Torvalds r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
7341da177e4SLinus Torvalds if (r1 == 0)
7351da177e4SLinus Torvalds r1 = fpzeroreg;
7361da177e4SLinus Torvalds t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
7371da177e4SLinus Torvalds if (t == 0 && class != 2)
7381da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
7391da177e4SLinus Torvalds if (class < 2) /* class 0 or 1 has 2 bit fmt */
7401da177e4SLinus Torvalds fmt = extru(ir,fpfmtpos,2);
7411da177e4SLinus Torvalds else /* class 2 and 3 have 1 bit fmt */
7421da177e4SLinus Torvalds fmt = extru(ir,fp0efmtpos,1);
7431da177e4SLinus Torvalds /*
7441da177e4SLinus Torvalds * An undefined combination, double precision accessing the
7451da177e4SLinus Torvalds * right half of a FPR, can get us into trouble.
7461da177e4SLinus Torvalds * Let's just force proper alignment on it.
7471da177e4SLinus Torvalds */
7481da177e4SLinus Torvalds if (fmt == DBL) {
7491da177e4SLinus Torvalds r1 &= ~1;
7501da177e4SLinus Torvalds if (class != 1)
7511da177e4SLinus Torvalds t &= ~1;
7521da177e4SLinus Torvalds }
7531da177e4SLinus Torvalds
7541da177e4SLinus Torvalds switch (class) {
7551da177e4SLinus Torvalds case 0:
7561da177e4SLinus Torvalds switch (subop) {
7571da177e4SLinus Torvalds case 0: /* unimplemented */
7581da177e4SLinus Torvalds case 1:
7591da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
7601da177e4SLinus Torvalds case 2: /* FCPY */
7611da177e4SLinus Torvalds switch (fmt) {
7621da177e4SLinus Torvalds case 2:
7631da177e4SLinus Torvalds case 3:
7641da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
7651da177e4SLinus Torvalds case 1: /* double */
7661da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
767*6f1fce59SHelge Deller fallthrough;
7681da177e4SLinus Torvalds case 0: /* single */
7691da177e4SLinus Torvalds fpregs[t] = fpregs[r1];
7701da177e4SLinus Torvalds return(NOEXCEPTION);
7711da177e4SLinus Torvalds }
772*6f1fce59SHelge Deller BUG();
7731da177e4SLinus Torvalds case 3: /* FABS */
7741da177e4SLinus Torvalds switch (fmt) {
7751da177e4SLinus Torvalds case 2:
7761da177e4SLinus Torvalds case 3:
7771da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
7781da177e4SLinus Torvalds case 1: /* double */
7791da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
780*6f1fce59SHelge Deller fallthrough;
7811da177e4SLinus Torvalds case 0: /* single */
7821da177e4SLinus Torvalds fpregs[t] = fpregs[r1] & 0x7fffffff;
7831da177e4SLinus Torvalds return(NOEXCEPTION);
7841da177e4SLinus Torvalds }
785*6f1fce59SHelge Deller BUG();
7861da177e4SLinus Torvalds case 6: /* FNEG */
7871da177e4SLinus Torvalds switch (fmt) {
7881da177e4SLinus Torvalds case 2:
7891da177e4SLinus Torvalds case 3:
7901da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
7911da177e4SLinus Torvalds case 1: /* double */
7921da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
793*6f1fce59SHelge Deller fallthrough;
7941da177e4SLinus Torvalds case 0: /* single */
7951da177e4SLinus Torvalds fpregs[t] = fpregs[r1] ^ 0x80000000;
7961da177e4SLinus Torvalds return(NOEXCEPTION);
7971da177e4SLinus Torvalds }
798*6f1fce59SHelge Deller BUG();
7991da177e4SLinus Torvalds case 7: /* FNEGABS */
8001da177e4SLinus Torvalds switch (fmt) {
8011da177e4SLinus Torvalds case 2:
8021da177e4SLinus Torvalds case 3:
8031da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8041da177e4SLinus Torvalds case 1: /* double */
8051da177e4SLinus Torvalds fpregs[t+1] = fpregs[r1+1];
806*6f1fce59SHelge Deller fallthrough;
8071da177e4SLinus Torvalds case 0: /* single */
8081da177e4SLinus Torvalds fpregs[t] = fpregs[r1] | 0x80000000;
8091da177e4SLinus Torvalds return(NOEXCEPTION);
8101da177e4SLinus Torvalds }
811*6f1fce59SHelge Deller BUG();
8121da177e4SLinus Torvalds case 4: /* FSQRT */
8131da177e4SLinus Torvalds switch (fmt) {
8141da177e4SLinus Torvalds case 0:
8151da177e4SLinus Torvalds return(sgl_fsqrt(&fpregs[r1],0,
8161da177e4SLinus Torvalds &fpregs[t], status));
8171da177e4SLinus Torvalds case 1:
8181da177e4SLinus Torvalds return(dbl_fsqrt(&fpregs[r1],0,
8191da177e4SLinus Torvalds &fpregs[t], status));
8201da177e4SLinus Torvalds case 2:
8211da177e4SLinus Torvalds case 3:
8221da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8231da177e4SLinus Torvalds }
824*6f1fce59SHelge Deller BUG();
8251da177e4SLinus Torvalds case 5: /* FRMD */
8261da177e4SLinus Torvalds switch (fmt) {
8271da177e4SLinus Torvalds case 0:
8281da177e4SLinus Torvalds return(sgl_frnd(&fpregs[r1],0,
8291da177e4SLinus Torvalds &fpregs[t], status));
8301da177e4SLinus Torvalds case 1:
8311da177e4SLinus Torvalds return(dbl_frnd(&fpregs[r1],0,
8321da177e4SLinus Torvalds &fpregs[t], status));
8331da177e4SLinus Torvalds case 2:
8341da177e4SLinus Torvalds case 3:
8351da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8361da177e4SLinus Torvalds }
8371da177e4SLinus Torvalds } /* end of switch (subop */
838*6f1fce59SHelge Deller BUG();
8391da177e4SLinus Torvalds case 1: /* class 1 */
8401da177e4SLinus Torvalds df = extru(ir,fpdfpos,2); /* get dest format */
8411da177e4SLinus Torvalds /*
8421da177e4SLinus Torvalds * Fix Crashme problem (writing to 31R in double precision)
8431da177e4SLinus Torvalds * here too.
8441da177e4SLinus Torvalds */
8451da177e4SLinus Torvalds if (df == DBL) {
8461da177e4SLinus Torvalds t &= ~1;
8471da177e4SLinus Torvalds }
8481da177e4SLinus Torvalds if ((df & 2) || (fmt & 2))
8491da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8501da177e4SLinus Torvalds
8511da177e4SLinus Torvalds fmt = (fmt << 1) | df;
8521da177e4SLinus Torvalds switch (subop) {
8531da177e4SLinus Torvalds case 0: /* FCNVFF */
8541da177e4SLinus Torvalds switch(fmt) {
8551da177e4SLinus Torvalds case 0: /* sgl/sgl */
8561da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8571da177e4SLinus Torvalds case 1: /* sgl/dbl */
8581da177e4SLinus Torvalds return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
8591da177e4SLinus Torvalds &fpregs[t],status));
8601da177e4SLinus Torvalds case 2: /* dbl/sgl */
8611da177e4SLinus Torvalds return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
8621da177e4SLinus Torvalds &fpregs[t],status));
8631da177e4SLinus Torvalds case 3: /* dbl/dbl */
8641da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
8651da177e4SLinus Torvalds }
866*6f1fce59SHelge Deller BUG();
8671da177e4SLinus Torvalds case 1: /* FCNVXF */
8681da177e4SLinus Torvalds switch(fmt) {
8691da177e4SLinus Torvalds case 0: /* sgl/sgl */
8701da177e4SLinus Torvalds return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
8711da177e4SLinus Torvalds &fpregs[t],status));
8721da177e4SLinus Torvalds case 1: /* sgl/dbl */
8731da177e4SLinus Torvalds return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
8741da177e4SLinus Torvalds &fpregs[t],status));
8751da177e4SLinus Torvalds case 2: /* dbl/sgl */
8761da177e4SLinus Torvalds return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
8771da177e4SLinus Torvalds &fpregs[t],status));
8781da177e4SLinus Torvalds case 3: /* dbl/dbl */
8791da177e4SLinus Torvalds return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
8801da177e4SLinus Torvalds &fpregs[t],status));
8811da177e4SLinus Torvalds }
882*6f1fce59SHelge Deller BUG();
8831da177e4SLinus Torvalds case 2: /* FCNVFX */
8841da177e4SLinus Torvalds switch(fmt) {
8851da177e4SLinus Torvalds case 0: /* sgl/sgl */
8861da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
8871da177e4SLinus Torvalds &fpregs[t],status));
8881da177e4SLinus Torvalds case 1: /* sgl/dbl */
8891da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
8901da177e4SLinus Torvalds &fpregs[t],status));
8911da177e4SLinus Torvalds case 2: /* dbl/sgl */
8921da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
8931da177e4SLinus Torvalds &fpregs[t],status));
8941da177e4SLinus Torvalds case 3: /* dbl/dbl */
8951da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
8961da177e4SLinus Torvalds &fpregs[t],status));
8971da177e4SLinus Torvalds }
898*6f1fce59SHelge Deller BUG();
8991da177e4SLinus Torvalds case 3: /* FCNVFXT */
9001da177e4SLinus Torvalds switch(fmt) {
9011da177e4SLinus Torvalds case 0: /* sgl/sgl */
9021da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
9031da177e4SLinus Torvalds &fpregs[t],status));
9041da177e4SLinus Torvalds case 1: /* sgl/dbl */
9051da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
9061da177e4SLinus Torvalds &fpregs[t],status));
9071da177e4SLinus Torvalds case 2: /* dbl/sgl */
9081da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
9091da177e4SLinus Torvalds &fpregs[t],status));
9101da177e4SLinus Torvalds case 3: /* dbl/dbl */
9111da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
9121da177e4SLinus Torvalds &fpregs[t],status));
9131da177e4SLinus Torvalds }
914*6f1fce59SHelge Deller BUG();
9151da177e4SLinus Torvalds case 5: /* FCNVUF (PA2.0 only) */
9161da177e4SLinus Torvalds switch(fmt) {
9171da177e4SLinus Torvalds case 0: /* sgl/sgl */
9181da177e4SLinus Torvalds return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
9191da177e4SLinus Torvalds &fpregs[t],status));
9201da177e4SLinus Torvalds case 1: /* sgl/dbl */
9211da177e4SLinus Torvalds return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
9221da177e4SLinus Torvalds &fpregs[t],status));
9231da177e4SLinus Torvalds case 2: /* dbl/sgl */
9241da177e4SLinus Torvalds return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
9251da177e4SLinus Torvalds &fpregs[t],status));
9261da177e4SLinus Torvalds case 3: /* dbl/dbl */
9271da177e4SLinus Torvalds return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
9281da177e4SLinus Torvalds &fpregs[t],status));
9291da177e4SLinus Torvalds }
930*6f1fce59SHelge Deller BUG();
9311da177e4SLinus Torvalds case 6: /* FCNVFU (PA2.0 only) */
9321da177e4SLinus Torvalds switch(fmt) {
9331da177e4SLinus Torvalds case 0: /* sgl/sgl */
9341da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
9351da177e4SLinus Torvalds &fpregs[t],status));
9361da177e4SLinus Torvalds case 1: /* sgl/dbl */
9371da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
9381da177e4SLinus Torvalds &fpregs[t],status));
9391da177e4SLinus Torvalds case 2: /* dbl/sgl */
9401da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
9411da177e4SLinus Torvalds &fpregs[t],status));
9421da177e4SLinus Torvalds case 3: /* dbl/dbl */
9431da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
9441da177e4SLinus Torvalds &fpregs[t],status));
9451da177e4SLinus Torvalds }
946*6f1fce59SHelge Deller BUG();
9471da177e4SLinus Torvalds case 7: /* FCNVFUT (PA2.0 only) */
9481da177e4SLinus Torvalds switch(fmt) {
9491da177e4SLinus Torvalds case 0: /* sgl/sgl */
9501da177e4SLinus Torvalds return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
9511da177e4SLinus Torvalds &fpregs[t],status));
9521da177e4SLinus Torvalds case 1: /* sgl/dbl */
9531da177e4SLinus Torvalds return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
9541da177e4SLinus Torvalds &fpregs[t],status));
9551da177e4SLinus Torvalds case 2: /* dbl/sgl */
9561da177e4SLinus Torvalds return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
9571da177e4SLinus Torvalds &fpregs[t],status));
9581da177e4SLinus Torvalds case 3: /* dbl/dbl */
9591da177e4SLinus Torvalds return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
9601da177e4SLinus Torvalds &fpregs[t],status));
9611da177e4SLinus Torvalds }
962*6f1fce59SHelge Deller BUG();
9631da177e4SLinus Torvalds case 4: /* undefined */
9641da177e4SLinus Torvalds return(MAJOR_0C_EXCP);
9651da177e4SLinus Torvalds } /* end of switch subop */
966*6f1fce59SHelge Deller BUG();
9671da177e4SLinus Torvalds case 2: /* class 2 */
9681da177e4SLinus Torvalds /*
9691da177e4SLinus Torvalds * Be careful out there.
9701da177e4SLinus Torvalds * Crashme can generate cases where FR31R is specified
9711da177e4SLinus Torvalds * as the source or target of a double precision operation.
9721da177e4SLinus Torvalds * Since we just pass the address of the floating-point
9731da177e4SLinus Torvalds * register to the emulation routines, this can cause
9741da177e4SLinus Torvalds * corruption of fpzeroreg.
9751da177e4SLinus Torvalds */
9761da177e4SLinus Torvalds if (fmt == DBL)
9771da177e4SLinus Torvalds r2 = (extru(ir,fpr2pos,5)<<1);
9781da177e4SLinus Torvalds else
9791da177e4SLinus Torvalds r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
9801da177e4SLinus Torvalds fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
9811da177e4SLinus Torvalds if (r2 == 0)
9821da177e4SLinus Torvalds r2 = fpzeroreg;
9831da177e4SLinus Torvalds if (fpu_type_flags & PA2_0_FPU_FLAG) {
9841da177e4SLinus Torvalds /* FTEST if nullify bit set, otherwise FCMP */
9851da177e4SLinus Torvalds if (extru(ir, fpnulpos, 1)) { /* FTEST */
9861da177e4SLinus Torvalds /* not legal */
9871da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
9881da177e4SLinus Torvalds } else { /* FCMP */
9891da177e4SLinus Torvalds switch (fmt) {
9901da177e4SLinus Torvalds /*
9911da177e4SLinus Torvalds * fmt is only 1 bit long
9921da177e4SLinus Torvalds */
9931da177e4SLinus Torvalds case 0:
9941da177e4SLinus Torvalds retval = sgl_fcmp(&fpregs[r1],
9951da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
9961da177e4SLinus Torvalds &local_status);
9971da177e4SLinus Torvalds update_status_cbit(status,local_status,
9981da177e4SLinus Torvalds fpu_type_flags, subop);
9991da177e4SLinus Torvalds return(retval);
10001da177e4SLinus Torvalds case 1:
10011da177e4SLinus Torvalds retval = dbl_fcmp(&fpregs[r1],
10021da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
10031da177e4SLinus Torvalds &local_status);
10041da177e4SLinus Torvalds update_status_cbit(status,local_status,
10051da177e4SLinus Torvalds fpu_type_flags, subop);
10061da177e4SLinus Torvalds return(retval);
10071da177e4SLinus Torvalds }
10081da177e4SLinus Torvalds }
10091da177e4SLinus Torvalds } /* end of if for PA2.0 */
10101da177e4SLinus Torvalds else { /* PA1.0 & PA1.1 */
10111da177e4SLinus Torvalds switch (subop) {
10121da177e4SLinus Torvalds case 1:
10131da177e4SLinus Torvalds case 2:
10141da177e4SLinus Torvalds case 3:
10151da177e4SLinus Torvalds case 4:
10161da177e4SLinus Torvalds case 5:
10171da177e4SLinus Torvalds case 6:
10181da177e4SLinus Torvalds case 7:
10191da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
10201da177e4SLinus Torvalds case 0: /* FCMP */
10211da177e4SLinus Torvalds switch (fmt) {
10221da177e4SLinus Torvalds /*
10231da177e4SLinus Torvalds * fmt is only 1 bit long
10241da177e4SLinus Torvalds */
10251da177e4SLinus Torvalds case 0:
10261da177e4SLinus Torvalds retval = sgl_fcmp(&fpregs[r1],
10271da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
10281da177e4SLinus Torvalds &local_status);
10291da177e4SLinus Torvalds update_status_cbit(status,local_status,
10301da177e4SLinus Torvalds fpu_type_flags, subop);
10311da177e4SLinus Torvalds return(retval);
10321da177e4SLinus Torvalds case 1:
10331da177e4SLinus Torvalds retval = dbl_fcmp(&fpregs[r1],
10341da177e4SLinus Torvalds &fpregs[r2],extru(ir,fptpos,5),
10351da177e4SLinus Torvalds &local_status);
10361da177e4SLinus Torvalds update_status_cbit(status,local_status,
10371da177e4SLinus Torvalds fpu_type_flags, subop);
10381da177e4SLinus Torvalds return(retval);
10391da177e4SLinus Torvalds }
10401da177e4SLinus Torvalds } /* end of switch subop */
10411da177e4SLinus Torvalds } /* end of else for PA1.0 & PA1.1 */
1042*6f1fce59SHelge Deller BUG();
10431da177e4SLinus Torvalds case 3: /* class 3 */
10441da177e4SLinus Torvalds /*
10451da177e4SLinus Torvalds * Be careful out there.
10461da177e4SLinus Torvalds * Crashme can generate cases where FR31R is specified
10471da177e4SLinus Torvalds * as the source or target of a double precision operation.
10481da177e4SLinus Torvalds * Since we just pass the address of the floating-point
10491da177e4SLinus Torvalds * register to the emulation routines, this can cause
10501da177e4SLinus Torvalds * corruption of fpzeroreg.
10511da177e4SLinus Torvalds */
10521da177e4SLinus Torvalds if (fmt == DBL)
10531da177e4SLinus Torvalds r2 = (extru(ir,fpr2pos,5)<<1);
10541da177e4SLinus Torvalds else
10551da177e4SLinus Torvalds r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
10561da177e4SLinus Torvalds if (r2 == 0)
10571da177e4SLinus Torvalds r2 = fpzeroreg;
10581da177e4SLinus Torvalds switch (subop) {
10591da177e4SLinus Torvalds case 5:
10601da177e4SLinus Torvalds case 6:
10611da177e4SLinus Torvalds case 7:
10621da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
10631da177e4SLinus Torvalds
10641da177e4SLinus Torvalds /*
10651da177e4SLinus Torvalds * Note that fmt is only 1 bit for class 3 */
10661da177e4SLinus Torvalds case 0: /* FADD */
10671da177e4SLinus Torvalds switch (fmt) {
10681da177e4SLinus Torvalds case 0:
10691da177e4SLinus Torvalds return(sgl_fadd(&fpregs[r1],&fpregs[r2],
10701da177e4SLinus Torvalds &fpregs[t],status));
10711da177e4SLinus Torvalds case 1:
10721da177e4SLinus Torvalds return(dbl_fadd(&fpregs[r1],&fpregs[r2],
10731da177e4SLinus Torvalds &fpregs[t],status));
10741da177e4SLinus Torvalds }
1075*6f1fce59SHelge Deller BUG();
10761da177e4SLinus Torvalds case 1: /* FSUB */
10771da177e4SLinus Torvalds switch (fmt) {
10781da177e4SLinus Torvalds case 0:
10791da177e4SLinus Torvalds return(sgl_fsub(&fpregs[r1],&fpregs[r2],
10801da177e4SLinus Torvalds &fpregs[t],status));
10811da177e4SLinus Torvalds case 1:
10821da177e4SLinus Torvalds return(dbl_fsub(&fpregs[r1],&fpregs[r2],
10831da177e4SLinus Torvalds &fpregs[t],status));
10841da177e4SLinus Torvalds }
1085*6f1fce59SHelge Deller BUG();
10861da177e4SLinus Torvalds case 2: /* FMPY or XMPYU */
10871da177e4SLinus Torvalds /*
10881da177e4SLinus Torvalds * check for integer multiply (x bit set)
10891da177e4SLinus Torvalds */
10901da177e4SLinus Torvalds if (extru(ir,fpxpos,1)) {
10911da177e4SLinus Torvalds /*
10921da177e4SLinus Torvalds * emulate XMPYU
10931da177e4SLinus Torvalds */
10941da177e4SLinus Torvalds switch (fmt) {
10951da177e4SLinus Torvalds case 0:
10961da177e4SLinus Torvalds /*
10971da177e4SLinus Torvalds * bad instruction if t specifies
10981da177e4SLinus Torvalds * the right half of a register
10991da177e4SLinus Torvalds */
11001da177e4SLinus Torvalds if (t & 1)
11011da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
11021da177e4SLinus Torvalds BUG();
11031da177e4SLinus Torvalds /* unsupported
11041da177e4SLinus Torvalds * impyu(&fpregs[r1],&fpregs[r2],
11051da177e4SLinus Torvalds * &fpregs[t]);
11061da177e4SLinus Torvalds */
11071da177e4SLinus Torvalds return(NOEXCEPTION);
11081da177e4SLinus Torvalds case 1:
11091da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
11101da177e4SLinus Torvalds }
11111da177e4SLinus Torvalds }
11121da177e4SLinus Torvalds else { /* FMPY */
11131da177e4SLinus Torvalds switch (fmt) {
11141da177e4SLinus Torvalds case 0:
11151da177e4SLinus Torvalds return(sgl_fmpy(&fpregs[r1],
11161da177e4SLinus Torvalds &fpregs[r2],&fpregs[t],status));
11171da177e4SLinus Torvalds case 1:
11181da177e4SLinus Torvalds return(dbl_fmpy(&fpregs[r1],
11191da177e4SLinus Torvalds &fpregs[r2],&fpregs[t],status));
11201da177e4SLinus Torvalds }
11211da177e4SLinus Torvalds }
1122*6f1fce59SHelge Deller BUG();
11231da177e4SLinus Torvalds case 3: /* FDIV */
11241da177e4SLinus Torvalds switch (fmt) {
11251da177e4SLinus Torvalds case 0:
11261da177e4SLinus Torvalds return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
11271da177e4SLinus Torvalds &fpregs[t],status));
11281da177e4SLinus Torvalds case 1:
11291da177e4SLinus Torvalds return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
11301da177e4SLinus Torvalds &fpregs[t],status));
11311da177e4SLinus Torvalds }
1132*6f1fce59SHelge Deller BUG();
11331da177e4SLinus Torvalds case 4: /* FREM */
11341da177e4SLinus Torvalds switch (fmt) {
11351da177e4SLinus Torvalds case 0:
11361da177e4SLinus Torvalds return(sgl_frem(&fpregs[r1],&fpregs[r2],
11371da177e4SLinus Torvalds &fpregs[t],status));
11381da177e4SLinus Torvalds case 1:
11391da177e4SLinus Torvalds return(dbl_frem(&fpregs[r1],&fpregs[r2],
11401da177e4SLinus Torvalds &fpregs[t],status));
11411da177e4SLinus Torvalds }
11421da177e4SLinus Torvalds } /* end of class 3 switch */
11431da177e4SLinus Torvalds } /* end of switch(class) */
11441da177e4SLinus Torvalds
11451da177e4SLinus Torvalds /* If we get here, something is really wrong! */
11461da177e4SLinus Torvalds return(MAJOR_0E_EXCP);
11471da177e4SLinus Torvalds }
11481da177e4SLinus Torvalds
11491da177e4SLinus Torvalds
11501da177e4SLinus Torvalds /*
11511da177e4SLinus Torvalds * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
11521da177e4SLinus Torvalds */
11531da177e4SLinus Torvalds static u_int
decode_06(ir,fpregs)11541da177e4SLinus Torvalds decode_06(ir,fpregs)
11551da177e4SLinus Torvalds u_int ir;
11561da177e4SLinus Torvalds u_int fpregs[];
11571da177e4SLinus Torvalds {
11581da177e4SLinus Torvalds u_int rm1, rm2, tm, ra, ta; /* operands */
11591da177e4SLinus Torvalds u_int fmt;
11601da177e4SLinus Torvalds u_int error = 0;
11611da177e4SLinus Torvalds u_int status;
11621da177e4SLinus Torvalds u_int fpu_type_flags;
11631da177e4SLinus Torvalds union {
11641da177e4SLinus Torvalds double dbl;
11651da177e4SLinus Torvalds float flt;
11661da177e4SLinus Torvalds struct { u_int i1; u_int i2; } ints;
11671da177e4SLinus Torvalds } mtmp, atmp;
11681da177e4SLinus Torvalds
11691da177e4SLinus Torvalds
11701da177e4SLinus Torvalds status = fpregs[0]; /* use a local copy of status reg */
11711da177e4SLinus Torvalds fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
11721da177e4SLinus Torvalds fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
11731da177e4SLinus Torvalds if (fmt == 0) { /* DBL */
11741da177e4SLinus Torvalds rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
11751da177e4SLinus Torvalds if (rm1 == 0)
11761da177e4SLinus Torvalds rm1 = fpzeroreg;
11771da177e4SLinus Torvalds rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
11781da177e4SLinus Torvalds if (rm2 == 0)
11791da177e4SLinus Torvalds rm2 = fpzeroreg;
11801da177e4SLinus Torvalds tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
11811da177e4SLinus Torvalds if (tm == 0)
11821da177e4SLinus Torvalds return(MAJOR_06_EXCP);
11831da177e4SLinus Torvalds ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
11841da177e4SLinus Torvalds ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
11851da177e4SLinus Torvalds if (ta == 0)
11861da177e4SLinus Torvalds return(MAJOR_06_EXCP);
11871da177e4SLinus Torvalds
11881da177e4SLinus Torvalds if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
11891da177e4SLinus Torvalds
11901da177e4SLinus Torvalds if (ra == 0) {
11911da177e4SLinus Torvalds /* special case FMPYCFXT, see sgl case below */
11921da177e4SLinus Torvalds if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
11931da177e4SLinus Torvalds &mtmp.ints.i1,&status))
11941da177e4SLinus Torvalds error = 1;
11951da177e4SLinus Torvalds if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
11961da177e4SLinus Torvalds &atmp.ints.i1,&atmp.ints.i1,&status))
11971da177e4SLinus Torvalds error = 1;
11981da177e4SLinus Torvalds }
11991da177e4SLinus Torvalds else {
12001da177e4SLinus Torvalds
12011da177e4SLinus Torvalds if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12021da177e4SLinus Torvalds &status))
12031da177e4SLinus Torvalds error = 1;
12041da177e4SLinus Torvalds if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
12051da177e4SLinus Torvalds &status))
12061da177e4SLinus Torvalds error = 1;
12071da177e4SLinus Torvalds }
12081da177e4SLinus Torvalds }
12091da177e4SLinus Torvalds
12101da177e4SLinus Torvalds else
12111da177e4SLinus Torvalds
12121da177e4SLinus Torvalds {
12131da177e4SLinus Torvalds if (ra == 0)
12141da177e4SLinus Torvalds ra = fpzeroreg;
12151da177e4SLinus Torvalds
12161da177e4SLinus Torvalds if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12171da177e4SLinus Torvalds &status))
12181da177e4SLinus Torvalds error = 1;
12191da177e4SLinus Torvalds if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
12201da177e4SLinus Torvalds &status))
12211da177e4SLinus Torvalds error = 1;
12221da177e4SLinus Torvalds
12231da177e4SLinus Torvalds }
12241da177e4SLinus Torvalds
12251da177e4SLinus Torvalds if (error)
12261da177e4SLinus Torvalds return(MAJOR_06_EXCP);
12271da177e4SLinus Torvalds else {
12281da177e4SLinus Torvalds /* copy results */
12291da177e4SLinus Torvalds fpregs[tm] = mtmp.ints.i1;
12301da177e4SLinus Torvalds fpregs[tm+1] = mtmp.ints.i2;
12311da177e4SLinus Torvalds fpregs[ta] = atmp.ints.i1;
12321da177e4SLinus Torvalds fpregs[ta+1] = atmp.ints.i2;
12331da177e4SLinus Torvalds fpregs[0] = status;
12341da177e4SLinus Torvalds return(NOEXCEPTION);
12351da177e4SLinus Torvalds }
12361da177e4SLinus Torvalds }
12371da177e4SLinus Torvalds else { /* SGL */
12381da177e4SLinus Torvalds /*
12391da177e4SLinus Torvalds * calculate offsets for single precision numbers
12401da177e4SLinus Torvalds * See table 6-14 in PA-89 architecture for mapping
12411da177e4SLinus Torvalds */
12421da177e4SLinus Torvalds rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
12431da177e4SLinus Torvalds rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
12441da177e4SLinus Torvalds
12451da177e4SLinus Torvalds rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
12461da177e4SLinus Torvalds rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
12471da177e4SLinus Torvalds
12481da177e4SLinus Torvalds tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
12491da177e4SLinus Torvalds tm |= extru(ir,fptmpos-4,1); /* add right word offset */
12501da177e4SLinus Torvalds
12511da177e4SLinus Torvalds ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
12521da177e4SLinus Torvalds ra |= extru(ir,fprapos-4,1); /* add right word offset */
12531da177e4SLinus Torvalds
12541da177e4SLinus Torvalds ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
12551da177e4SLinus Torvalds ta |= extru(ir,fptapos-4,1); /* add right word offset */
12561da177e4SLinus Torvalds
12571da177e4SLinus Torvalds if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
12581da177e4SLinus Torvalds /* special case FMPYCFXT (really 0)
12591da177e4SLinus Torvalds * This instruction is only present on the Timex and
12601da177e4SLinus Torvalds * Rolex fpu's in so if it is the special case and
12611da177e4SLinus Torvalds * one of these fpu's we run the FMPYCFXT instruction
12621da177e4SLinus Torvalds */
12631da177e4SLinus Torvalds if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12641da177e4SLinus Torvalds &status))
12651da177e4SLinus Torvalds error = 1;
12661da177e4SLinus Torvalds if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
12671da177e4SLinus Torvalds &atmp.ints.i1,&status))
12681da177e4SLinus Torvalds error = 1;
12691da177e4SLinus Torvalds }
12701da177e4SLinus Torvalds else {
12711da177e4SLinus Torvalds if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12721da177e4SLinus Torvalds &status))
12731da177e4SLinus Torvalds error = 1;
12741da177e4SLinus Torvalds if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
12751da177e4SLinus Torvalds &status))
12761da177e4SLinus Torvalds error = 1;
12771da177e4SLinus Torvalds }
12781da177e4SLinus Torvalds if (error)
12791da177e4SLinus Torvalds return(MAJOR_06_EXCP);
12801da177e4SLinus Torvalds else {
12811da177e4SLinus Torvalds /* copy results */
12821da177e4SLinus Torvalds fpregs[tm] = mtmp.ints.i1;
12831da177e4SLinus Torvalds fpregs[ta] = atmp.ints.i1;
12841da177e4SLinus Torvalds fpregs[0] = status;
12851da177e4SLinus Torvalds return(NOEXCEPTION);
12861da177e4SLinus Torvalds }
12871da177e4SLinus Torvalds }
12881da177e4SLinus Torvalds }
12891da177e4SLinus Torvalds
12901da177e4SLinus Torvalds /*
12911da177e4SLinus Torvalds * routine to decode the 26 (FMPYSUB) instruction
12921da177e4SLinus Torvalds */
12931da177e4SLinus Torvalds static u_int
decode_26(ir,fpregs)12941da177e4SLinus Torvalds decode_26(ir,fpregs)
12951da177e4SLinus Torvalds u_int ir;
12961da177e4SLinus Torvalds u_int fpregs[];
12971da177e4SLinus Torvalds {
12981da177e4SLinus Torvalds u_int rm1, rm2, tm, ra, ta; /* operands */
12991da177e4SLinus Torvalds u_int fmt;
13001da177e4SLinus Torvalds u_int error = 0;
13011da177e4SLinus Torvalds u_int status;
13021da177e4SLinus Torvalds union {
13031da177e4SLinus Torvalds double dbl;
13041da177e4SLinus Torvalds float flt;
13051da177e4SLinus Torvalds struct { u_int i1; u_int i2; } ints;
13061da177e4SLinus Torvalds } mtmp, atmp;
13071da177e4SLinus Torvalds
13081da177e4SLinus Torvalds
13091da177e4SLinus Torvalds status = fpregs[0];
13101da177e4SLinus Torvalds fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
13111da177e4SLinus Torvalds if (fmt == 0) { /* DBL */
13121da177e4SLinus Torvalds rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
13131da177e4SLinus Torvalds if (rm1 == 0)
13141da177e4SLinus Torvalds rm1 = fpzeroreg;
13151da177e4SLinus Torvalds rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
13161da177e4SLinus Torvalds if (rm2 == 0)
13171da177e4SLinus Torvalds rm2 = fpzeroreg;
13181da177e4SLinus Torvalds tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
13191da177e4SLinus Torvalds if (tm == 0)
13201da177e4SLinus Torvalds return(MAJOR_26_EXCP);
13211da177e4SLinus Torvalds ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
13221da177e4SLinus Torvalds if (ra == 0)
13231da177e4SLinus Torvalds return(MAJOR_26_EXCP);
13241da177e4SLinus Torvalds ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
13251da177e4SLinus Torvalds if (ta == 0)
13261da177e4SLinus Torvalds return(MAJOR_26_EXCP);
13271da177e4SLinus Torvalds
13281da177e4SLinus Torvalds if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
13291da177e4SLinus Torvalds error = 1;
13301da177e4SLinus Torvalds if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
13311da177e4SLinus Torvalds error = 1;
13321da177e4SLinus Torvalds if (error)
13331da177e4SLinus Torvalds return(MAJOR_26_EXCP);
13341da177e4SLinus Torvalds else {
13351da177e4SLinus Torvalds /* copy results */
13361da177e4SLinus Torvalds fpregs[tm] = mtmp.ints.i1;
13371da177e4SLinus Torvalds fpregs[tm+1] = mtmp.ints.i2;
13381da177e4SLinus Torvalds fpregs[ta] = atmp.ints.i1;
13391da177e4SLinus Torvalds fpregs[ta+1] = atmp.ints.i2;
13401da177e4SLinus Torvalds fpregs[0] = status;
13411da177e4SLinus Torvalds return(NOEXCEPTION);
13421da177e4SLinus Torvalds }
13431da177e4SLinus Torvalds }
13441da177e4SLinus Torvalds else { /* SGL */
13451da177e4SLinus Torvalds /*
13461da177e4SLinus Torvalds * calculate offsets for single precision numbers
13471da177e4SLinus Torvalds * See table 6-14 in PA-89 architecture for mapping
13481da177e4SLinus Torvalds */
13491da177e4SLinus Torvalds rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
13501da177e4SLinus Torvalds rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
13511da177e4SLinus Torvalds
13521da177e4SLinus Torvalds rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
13531da177e4SLinus Torvalds rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
13541da177e4SLinus Torvalds
13551da177e4SLinus Torvalds tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
13561da177e4SLinus Torvalds tm |= extru(ir,fptmpos-4,1); /* add right word offset */
13571da177e4SLinus Torvalds
13581da177e4SLinus Torvalds ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
13591da177e4SLinus Torvalds ra |= extru(ir,fprapos-4,1); /* add right word offset */
13601da177e4SLinus Torvalds
13611da177e4SLinus Torvalds ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
13621da177e4SLinus Torvalds ta |= extru(ir,fptapos-4,1); /* add right word offset */
13631da177e4SLinus Torvalds
13641da177e4SLinus Torvalds if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
13651da177e4SLinus Torvalds error = 1;
13661da177e4SLinus Torvalds if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
13671da177e4SLinus Torvalds error = 1;
13681da177e4SLinus Torvalds if (error)
13691da177e4SLinus Torvalds return(MAJOR_26_EXCP);
13701da177e4SLinus Torvalds else {
13711da177e4SLinus Torvalds /* copy results */
13721da177e4SLinus Torvalds fpregs[tm] = mtmp.ints.i1;
13731da177e4SLinus Torvalds fpregs[ta] = atmp.ints.i1;
13741da177e4SLinus Torvalds fpregs[0] = status;
13751da177e4SLinus Torvalds return(NOEXCEPTION);
13761da177e4SLinus Torvalds }
13771da177e4SLinus Torvalds }
13781da177e4SLinus Torvalds
13791da177e4SLinus Torvalds }
13801da177e4SLinus Torvalds
13811da177e4SLinus Torvalds /*
13821da177e4SLinus Torvalds * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
13831da177e4SLinus Torvalds */
13841da177e4SLinus Torvalds static u_int
decode_2e(ir,fpregs)13851da177e4SLinus Torvalds decode_2e(ir,fpregs)
13861da177e4SLinus Torvalds u_int ir;
13871da177e4SLinus Torvalds u_int fpregs[];
13881da177e4SLinus Torvalds {
13891da177e4SLinus Torvalds u_int rm1, rm2, ra, t; /* operands */
13901da177e4SLinus Torvalds u_int fmt;
13911da177e4SLinus Torvalds
13921da177e4SLinus Torvalds fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
13931da177e4SLinus Torvalds if (fmt == DBL) { /* DBL */
13941da177e4SLinus Torvalds rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
13951da177e4SLinus Torvalds if (rm1 == 0)
13961da177e4SLinus Torvalds rm1 = fpzeroreg;
13971da177e4SLinus Torvalds rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
13981da177e4SLinus Torvalds if (rm2 == 0)
13991da177e4SLinus Torvalds rm2 = fpzeroreg;
14001da177e4SLinus Torvalds ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
14011da177e4SLinus Torvalds sizeof(double)/sizeof(u_int);
14021da177e4SLinus Torvalds if (ra == 0)
14031da177e4SLinus Torvalds ra = fpzeroreg;
14041da177e4SLinus Torvalds t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
14051da177e4SLinus Torvalds if (t == 0)
14061da177e4SLinus Torvalds return(MAJOR_2E_EXCP);
14071da177e4SLinus Torvalds
14081da177e4SLinus Torvalds if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
14091da177e4SLinus Torvalds return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
14101da177e4SLinus Torvalds &fpregs[ra], &fpregs[0], &fpregs[t]));
14111da177e4SLinus Torvalds } else {
14121da177e4SLinus Torvalds return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
14131da177e4SLinus Torvalds &fpregs[ra], &fpregs[0], &fpregs[t]));
14141da177e4SLinus Torvalds }
14151da177e4SLinus Torvalds } /* end DBL */
14161da177e4SLinus Torvalds else { /* SGL */
14171da177e4SLinus Torvalds rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
14181da177e4SLinus Torvalds if (rm1 == 0)
14191da177e4SLinus Torvalds rm1 = fpzeroreg;
14201da177e4SLinus Torvalds rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
14211da177e4SLinus Torvalds if (rm2 == 0)
14221da177e4SLinus Torvalds rm2 = fpzeroreg;
14231da177e4SLinus Torvalds ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
14241da177e4SLinus Torvalds if (ra == 0)
14251da177e4SLinus Torvalds ra = fpzeroreg;
14261da177e4SLinus Torvalds t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
14271da177e4SLinus Torvalds if (t == 0)
14281da177e4SLinus Torvalds return(MAJOR_2E_EXCP);
14291da177e4SLinus Torvalds
14301da177e4SLinus Torvalds if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
14311da177e4SLinus Torvalds return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
14321da177e4SLinus Torvalds &fpregs[ra], &fpregs[0], &fpregs[t]));
14331da177e4SLinus Torvalds } else {
14341da177e4SLinus Torvalds return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
14351da177e4SLinus Torvalds &fpregs[ra], &fpregs[0], &fpregs[t]));
14361da177e4SLinus Torvalds }
14371da177e4SLinus Torvalds } /* end SGL */
14381da177e4SLinus Torvalds }
14391da177e4SLinus Torvalds
14401da177e4SLinus Torvalds /*
14411da177e4SLinus Torvalds * update_status_cbit
14421da177e4SLinus Torvalds *
14431da177e4SLinus Torvalds * This routine returns the correct FP status register value in
14441da177e4SLinus Torvalds * *status, based on the C-bit & V-bit returned by the FCMP
14451da177e4SLinus Torvalds * emulation routine in new_status. The architecture type
14461da177e4SLinus Torvalds * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
14471da177e4SLinus Torvalds * and the architecture type are used to determine what flavor
14481da177e4SLinus Torvalds * of FCMP is being emulated.
14491da177e4SLinus Torvalds */
14501da177e4SLinus Torvalds static void
update_status_cbit(status,new_status,fpu_type,y_field)14511da177e4SLinus Torvalds update_status_cbit(status, new_status, fpu_type, y_field)
14521da177e4SLinus Torvalds u_int *status, new_status;
14531da177e4SLinus Torvalds u_int fpu_type;
14541da177e4SLinus Torvalds u_int y_field;
14551da177e4SLinus Torvalds {
14561da177e4SLinus Torvalds /*
14571da177e4SLinus Torvalds * For PA89 FPU's which implement the Compare Queue and
14581da177e4SLinus Torvalds * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
14591da177e4SLinus Torvalds * otherwise update the specified bit in the Compare Array.
14601da177e4SLinus Torvalds * Note that the y-field will always be 0 for non-PA2.0 FPU's.
14611da177e4SLinus Torvalds */
14621da177e4SLinus Torvalds if ((fpu_type & TIMEX_EXTEN_FLAG) ||
14631da177e4SLinus Torvalds (fpu_type & ROLEX_EXTEN_FLAG) ||
14641da177e4SLinus Torvalds (fpu_type & PA2_0_FPU_FLAG)) {
14651da177e4SLinus Torvalds if (y_field == 0) {
14661da177e4SLinus Torvalds *status = ((*status & 0x04000000) >> 5) | /* old Cbit */
14671da177e4SLinus Torvalds ((*status & 0x003ff000) >> 1) | /* old CQ */
14681da177e4SLinus Torvalds (new_status & 0xffc007ff); /* all other bits*/
14691da177e4SLinus Torvalds } else {
14701da177e4SLinus Torvalds *status = (*status & 0x04000000) | /* old Cbit */
14711da177e4SLinus Torvalds ((new_status & 0x04000000) >> (y_field+4)) |
14721da177e4SLinus Torvalds (new_status & ~0x04000000 & /* other bits */
14731da177e4SLinus Torvalds ~(0x04000000 >> (y_field+4)));
14741da177e4SLinus Torvalds }
14751da177e4SLinus Torvalds }
14761da177e4SLinus Torvalds /* if PA83, just update the C-bit */
14771da177e4SLinus Torvalds else {
14781da177e4SLinus Torvalds *status = new_status;
14791da177e4SLinus Torvalds }
14801da177e4SLinus Torvalds }
1481