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