162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Floating-point emulation code 662306a36Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * BEGIN_DESC 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * File: 1262306a36Sopenharmony_ci * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Purpose: 1562306a36Sopenharmony_ci * <<please update with a synopsis of the functionality provided by this file>> 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * External Interfaces: 1862306a36Sopenharmony_ci * <<the following list was autogenerated, please review>> 1962306a36Sopenharmony_ci * emfpudispatch(ir, dummy1, dummy2, fpregs) 2062306a36Sopenharmony_ci * fpudispatch(ir, excp_code, holder, fpregs) 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Internal Interfaces: 2362306a36Sopenharmony_ci * <<the following list was autogenerated, please review>> 2462306a36Sopenharmony_ci * static u_int decode_06(u_int, u_int *) 2562306a36Sopenharmony_ci * static u_int decode_0c(u_int, u_int, u_int, u_int *) 2662306a36Sopenharmony_ci * static u_int decode_0e(u_int, u_int, u_int, u_int *) 2762306a36Sopenharmony_ci * static u_int decode_26(u_int, u_int *) 2862306a36Sopenharmony_ci * static u_int decode_2e(u_int, u_int *) 2962306a36Sopenharmony_ci * static void update_status_cbit(u_int *, u_int, u_int, u_int) 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Theory: 3262306a36Sopenharmony_ci * <<please update with a overview of the operation of this file>> 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * END_DESC 3562306a36Sopenharmony_ci*/ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define FPUDEBUG 0 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include "float.h" 4062306a36Sopenharmony_ci#include <linux/bug.h> 4162306a36Sopenharmony_ci#include <linux/kernel.h> 4262306a36Sopenharmony_ci#include <asm/processor.h> 4362306a36Sopenharmony_ci/* #include <sys/debug.h> */ 4462306a36Sopenharmony_ci/* #include <machine/sys/mdep_private.h> */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define COPR_INST 0x30000000 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * definition of extru macro. If pos and len are constants, the compiler 5062306a36Sopenharmony_ci * will generate an extru instruction when optimized 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) 5362306a36Sopenharmony_ci/* definitions of bit field locations in the instruction */ 5462306a36Sopenharmony_ci#define fpmajorpos 5 5562306a36Sopenharmony_ci#define fpr1pos 10 5662306a36Sopenharmony_ci#define fpr2pos 15 5762306a36Sopenharmony_ci#define fptpos 31 5862306a36Sopenharmony_ci#define fpsubpos 18 5962306a36Sopenharmony_ci#define fpclass1subpos 16 6062306a36Sopenharmony_ci#define fpclasspos 22 6162306a36Sopenharmony_ci#define fpfmtpos 20 6262306a36Sopenharmony_ci#define fpdfpos 18 6362306a36Sopenharmony_ci#define fpnulpos 26 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * the following are the extra bits for the 0E major op 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_ci#define fpxr1pos 24 6862306a36Sopenharmony_ci#define fpxr2pos 19 6962306a36Sopenharmony_ci#define fpxtpos 25 7062306a36Sopenharmony_ci#define fpxpos 23 7162306a36Sopenharmony_ci#define fp0efmtpos 20 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * the following are for the multi-ops 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#define fprm1pos 10 7662306a36Sopenharmony_ci#define fprm2pos 15 7762306a36Sopenharmony_ci#define fptmpos 31 7862306a36Sopenharmony_ci#define fprapos 25 7962306a36Sopenharmony_ci#define fptapos 20 8062306a36Sopenharmony_ci#define fpmultifmt 26 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * the following are for the fused FP instructions 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci /* fprm1pos 10 */ 8562306a36Sopenharmony_ci /* fprm2pos 15 */ 8662306a36Sopenharmony_ci#define fpraupos 18 8762306a36Sopenharmony_ci#define fpxrm2pos 19 8862306a36Sopenharmony_ci /* fpfmtpos 20 */ 8962306a36Sopenharmony_ci#define fpralpos 23 9062306a36Sopenharmony_ci#define fpxrm1pos 24 9162306a36Sopenharmony_ci /* fpxtpos 25 */ 9262306a36Sopenharmony_ci#define fpfusedsubop 26 9362306a36Sopenharmony_ci /* fptpos 31 */ 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* 9662306a36Sopenharmony_ci * offset to constant zero in the FP emulation registers 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci#define fpzeroreg (32*sizeof(double)/sizeof(u_int)) 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* 10162306a36Sopenharmony_ci * extract the major opcode from the instruction 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci#define get_major(op) extru(op,fpmajorpos,6) 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci * extract the two bit class field from the FP instruction. The class is at bit 10662306a36Sopenharmony_ci * positions 21-22 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci#define get_class(op) extru(op,fpclasspos,2) 10962306a36Sopenharmony_ci/* 11062306a36Sopenharmony_ci * extract the 3 bit subop field. For all but class 1 instructions, it is 11162306a36Sopenharmony_ci * located at bit positions 16-18 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ci#define get_subop(op) extru(op,fpsubpos,3) 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * extract the 2 or 3 bit subop field from class 1 instructions. It is located 11662306a36Sopenharmony_ci * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_ci#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ 11962306a36Sopenharmony_ci#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/* definitions of unimplemented exceptions */ 12262306a36Sopenharmony_ci#define MAJOR_0C_EXCP 0x09 12362306a36Sopenharmony_ci#define MAJOR_0E_EXCP 0x0b 12462306a36Sopenharmony_ci#define MAJOR_06_EXCP 0x03 12562306a36Sopenharmony_ci#define MAJOR_26_EXCP 0x23 12662306a36Sopenharmony_ci#define MAJOR_2E_EXCP 0x2b 12762306a36Sopenharmony_ci#define PA83_UNIMP_EXCP 0x01 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* 13062306a36Sopenharmony_ci * Special Defines for TIMEX specific code 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) 13462306a36Sopenharmony_ci#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* 13762306a36Sopenharmony_ci * Static function definitions 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci#define _PROTOTYPES 14062306a36Sopenharmony_ci#if defined(_PROTOTYPES) || defined(_lint) 14162306a36Sopenharmony_cistatic u_int decode_0c(u_int, u_int, u_int, u_int *); 14262306a36Sopenharmony_cistatic u_int decode_0e(u_int, u_int, u_int, u_int *); 14362306a36Sopenharmony_cistatic u_int decode_06(u_int, u_int *); 14462306a36Sopenharmony_cistatic u_int decode_26(u_int, u_int *); 14562306a36Sopenharmony_cistatic u_int decode_2e(u_int, u_int *); 14662306a36Sopenharmony_cistatic void update_status_cbit(u_int *, u_int, u_int, u_int); 14762306a36Sopenharmony_ci#else /* !_PROTOTYPES&&!_lint */ 14862306a36Sopenharmony_cistatic u_int decode_0c(); 14962306a36Sopenharmony_cistatic u_int decode_0e(); 15062306a36Sopenharmony_cistatic u_int decode_06(); 15162306a36Sopenharmony_cistatic u_int decode_26(); 15262306a36Sopenharmony_cistatic u_int decode_2e(); 15362306a36Sopenharmony_cistatic void update_status_cbit(); 15462306a36Sopenharmony_ci#endif /* _PROTOTYPES&&!_lint */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define VASSERT(x) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic void parisc_linux_get_fpu_type(u_int fpregs[]) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci /* on pa-linux the fpu type is not filled in by the 16162306a36Sopenharmony_ci * caller; it is constructed here 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci if (boot_cpu_data.cpu_type == pcxs) 16462306a36Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG; 16562306a36Sopenharmony_ci else if (boot_cpu_data.cpu_type == pcxt || 16662306a36Sopenharmony_ci boot_cpu_data.cpu_type == pcxt_) 16762306a36Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG; 16862306a36Sopenharmony_ci else if (boot_cpu_data.cpu_type >= pcxu) 16962306a36Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* 17362306a36Sopenharmony_ci * this routine will decode the excepting floating point instruction and 17462306a36Sopenharmony_ci * call the appropriate emulation routine. 17562306a36Sopenharmony_ci * It is called by decode_fpu with the following parameters: 17662306a36Sopenharmony_ci * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) 17762306a36Sopenharmony_ci * where current_ir is the instruction to be emulated, 17862306a36Sopenharmony_ci * unimplemented_code is the exception_code that the hardware generated 17962306a36Sopenharmony_ci * and &Fpu_register is the address of emulated FP reg 0. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ciu_int 18262306a36Sopenharmony_cifpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci u_int class, subop; 18562306a36Sopenharmony_ci u_int fpu_type_flags; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* All FP emulation code assumes that ints are 4-bytes in length */ 18862306a36Sopenharmony_ci VASSERT(sizeof(int) == 4); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci parisc_linux_get_fpu_type(fpregs); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci class = get_class(ir); 19562306a36Sopenharmony_ci if (class == 1) { 19662306a36Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) 19762306a36Sopenharmony_ci subop = get_subop1_PA2_0(ir); 19862306a36Sopenharmony_ci else 19962306a36Sopenharmony_ci subop = get_subop1_PA1_1(ir); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci else 20262306a36Sopenharmony_ci subop = get_subop(ir); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (FPUDEBUG) printk("class %d subop %d\n", class, subop); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci switch (excp_code) { 20762306a36Sopenharmony_ci case MAJOR_0C_EXCP: 20862306a36Sopenharmony_ci case PA83_UNIMP_EXCP: 20962306a36Sopenharmony_ci return(decode_0c(ir,class,subop,fpregs)); 21062306a36Sopenharmony_ci case MAJOR_0E_EXCP: 21162306a36Sopenharmony_ci return(decode_0e(ir,class,subop,fpregs)); 21262306a36Sopenharmony_ci case MAJOR_06_EXCP: 21362306a36Sopenharmony_ci return(decode_06(ir,fpregs)); 21462306a36Sopenharmony_ci case MAJOR_26_EXCP: 21562306a36Sopenharmony_ci return(decode_26(ir,fpregs)); 21662306a36Sopenharmony_ci case MAJOR_2E_EXCP: 21762306a36Sopenharmony_ci return(decode_2e(ir,fpregs)); 21862306a36Sopenharmony_ci default: 21962306a36Sopenharmony_ci /* "crashme Night Gallery painting nr 2. (asm_crash.s). 22062306a36Sopenharmony_ci * This was fixed for multi-user kernels, but 22162306a36Sopenharmony_ci * workstation kernels had a panic here. This allowed 22262306a36Sopenharmony_ci * any arbitrary user to panic the kernel by executing 22362306a36Sopenharmony_ci * setting the FP exception registers to strange values 22462306a36Sopenharmony_ci * and generating an emulation trap. The emulation and 22562306a36Sopenharmony_ci * exception code must never be able to panic the 22662306a36Sopenharmony_ci * kernel. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci return(UNIMPLEMENTEDEXCEPTION); 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/* 23362306a36Sopenharmony_ci * this routine is called by $emulation_trap to emulate a coprocessor 23462306a36Sopenharmony_ci * instruction if one doesn't exist 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ciu_int 23762306a36Sopenharmony_ciemfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci u_int class, subop, major; 24062306a36Sopenharmony_ci u_int fpu_type_flags; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* All FP emulation code assumes that ints are 4-bytes in length */ 24362306a36Sopenharmony_ci VASSERT(sizeof(int) == 4); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci major = get_major(ir); 24862306a36Sopenharmony_ci class = get_class(ir); 24962306a36Sopenharmony_ci if (class == 1) { 25062306a36Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) 25162306a36Sopenharmony_ci subop = get_subop1_PA2_0(ir); 25262306a36Sopenharmony_ci else 25362306a36Sopenharmony_ci subop = get_subop1_PA1_1(ir); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci else 25662306a36Sopenharmony_ci subop = get_subop(ir); 25762306a36Sopenharmony_ci switch (major) { 25862306a36Sopenharmony_ci case 0x0C: 25962306a36Sopenharmony_ci return(decode_0c(ir,class,subop,fpregs)); 26062306a36Sopenharmony_ci case 0x0E: 26162306a36Sopenharmony_ci return(decode_0e(ir,class,subop,fpregs)); 26262306a36Sopenharmony_ci case 0x06: 26362306a36Sopenharmony_ci return(decode_06(ir,fpregs)); 26462306a36Sopenharmony_ci case 0x26: 26562306a36Sopenharmony_ci return(decode_26(ir,fpregs)); 26662306a36Sopenharmony_ci case 0x2E: 26762306a36Sopenharmony_ci return(decode_2e(ir,fpregs)); 26862306a36Sopenharmony_ci default: 26962306a36Sopenharmony_ci return(PA83_UNIMP_EXCP); 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic u_int 27562306a36Sopenharmony_cidecode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci u_int r1,r2,t; /* operand register offsets */ 27862306a36Sopenharmony_ci u_int fmt; /* also sf for class 1 conversions */ 27962306a36Sopenharmony_ci u_int df; /* for class 1 conversions */ 28062306a36Sopenharmony_ci u_int *status; 28162306a36Sopenharmony_ci u_int retval, local_status; 28262306a36Sopenharmony_ci u_int fpu_type_flags; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (ir == COPR_INST) { 28562306a36Sopenharmony_ci fpregs[0] = EMULATION_VERSION << 11; 28662306a36Sopenharmony_ci return(NOEXCEPTION); 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci status = &fpregs[0]; /* fp status register */ 28962306a36Sopenharmony_ci local_status = fpregs[0]; /* and local copy */ 29062306a36Sopenharmony_ci r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); 29162306a36Sopenharmony_ci if (r1 == 0) /* map fr0 source to constant zero */ 29262306a36Sopenharmony_ci r1 = fpzeroreg; 29362306a36Sopenharmony_ci t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 29462306a36Sopenharmony_ci if (t == 0 && class != 2) /* don't allow fr0 as a dest */ 29562306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 29662306a36Sopenharmony_ci fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci switch (class) { 29962306a36Sopenharmony_ci case 0: 30062306a36Sopenharmony_ci switch (subop) { 30162306a36Sopenharmony_ci case 0: /* COPR 0,0 emulated above*/ 30262306a36Sopenharmony_ci case 1: 30362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 30462306a36Sopenharmony_ci case 2: /* FCPY */ 30562306a36Sopenharmony_ci switch (fmt) { 30662306a36Sopenharmony_ci case 2: /* illegal */ 30762306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 30862306a36Sopenharmony_ci case 3: /* quad */ 30962306a36Sopenharmony_ci t &= ~3; /* force to even reg #s */ 31062306a36Sopenharmony_ci r1 &= ~3; 31162306a36Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 31262306a36Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 31362306a36Sopenharmony_ci fallthrough; 31462306a36Sopenharmony_ci case 1: /* double */ 31562306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 31662306a36Sopenharmony_ci fallthrough; 31762306a36Sopenharmony_ci case 0: /* single */ 31862306a36Sopenharmony_ci fpregs[t] = fpregs[r1]; 31962306a36Sopenharmony_ci return(NOEXCEPTION); 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci BUG(); 32262306a36Sopenharmony_ci case 3: /* FABS */ 32362306a36Sopenharmony_ci switch (fmt) { 32462306a36Sopenharmony_ci case 2: /* illegal */ 32562306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 32662306a36Sopenharmony_ci case 3: /* quad */ 32762306a36Sopenharmony_ci t &= ~3; /* force to even reg #s */ 32862306a36Sopenharmony_ci r1 &= ~3; 32962306a36Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 33062306a36Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 33162306a36Sopenharmony_ci fallthrough; 33262306a36Sopenharmony_ci case 1: /* double */ 33362306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 33462306a36Sopenharmony_ci fallthrough; 33562306a36Sopenharmony_ci case 0: /* single */ 33662306a36Sopenharmony_ci /* copy and clear sign bit */ 33762306a36Sopenharmony_ci fpregs[t] = fpregs[r1] & 0x7fffffff; 33862306a36Sopenharmony_ci return(NOEXCEPTION); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci BUG(); 34162306a36Sopenharmony_ci case 6: /* FNEG */ 34262306a36Sopenharmony_ci switch (fmt) { 34362306a36Sopenharmony_ci case 2: /* illegal */ 34462306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 34562306a36Sopenharmony_ci case 3: /* quad */ 34662306a36Sopenharmony_ci t &= ~3; /* force to even reg #s */ 34762306a36Sopenharmony_ci r1 &= ~3; 34862306a36Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 34962306a36Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 35062306a36Sopenharmony_ci fallthrough; 35162306a36Sopenharmony_ci case 1: /* double */ 35262306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 35362306a36Sopenharmony_ci fallthrough; 35462306a36Sopenharmony_ci case 0: /* single */ 35562306a36Sopenharmony_ci /* copy and invert sign bit */ 35662306a36Sopenharmony_ci fpregs[t] = fpregs[r1] ^ 0x80000000; 35762306a36Sopenharmony_ci return(NOEXCEPTION); 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci BUG(); 36062306a36Sopenharmony_ci case 7: /* FNEGABS */ 36162306a36Sopenharmony_ci switch (fmt) { 36262306a36Sopenharmony_ci case 2: /* illegal */ 36362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 36462306a36Sopenharmony_ci case 3: /* quad */ 36562306a36Sopenharmony_ci t &= ~3; /* force to even reg #s */ 36662306a36Sopenharmony_ci r1 &= ~3; 36762306a36Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 36862306a36Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 36962306a36Sopenharmony_ci fallthrough; 37062306a36Sopenharmony_ci case 1: /* double */ 37162306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 37262306a36Sopenharmony_ci fallthrough; 37362306a36Sopenharmony_ci case 0: /* single */ 37462306a36Sopenharmony_ci /* copy and set sign bit */ 37562306a36Sopenharmony_ci fpregs[t] = fpregs[r1] | 0x80000000; 37662306a36Sopenharmony_ci return(NOEXCEPTION); 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci BUG(); 37962306a36Sopenharmony_ci case 4: /* FSQRT */ 38062306a36Sopenharmony_ci switch (fmt) { 38162306a36Sopenharmony_ci case 0: 38262306a36Sopenharmony_ci return(sgl_fsqrt(&fpregs[r1],0, 38362306a36Sopenharmony_ci &fpregs[t],status)); 38462306a36Sopenharmony_ci case 1: 38562306a36Sopenharmony_ci return(dbl_fsqrt(&fpregs[r1],0, 38662306a36Sopenharmony_ci &fpregs[t],status)); 38762306a36Sopenharmony_ci case 2: 38862306a36Sopenharmony_ci case 3: /* quad not implemented */ 38962306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci BUG(); 39262306a36Sopenharmony_ci case 5: /* FRND */ 39362306a36Sopenharmony_ci switch (fmt) { 39462306a36Sopenharmony_ci case 0: 39562306a36Sopenharmony_ci return(sgl_frnd(&fpregs[r1],0, 39662306a36Sopenharmony_ci &fpregs[t],status)); 39762306a36Sopenharmony_ci case 1: 39862306a36Sopenharmony_ci return(dbl_frnd(&fpregs[r1],0, 39962306a36Sopenharmony_ci &fpregs[t],status)); 40062306a36Sopenharmony_ci case 2: 40162306a36Sopenharmony_ci case 3: /* quad not implemented */ 40262306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci } /* end of switch (subop) */ 40562306a36Sopenharmony_ci BUG(); 40662306a36Sopenharmony_ci case 1: /* class 1 */ 40762306a36Sopenharmony_ci df = extru(ir,fpdfpos,2); /* get dest format */ 40862306a36Sopenharmony_ci if ((df & 2) || (fmt & 2)) { 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * fmt's 2 and 3 are illegal of not implemented 41162306a36Sopenharmony_ci * quad conversions 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci /* 41662306a36Sopenharmony_ci * encode source and dest formats into 2 bits. 41762306a36Sopenharmony_ci * high bit is source, low bit is dest. 41862306a36Sopenharmony_ci * bit = 1 --> double precision 41962306a36Sopenharmony_ci */ 42062306a36Sopenharmony_ci fmt = (fmt << 1) | df; 42162306a36Sopenharmony_ci switch (subop) { 42262306a36Sopenharmony_ci case 0: /* FCNVFF */ 42362306a36Sopenharmony_ci switch(fmt) { 42462306a36Sopenharmony_ci case 0: /* sgl/sgl */ 42562306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 42662306a36Sopenharmony_ci case 1: /* sgl/dbl */ 42762306a36Sopenharmony_ci return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 42862306a36Sopenharmony_ci &fpregs[t],status)); 42962306a36Sopenharmony_ci case 2: /* dbl/sgl */ 43062306a36Sopenharmony_ci return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 43162306a36Sopenharmony_ci &fpregs[t],status)); 43262306a36Sopenharmony_ci case 3: /* dbl/dbl */ 43362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci BUG(); 43662306a36Sopenharmony_ci case 1: /* FCNVXF */ 43762306a36Sopenharmony_ci switch(fmt) { 43862306a36Sopenharmony_ci case 0: /* sgl/sgl */ 43962306a36Sopenharmony_ci return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 44062306a36Sopenharmony_ci &fpregs[t],status)); 44162306a36Sopenharmony_ci case 1: /* sgl/dbl */ 44262306a36Sopenharmony_ci return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 44362306a36Sopenharmony_ci &fpregs[t],status)); 44462306a36Sopenharmony_ci case 2: /* dbl/sgl */ 44562306a36Sopenharmony_ci return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 44662306a36Sopenharmony_ci &fpregs[t],status)); 44762306a36Sopenharmony_ci case 3: /* dbl/dbl */ 44862306a36Sopenharmony_ci return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 44962306a36Sopenharmony_ci &fpregs[t],status)); 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci BUG(); 45262306a36Sopenharmony_ci case 2: /* FCNVFX */ 45362306a36Sopenharmony_ci switch(fmt) { 45462306a36Sopenharmony_ci case 0: /* sgl/sgl */ 45562306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 45662306a36Sopenharmony_ci &fpregs[t],status)); 45762306a36Sopenharmony_ci case 1: /* sgl/dbl */ 45862306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 45962306a36Sopenharmony_ci &fpregs[t],status)); 46062306a36Sopenharmony_ci case 2: /* dbl/sgl */ 46162306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 46262306a36Sopenharmony_ci &fpregs[t],status)); 46362306a36Sopenharmony_ci case 3: /* dbl/dbl */ 46462306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 46562306a36Sopenharmony_ci &fpregs[t],status)); 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci BUG(); 46862306a36Sopenharmony_ci case 3: /* FCNVFXT */ 46962306a36Sopenharmony_ci switch(fmt) { 47062306a36Sopenharmony_ci case 0: /* sgl/sgl */ 47162306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 47262306a36Sopenharmony_ci &fpregs[t],status)); 47362306a36Sopenharmony_ci case 1: /* sgl/dbl */ 47462306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 47562306a36Sopenharmony_ci &fpregs[t],status)); 47662306a36Sopenharmony_ci case 2: /* dbl/sgl */ 47762306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 47862306a36Sopenharmony_ci &fpregs[t],status)); 47962306a36Sopenharmony_ci case 3: /* dbl/dbl */ 48062306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 48162306a36Sopenharmony_ci &fpregs[t],status)); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci BUG(); 48462306a36Sopenharmony_ci case 5: /* FCNVUF (PA2.0 only) */ 48562306a36Sopenharmony_ci switch(fmt) { 48662306a36Sopenharmony_ci case 0: /* sgl/sgl */ 48762306a36Sopenharmony_ci return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 48862306a36Sopenharmony_ci &fpregs[t],status)); 48962306a36Sopenharmony_ci case 1: /* sgl/dbl */ 49062306a36Sopenharmony_ci return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 49162306a36Sopenharmony_ci &fpregs[t],status)); 49262306a36Sopenharmony_ci case 2: /* dbl/sgl */ 49362306a36Sopenharmony_ci return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 49462306a36Sopenharmony_ci &fpregs[t],status)); 49562306a36Sopenharmony_ci case 3: /* dbl/dbl */ 49662306a36Sopenharmony_ci return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 49762306a36Sopenharmony_ci &fpregs[t],status)); 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci BUG(); 50062306a36Sopenharmony_ci case 6: /* FCNVFU (PA2.0 only) */ 50162306a36Sopenharmony_ci switch(fmt) { 50262306a36Sopenharmony_ci case 0: /* sgl/sgl */ 50362306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 50462306a36Sopenharmony_ci &fpregs[t],status)); 50562306a36Sopenharmony_ci case 1: /* sgl/dbl */ 50662306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 50762306a36Sopenharmony_ci &fpregs[t],status)); 50862306a36Sopenharmony_ci case 2: /* dbl/sgl */ 50962306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 51062306a36Sopenharmony_ci &fpregs[t],status)); 51162306a36Sopenharmony_ci case 3: /* dbl/dbl */ 51262306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 51362306a36Sopenharmony_ci &fpregs[t],status)); 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci BUG(); 51662306a36Sopenharmony_ci case 7: /* FCNVFUT (PA2.0 only) */ 51762306a36Sopenharmony_ci switch(fmt) { 51862306a36Sopenharmony_ci case 0: /* sgl/sgl */ 51962306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 52062306a36Sopenharmony_ci &fpregs[t],status)); 52162306a36Sopenharmony_ci case 1: /* sgl/dbl */ 52262306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 52362306a36Sopenharmony_ci &fpregs[t],status)); 52462306a36Sopenharmony_ci case 2: /* dbl/sgl */ 52562306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 52662306a36Sopenharmony_ci &fpregs[t],status)); 52762306a36Sopenharmony_ci case 3: /* dbl/dbl */ 52862306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 52962306a36Sopenharmony_ci &fpregs[t],status)); 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci BUG(); 53262306a36Sopenharmony_ci case 4: /* undefined */ 53362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 53462306a36Sopenharmony_ci } /* end of switch subop */ 53562306a36Sopenharmony_ci BUG(); 53662306a36Sopenharmony_ci case 2: /* class 2 */ 53762306a36Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 53862306a36Sopenharmony_ci r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); 53962306a36Sopenharmony_ci if (r2 == 0) 54062306a36Sopenharmony_ci r2 = fpzeroreg; 54162306a36Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) { 54262306a36Sopenharmony_ci /* FTEST if nullify bit set, otherwise FCMP */ 54362306a36Sopenharmony_ci if (extru(ir, fpnulpos, 1)) { /* FTEST */ 54462306a36Sopenharmony_ci switch (fmt) { 54562306a36Sopenharmony_ci case 0: 54662306a36Sopenharmony_ci /* 54762306a36Sopenharmony_ci * arg0 is not used 54862306a36Sopenharmony_ci * second param is the t field used for 54962306a36Sopenharmony_ci * ftest,acc and ftest,rej 55062306a36Sopenharmony_ci * third param is the subop (y-field) 55162306a36Sopenharmony_ci */ 55262306a36Sopenharmony_ci BUG(); 55362306a36Sopenharmony_ci /* Unsupported 55462306a36Sopenharmony_ci * return(ftest(0L,extru(ir,fptpos,5), 55562306a36Sopenharmony_ci * &fpregs[0],subop)); 55662306a36Sopenharmony_ci */ 55762306a36Sopenharmony_ci case 1: 55862306a36Sopenharmony_ci case 2: 55962306a36Sopenharmony_ci case 3: 56062306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci } else { /* FCMP */ 56362306a36Sopenharmony_ci switch (fmt) { 56462306a36Sopenharmony_ci case 0: 56562306a36Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 56662306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 56762306a36Sopenharmony_ci &local_status); 56862306a36Sopenharmony_ci update_status_cbit(status,local_status, 56962306a36Sopenharmony_ci fpu_type_flags, subop); 57062306a36Sopenharmony_ci return(retval); 57162306a36Sopenharmony_ci case 1: 57262306a36Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 57362306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 57462306a36Sopenharmony_ci &local_status); 57562306a36Sopenharmony_ci update_status_cbit(status,local_status, 57662306a36Sopenharmony_ci fpu_type_flags, subop); 57762306a36Sopenharmony_ci return(retval); 57862306a36Sopenharmony_ci case 2: /* illegal */ 57962306a36Sopenharmony_ci case 3: /* quad not implemented */ 58062306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci } /* end of if for PA2.0 */ 58462306a36Sopenharmony_ci else { /* PA1.0 & PA1.1 */ 58562306a36Sopenharmony_ci switch (subop) { 58662306a36Sopenharmony_ci case 2: 58762306a36Sopenharmony_ci case 3: 58862306a36Sopenharmony_ci case 4: 58962306a36Sopenharmony_ci case 5: 59062306a36Sopenharmony_ci case 6: 59162306a36Sopenharmony_ci case 7: 59262306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 59362306a36Sopenharmony_ci case 0: /* FCMP */ 59462306a36Sopenharmony_ci switch (fmt) { 59562306a36Sopenharmony_ci case 0: 59662306a36Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 59762306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 59862306a36Sopenharmony_ci &local_status); 59962306a36Sopenharmony_ci update_status_cbit(status,local_status, 60062306a36Sopenharmony_ci fpu_type_flags, subop); 60162306a36Sopenharmony_ci return(retval); 60262306a36Sopenharmony_ci case 1: 60362306a36Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 60462306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 60562306a36Sopenharmony_ci &local_status); 60662306a36Sopenharmony_ci update_status_cbit(status,local_status, 60762306a36Sopenharmony_ci fpu_type_flags, subop); 60862306a36Sopenharmony_ci return(retval); 60962306a36Sopenharmony_ci case 2: /* illegal */ 61062306a36Sopenharmony_ci case 3: /* quad not implemented */ 61162306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci BUG(); 61462306a36Sopenharmony_ci case 1: /* FTEST */ 61562306a36Sopenharmony_ci switch (fmt) { 61662306a36Sopenharmony_ci case 0: 61762306a36Sopenharmony_ci /* 61862306a36Sopenharmony_ci * arg0 is not used 61962306a36Sopenharmony_ci * second param is the t field used for 62062306a36Sopenharmony_ci * ftest,acc and ftest,rej 62162306a36Sopenharmony_ci * third param is the subop (y-field) 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci BUG(); 62462306a36Sopenharmony_ci /* unsupported 62562306a36Sopenharmony_ci * return(ftest(0L,extru(ir,fptpos,5), 62662306a36Sopenharmony_ci * &fpregs[0],subop)); 62762306a36Sopenharmony_ci */ 62862306a36Sopenharmony_ci case 1: 62962306a36Sopenharmony_ci case 2: 63062306a36Sopenharmony_ci case 3: 63162306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci BUG(); 63462306a36Sopenharmony_ci } /* end of switch subop */ 63562306a36Sopenharmony_ci } /* end of else for PA1.0 & PA1.1 */ 63662306a36Sopenharmony_ci BUG(); 63762306a36Sopenharmony_ci case 3: /* class 3 */ 63862306a36Sopenharmony_ci r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); 63962306a36Sopenharmony_ci if (r2 == 0) 64062306a36Sopenharmony_ci r2 = fpzeroreg; 64162306a36Sopenharmony_ci switch (subop) { 64262306a36Sopenharmony_ci case 5: 64362306a36Sopenharmony_ci case 6: 64462306a36Sopenharmony_ci case 7: 64562306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci case 0: /* FADD */ 64862306a36Sopenharmony_ci switch (fmt) { 64962306a36Sopenharmony_ci case 0: 65062306a36Sopenharmony_ci return(sgl_fadd(&fpregs[r1],&fpregs[r2], 65162306a36Sopenharmony_ci &fpregs[t],status)); 65262306a36Sopenharmony_ci case 1: 65362306a36Sopenharmony_ci return(dbl_fadd(&fpregs[r1],&fpregs[r2], 65462306a36Sopenharmony_ci &fpregs[t],status)); 65562306a36Sopenharmony_ci case 2: /* illegal */ 65662306a36Sopenharmony_ci case 3: /* quad not implemented */ 65762306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci BUG(); 66062306a36Sopenharmony_ci case 1: /* FSUB */ 66162306a36Sopenharmony_ci switch (fmt) { 66262306a36Sopenharmony_ci case 0: 66362306a36Sopenharmony_ci return(sgl_fsub(&fpregs[r1],&fpregs[r2], 66462306a36Sopenharmony_ci &fpregs[t],status)); 66562306a36Sopenharmony_ci case 1: 66662306a36Sopenharmony_ci return(dbl_fsub(&fpregs[r1],&fpregs[r2], 66762306a36Sopenharmony_ci &fpregs[t],status)); 66862306a36Sopenharmony_ci case 2: /* illegal */ 66962306a36Sopenharmony_ci case 3: /* quad not implemented */ 67062306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci BUG(); 67362306a36Sopenharmony_ci case 2: /* FMPY */ 67462306a36Sopenharmony_ci switch (fmt) { 67562306a36Sopenharmony_ci case 0: 67662306a36Sopenharmony_ci return(sgl_fmpy(&fpregs[r1],&fpregs[r2], 67762306a36Sopenharmony_ci &fpregs[t],status)); 67862306a36Sopenharmony_ci case 1: 67962306a36Sopenharmony_ci return(dbl_fmpy(&fpregs[r1],&fpregs[r2], 68062306a36Sopenharmony_ci &fpregs[t],status)); 68162306a36Sopenharmony_ci case 2: /* illegal */ 68262306a36Sopenharmony_ci case 3: /* quad not implemented */ 68362306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci BUG(); 68662306a36Sopenharmony_ci case 3: /* FDIV */ 68762306a36Sopenharmony_ci switch (fmt) { 68862306a36Sopenharmony_ci case 0: 68962306a36Sopenharmony_ci return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 69062306a36Sopenharmony_ci &fpregs[t],status)); 69162306a36Sopenharmony_ci case 1: 69262306a36Sopenharmony_ci return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 69362306a36Sopenharmony_ci &fpregs[t],status)); 69462306a36Sopenharmony_ci case 2: /* illegal */ 69562306a36Sopenharmony_ci case 3: /* quad not implemented */ 69662306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci BUG(); 69962306a36Sopenharmony_ci case 4: /* FREM */ 70062306a36Sopenharmony_ci switch (fmt) { 70162306a36Sopenharmony_ci case 0: 70262306a36Sopenharmony_ci return(sgl_frem(&fpregs[r1],&fpregs[r2], 70362306a36Sopenharmony_ci &fpregs[t],status)); 70462306a36Sopenharmony_ci case 1: 70562306a36Sopenharmony_ci return(dbl_frem(&fpregs[r1],&fpregs[r2], 70662306a36Sopenharmony_ci &fpregs[t],status)); 70762306a36Sopenharmony_ci case 2: /* illegal */ 70862306a36Sopenharmony_ci case 3: /* quad not implemented */ 70962306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci BUG(); 71262306a36Sopenharmony_ci } /* end of class 3 switch */ 71362306a36Sopenharmony_ci } /* end of switch(class) */ 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci /* If we get here, something is really wrong! */ 71662306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic u_int 72062306a36Sopenharmony_cidecode_0e(ir,class,subop,fpregs) 72162306a36Sopenharmony_ciu_int ir,class,subop; 72262306a36Sopenharmony_ciu_int fpregs[]; 72362306a36Sopenharmony_ci{ 72462306a36Sopenharmony_ci u_int r1,r2,t; /* operand register offsets */ 72562306a36Sopenharmony_ci u_int fmt; /* also sf for class 1 conversions */ 72662306a36Sopenharmony_ci u_int df; /* dest format for class 1 conversions */ 72762306a36Sopenharmony_ci u_int *status; 72862306a36Sopenharmony_ci u_int retval, local_status; 72962306a36Sopenharmony_ci u_int fpu_type_flags; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci status = &fpregs[0]; 73262306a36Sopenharmony_ci local_status = fpregs[0]; 73362306a36Sopenharmony_ci r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); 73462306a36Sopenharmony_ci if (r1 == 0) 73562306a36Sopenharmony_ci r1 = fpzeroreg; 73662306a36Sopenharmony_ci t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 73762306a36Sopenharmony_ci if (t == 0 && class != 2) 73862306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 73962306a36Sopenharmony_ci if (class < 2) /* class 0 or 1 has 2 bit fmt */ 74062306a36Sopenharmony_ci fmt = extru(ir,fpfmtpos,2); 74162306a36Sopenharmony_ci else /* class 2 and 3 have 1 bit fmt */ 74262306a36Sopenharmony_ci fmt = extru(ir,fp0efmtpos,1); 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * An undefined combination, double precision accessing the 74562306a36Sopenharmony_ci * right half of a FPR, can get us into trouble. 74662306a36Sopenharmony_ci * Let's just force proper alignment on it. 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_ci if (fmt == DBL) { 74962306a36Sopenharmony_ci r1 &= ~1; 75062306a36Sopenharmony_ci if (class != 1) 75162306a36Sopenharmony_ci t &= ~1; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci switch (class) { 75562306a36Sopenharmony_ci case 0: 75662306a36Sopenharmony_ci switch (subop) { 75762306a36Sopenharmony_ci case 0: /* unimplemented */ 75862306a36Sopenharmony_ci case 1: 75962306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 76062306a36Sopenharmony_ci case 2: /* FCPY */ 76162306a36Sopenharmony_ci switch (fmt) { 76262306a36Sopenharmony_ci case 2: 76362306a36Sopenharmony_ci case 3: 76462306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 76562306a36Sopenharmony_ci case 1: /* double */ 76662306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 76762306a36Sopenharmony_ci fallthrough; 76862306a36Sopenharmony_ci case 0: /* single */ 76962306a36Sopenharmony_ci fpregs[t] = fpregs[r1]; 77062306a36Sopenharmony_ci return(NOEXCEPTION); 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci BUG(); 77362306a36Sopenharmony_ci case 3: /* FABS */ 77462306a36Sopenharmony_ci switch (fmt) { 77562306a36Sopenharmony_ci case 2: 77662306a36Sopenharmony_ci case 3: 77762306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 77862306a36Sopenharmony_ci case 1: /* double */ 77962306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 78062306a36Sopenharmony_ci fallthrough; 78162306a36Sopenharmony_ci case 0: /* single */ 78262306a36Sopenharmony_ci fpregs[t] = fpregs[r1] & 0x7fffffff; 78362306a36Sopenharmony_ci return(NOEXCEPTION); 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci BUG(); 78662306a36Sopenharmony_ci case 6: /* FNEG */ 78762306a36Sopenharmony_ci switch (fmt) { 78862306a36Sopenharmony_ci case 2: 78962306a36Sopenharmony_ci case 3: 79062306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 79162306a36Sopenharmony_ci case 1: /* double */ 79262306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 79362306a36Sopenharmony_ci fallthrough; 79462306a36Sopenharmony_ci case 0: /* single */ 79562306a36Sopenharmony_ci fpregs[t] = fpregs[r1] ^ 0x80000000; 79662306a36Sopenharmony_ci return(NOEXCEPTION); 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci BUG(); 79962306a36Sopenharmony_ci case 7: /* FNEGABS */ 80062306a36Sopenharmony_ci switch (fmt) { 80162306a36Sopenharmony_ci case 2: 80262306a36Sopenharmony_ci case 3: 80362306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 80462306a36Sopenharmony_ci case 1: /* double */ 80562306a36Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 80662306a36Sopenharmony_ci fallthrough; 80762306a36Sopenharmony_ci case 0: /* single */ 80862306a36Sopenharmony_ci fpregs[t] = fpregs[r1] | 0x80000000; 80962306a36Sopenharmony_ci return(NOEXCEPTION); 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci BUG(); 81262306a36Sopenharmony_ci case 4: /* FSQRT */ 81362306a36Sopenharmony_ci switch (fmt) { 81462306a36Sopenharmony_ci case 0: 81562306a36Sopenharmony_ci return(sgl_fsqrt(&fpregs[r1],0, 81662306a36Sopenharmony_ci &fpregs[t], status)); 81762306a36Sopenharmony_ci case 1: 81862306a36Sopenharmony_ci return(dbl_fsqrt(&fpregs[r1],0, 81962306a36Sopenharmony_ci &fpregs[t], status)); 82062306a36Sopenharmony_ci case 2: 82162306a36Sopenharmony_ci case 3: 82262306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci BUG(); 82562306a36Sopenharmony_ci case 5: /* FRMD */ 82662306a36Sopenharmony_ci switch (fmt) { 82762306a36Sopenharmony_ci case 0: 82862306a36Sopenharmony_ci return(sgl_frnd(&fpregs[r1],0, 82962306a36Sopenharmony_ci &fpregs[t], status)); 83062306a36Sopenharmony_ci case 1: 83162306a36Sopenharmony_ci return(dbl_frnd(&fpregs[r1],0, 83262306a36Sopenharmony_ci &fpregs[t], status)); 83362306a36Sopenharmony_ci case 2: 83462306a36Sopenharmony_ci case 3: 83562306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci } /* end of switch (subop */ 83862306a36Sopenharmony_ci BUG(); 83962306a36Sopenharmony_ci case 1: /* class 1 */ 84062306a36Sopenharmony_ci df = extru(ir,fpdfpos,2); /* get dest format */ 84162306a36Sopenharmony_ci /* 84262306a36Sopenharmony_ci * Fix Crashme problem (writing to 31R in double precision) 84362306a36Sopenharmony_ci * here too. 84462306a36Sopenharmony_ci */ 84562306a36Sopenharmony_ci if (df == DBL) { 84662306a36Sopenharmony_ci t &= ~1; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci if ((df & 2) || (fmt & 2)) 84962306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci fmt = (fmt << 1) | df; 85262306a36Sopenharmony_ci switch (subop) { 85362306a36Sopenharmony_ci case 0: /* FCNVFF */ 85462306a36Sopenharmony_ci switch(fmt) { 85562306a36Sopenharmony_ci case 0: /* sgl/sgl */ 85662306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 85762306a36Sopenharmony_ci case 1: /* sgl/dbl */ 85862306a36Sopenharmony_ci return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 85962306a36Sopenharmony_ci &fpregs[t],status)); 86062306a36Sopenharmony_ci case 2: /* dbl/sgl */ 86162306a36Sopenharmony_ci return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 86262306a36Sopenharmony_ci &fpregs[t],status)); 86362306a36Sopenharmony_ci case 3: /* dbl/dbl */ 86462306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci BUG(); 86762306a36Sopenharmony_ci case 1: /* FCNVXF */ 86862306a36Sopenharmony_ci switch(fmt) { 86962306a36Sopenharmony_ci case 0: /* sgl/sgl */ 87062306a36Sopenharmony_ci return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 87162306a36Sopenharmony_ci &fpregs[t],status)); 87262306a36Sopenharmony_ci case 1: /* sgl/dbl */ 87362306a36Sopenharmony_ci return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 87462306a36Sopenharmony_ci &fpregs[t],status)); 87562306a36Sopenharmony_ci case 2: /* dbl/sgl */ 87662306a36Sopenharmony_ci return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 87762306a36Sopenharmony_ci &fpregs[t],status)); 87862306a36Sopenharmony_ci case 3: /* dbl/dbl */ 87962306a36Sopenharmony_ci return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 88062306a36Sopenharmony_ci &fpregs[t],status)); 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci BUG(); 88362306a36Sopenharmony_ci case 2: /* FCNVFX */ 88462306a36Sopenharmony_ci switch(fmt) { 88562306a36Sopenharmony_ci case 0: /* sgl/sgl */ 88662306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 88762306a36Sopenharmony_ci &fpregs[t],status)); 88862306a36Sopenharmony_ci case 1: /* sgl/dbl */ 88962306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 89062306a36Sopenharmony_ci &fpregs[t],status)); 89162306a36Sopenharmony_ci case 2: /* dbl/sgl */ 89262306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 89362306a36Sopenharmony_ci &fpregs[t],status)); 89462306a36Sopenharmony_ci case 3: /* dbl/dbl */ 89562306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 89662306a36Sopenharmony_ci &fpregs[t],status)); 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci BUG(); 89962306a36Sopenharmony_ci case 3: /* FCNVFXT */ 90062306a36Sopenharmony_ci switch(fmt) { 90162306a36Sopenharmony_ci case 0: /* sgl/sgl */ 90262306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 90362306a36Sopenharmony_ci &fpregs[t],status)); 90462306a36Sopenharmony_ci case 1: /* sgl/dbl */ 90562306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 90662306a36Sopenharmony_ci &fpregs[t],status)); 90762306a36Sopenharmony_ci case 2: /* dbl/sgl */ 90862306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 90962306a36Sopenharmony_ci &fpregs[t],status)); 91062306a36Sopenharmony_ci case 3: /* dbl/dbl */ 91162306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 91262306a36Sopenharmony_ci &fpregs[t],status)); 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci BUG(); 91562306a36Sopenharmony_ci case 5: /* FCNVUF (PA2.0 only) */ 91662306a36Sopenharmony_ci switch(fmt) { 91762306a36Sopenharmony_ci case 0: /* sgl/sgl */ 91862306a36Sopenharmony_ci return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 91962306a36Sopenharmony_ci &fpregs[t],status)); 92062306a36Sopenharmony_ci case 1: /* sgl/dbl */ 92162306a36Sopenharmony_ci return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 92262306a36Sopenharmony_ci &fpregs[t],status)); 92362306a36Sopenharmony_ci case 2: /* dbl/sgl */ 92462306a36Sopenharmony_ci return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 92562306a36Sopenharmony_ci &fpregs[t],status)); 92662306a36Sopenharmony_ci case 3: /* dbl/dbl */ 92762306a36Sopenharmony_ci return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 92862306a36Sopenharmony_ci &fpregs[t],status)); 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci BUG(); 93162306a36Sopenharmony_ci case 6: /* FCNVFU (PA2.0 only) */ 93262306a36Sopenharmony_ci switch(fmt) { 93362306a36Sopenharmony_ci case 0: /* sgl/sgl */ 93462306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 93562306a36Sopenharmony_ci &fpregs[t],status)); 93662306a36Sopenharmony_ci case 1: /* sgl/dbl */ 93762306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 93862306a36Sopenharmony_ci &fpregs[t],status)); 93962306a36Sopenharmony_ci case 2: /* dbl/sgl */ 94062306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 94162306a36Sopenharmony_ci &fpregs[t],status)); 94262306a36Sopenharmony_ci case 3: /* dbl/dbl */ 94362306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 94462306a36Sopenharmony_ci &fpregs[t],status)); 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci BUG(); 94762306a36Sopenharmony_ci case 7: /* FCNVFUT (PA2.0 only) */ 94862306a36Sopenharmony_ci switch(fmt) { 94962306a36Sopenharmony_ci case 0: /* sgl/sgl */ 95062306a36Sopenharmony_ci return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 95162306a36Sopenharmony_ci &fpregs[t],status)); 95262306a36Sopenharmony_ci case 1: /* sgl/dbl */ 95362306a36Sopenharmony_ci return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 95462306a36Sopenharmony_ci &fpregs[t],status)); 95562306a36Sopenharmony_ci case 2: /* dbl/sgl */ 95662306a36Sopenharmony_ci return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 95762306a36Sopenharmony_ci &fpregs[t],status)); 95862306a36Sopenharmony_ci case 3: /* dbl/dbl */ 95962306a36Sopenharmony_ci return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 96062306a36Sopenharmony_ci &fpregs[t],status)); 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci BUG(); 96362306a36Sopenharmony_ci case 4: /* undefined */ 96462306a36Sopenharmony_ci return(MAJOR_0C_EXCP); 96562306a36Sopenharmony_ci } /* end of switch subop */ 96662306a36Sopenharmony_ci BUG(); 96762306a36Sopenharmony_ci case 2: /* class 2 */ 96862306a36Sopenharmony_ci /* 96962306a36Sopenharmony_ci * Be careful out there. 97062306a36Sopenharmony_ci * Crashme can generate cases where FR31R is specified 97162306a36Sopenharmony_ci * as the source or target of a double precision operation. 97262306a36Sopenharmony_ci * Since we just pass the address of the floating-point 97362306a36Sopenharmony_ci * register to the emulation routines, this can cause 97462306a36Sopenharmony_ci * corruption of fpzeroreg. 97562306a36Sopenharmony_ci */ 97662306a36Sopenharmony_ci if (fmt == DBL) 97762306a36Sopenharmony_ci r2 = (extru(ir,fpr2pos,5)<<1); 97862306a36Sopenharmony_ci else 97962306a36Sopenharmony_ci r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 98062306a36Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 98162306a36Sopenharmony_ci if (r2 == 0) 98262306a36Sopenharmony_ci r2 = fpzeroreg; 98362306a36Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) { 98462306a36Sopenharmony_ci /* FTEST if nullify bit set, otherwise FCMP */ 98562306a36Sopenharmony_ci if (extru(ir, fpnulpos, 1)) { /* FTEST */ 98662306a36Sopenharmony_ci /* not legal */ 98762306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 98862306a36Sopenharmony_ci } else { /* FCMP */ 98962306a36Sopenharmony_ci switch (fmt) { 99062306a36Sopenharmony_ci /* 99162306a36Sopenharmony_ci * fmt is only 1 bit long 99262306a36Sopenharmony_ci */ 99362306a36Sopenharmony_ci case 0: 99462306a36Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 99562306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 99662306a36Sopenharmony_ci &local_status); 99762306a36Sopenharmony_ci update_status_cbit(status,local_status, 99862306a36Sopenharmony_ci fpu_type_flags, subop); 99962306a36Sopenharmony_ci return(retval); 100062306a36Sopenharmony_ci case 1: 100162306a36Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 100262306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 100362306a36Sopenharmony_ci &local_status); 100462306a36Sopenharmony_ci update_status_cbit(status,local_status, 100562306a36Sopenharmony_ci fpu_type_flags, subop); 100662306a36Sopenharmony_ci return(retval); 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci } /* end of if for PA2.0 */ 101062306a36Sopenharmony_ci else { /* PA1.0 & PA1.1 */ 101162306a36Sopenharmony_ci switch (subop) { 101262306a36Sopenharmony_ci case 1: 101362306a36Sopenharmony_ci case 2: 101462306a36Sopenharmony_ci case 3: 101562306a36Sopenharmony_ci case 4: 101662306a36Sopenharmony_ci case 5: 101762306a36Sopenharmony_ci case 6: 101862306a36Sopenharmony_ci case 7: 101962306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 102062306a36Sopenharmony_ci case 0: /* FCMP */ 102162306a36Sopenharmony_ci switch (fmt) { 102262306a36Sopenharmony_ci /* 102362306a36Sopenharmony_ci * fmt is only 1 bit long 102462306a36Sopenharmony_ci */ 102562306a36Sopenharmony_ci case 0: 102662306a36Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 102762306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 102862306a36Sopenharmony_ci &local_status); 102962306a36Sopenharmony_ci update_status_cbit(status,local_status, 103062306a36Sopenharmony_ci fpu_type_flags, subop); 103162306a36Sopenharmony_ci return(retval); 103262306a36Sopenharmony_ci case 1: 103362306a36Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 103462306a36Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 103562306a36Sopenharmony_ci &local_status); 103662306a36Sopenharmony_ci update_status_cbit(status,local_status, 103762306a36Sopenharmony_ci fpu_type_flags, subop); 103862306a36Sopenharmony_ci return(retval); 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci } /* end of switch subop */ 104162306a36Sopenharmony_ci } /* end of else for PA1.0 & PA1.1 */ 104262306a36Sopenharmony_ci BUG(); 104362306a36Sopenharmony_ci case 3: /* class 3 */ 104462306a36Sopenharmony_ci /* 104562306a36Sopenharmony_ci * Be careful out there. 104662306a36Sopenharmony_ci * Crashme can generate cases where FR31R is specified 104762306a36Sopenharmony_ci * as the source or target of a double precision operation. 104862306a36Sopenharmony_ci * Since we just pass the address of the floating-point 104962306a36Sopenharmony_ci * register to the emulation routines, this can cause 105062306a36Sopenharmony_ci * corruption of fpzeroreg. 105162306a36Sopenharmony_ci */ 105262306a36Sopenharmony_ci if (fmt == DBL) 105362306a36Sopenharmony_ci r2 = (extru(ir,fpr2pos,5)<<1); 105462306a36Sopenharmony_ci else 105562306a36Sopenharmony_ci r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 105662306a36Sopenharmony_ci if (r2 == 0) 105762306a36Sopenharmony_ci r2 = fpzeroreg; 105862306a36Sopenharmony_ci switch (subop) { 105962306a36Sopenharmony_ci case 5: 106062306a36Sopenharmony_ci case 6: 106162306a36Sopenharmony_ci case 7: 106262306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci /* 106562306a36Sopenharmony_ci * Note that fmt is only 1 bit for class 3 */ 106662306a36Sopenharmony_ci case 0: /* FADD */ 106762306a36Sopenharmony_ci switch (fmt) { 106862306a36Sopenharmony_ci case 0: 106962306a36Sopenharmony_ci return(sgl_fadd(&fpregs[r1],&fpregs[r2], 107062306a36Sopenharmony_ci &fpregs[t],status)); 107162306a36Sopenharmony_ci case 1: 107262306a36Sopenharmony_ci return(dbl_fadd(&fpregs[r1],&fpregs[r2], 107362306a36Sopenharmony_ci &fpregs[t],status)); 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci BUG(); 107662306a36Sopenharmony_ci case 1: /* FSUB */ 107762306a36Sopenharmony_ci switch (fmt) { 107862306a36Sopenharmony_ci case 0: 107962306a36Sopenharmony_ci return(sgl_fsub(&fpregs[r1],&fpregs[r2], 108062306a36Sopenharmony_ci &fpregs[t],status)); 108162306a36Sopenharmony_ci case 1: 108262306a36Sopenharmony_ci return(dbl_fsub(&fpregs[r1],&fpregs[r2], 108362306a36Sopenharmony_ci &fpregs[t],status)); 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci BUG(); 108662306a36Sopenharmony_ci case 2: /* FMPY or XMPYU */ 108762306a36Sopenharmony_ci /* 108862306a36Sopenharmony_ci * check for integer multiply (x bit set) 108962306a36Sopenharmony_ci */ 109062306a36Sopenharmony_ci if (extru(ir,fpxpos,1)) { 109162306a36Sopenharmony_ci /* 109262306a36Sopenharmony_ci * emulate XMPYU 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_ci switch (fmt) { 109562306a36Sopenharmony_ci case 0: 109662306a36Sopenharmony_ci /* 109762306a36Sopenharmony_ci * bad instruction if t specifies 109862306a36Sopenharmony_ci * the right half of a register 109962306a36Sopenharmony_ci */ 110062306a36Sopenharmony_ci if (t & 1) 110162306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 110262306a36Sopenharmony_ci BUG(); 110362306a36Sopenharmony_ci /* unsupported 110462306a36Sopenharmony_ci * impyu(&fpregs[r1],&fpregs[r2], 110562306a36Sopenharmony_ci * &fpregs[t]); 110662306a36Sopenharmony_ci */ 110762306a36Sopenharmony_ci return(NOEXCEPTION); 110862306a36Sopenharmony_ci case 1: 110962306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 111062306a36Sopenharmony_ci } 111162306a36Sopenharmony_ci } 111262306a36Sopenharmony_ci else { /* FMPY */ 111362306a36Sopenharmony_ci switch (fmt) { 111462306a36Sopenharmony_ci case 0: 111562306a36Sopenharmony_ci return(sgl_fmpy(&fpregs[r1], 111662306a36Sopenharmony_ci &fpregs[r2],&fpregs[t],status)); 111762306a36Sopenharmony_ci case 1: 111862306a36Sopenharmony_ci return(dbl_fmpy(&fpregs[r1], 111962306a36Sopenharmony_ci &fpregs[r2],&fpregs[t],status)); 112062306a36Sopenharmony_ci } 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci BUG(); 112362306a36Sopenharmony_ci case 3: /* FDIV */ 112462306a36Sopenharmony_ci switch (fmt) { 112562306a36Sopenharmony_ci case 0: 112662306a36Sopenharmony_ci return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 112762306a36Sopenharmony_ci &fpregs[t],status)); 112862306a36Sopenharmony_ci case 1: 112962306a36Sopenharmony_ci return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 113062306a36Sopenharmony_ci &fpregs[t],status)); 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci BUG(); 113362306a36Sopenharmony_ci case 4: /* FREM */ 113462306a36Sopenharmony_ci switch (fmt) { 113562306a36Sopenharmony_ci case 0: 113662306a36Sopenharmony_ci return(sgl_frem(&fpregs[r1],&fpregs[r2], 113762306a36Sopenharmony_ci &fpregs[t],status)); 113862306a36Sopenharmony_ci case 1: 113962306a36Sopenharmony_ci return(dbl_frem(&fpregs[r1],&fpregs[r2], 114062306a36Sopenharmony_ci &fpregs[t],status)); 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci } /* end of class 3 switch */ 114362306a36Sopenharmony_ci } /* end of switch(class) */ 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* If we get here, something is really wrong! */ 114662306a36Sopenharmony_ci return(MAJOR_0E_EXCP); 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci/* 115162306a36Sopenharmony_ci * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_cistatic u_int 115462306a36Sopenharmony_cidecode_06(ir,fpregs) 115562306a36Sopenharmony_ciu_int ir; 115662306a36Sopenharmony_ciu_int fpregs[]; 115762306a36Sopenharmony_ci{ 115862306a36Sopenharmony_ci u_int rm1, rm2, tm, ra, ta; /* operands */ 115962306a36Sopenharmony_ci u_int fmt; 116062306a36Sopenharmony_ci u_int error = 0; 116162306a36Sopenharmony_ci u_int status; 116262306a36Sopenharmony_ci u_int fpu_type_flags; 116362306a36Sopenharmony_ci union { 116462306a36Sopenharmony_ci double dbl; 116562306a36Sopenharmony_ci float flt; 116662306a36Sopenharmony_ci struct { u_int i1; u_int i2; } ints; 116762306a36Sopenharmony_ci } mtmp, atmp; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci status = fpregs[0]; /* use a local copy of status reg */ 117162306a36Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 117262306a36Sopenharmony_ci fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 117362306a36Sopenharmony_ci if (fmt == 0) { /* DBL */ 117462306a36Sopenharmony_ci rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 117562306a36Sopenharmony_ci if (rm1 == 0) 117662306a36Sopenharmony_ci rm1 = fpzeroreg; 117762306a36Sopenharmony_ci rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 117862306a36Sopenharmony_ci if (rm2 == 0) 117962306a36Sopenharmony_ci rm2 = fpzeroreg; 118062306a36Sopenharmony_ci tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 118162306a36Sopenharmony_ci if (tm == 0) 118262306a36Sopenharmony_ci return(MAJOR_06_EXCP); 118362306a36Sopenharmony_ci ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 118462306a36Sopenharmony_ci ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 118562306a36Sopenharmony_ci if (ta == 0) 118662306a36Sopenharmony_ci return(MAJOR_06_EXCP); 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci if (ra == 0) { 119162306a36Sopenharmony_ci /* special case FMPYCFXT, see sgl case below */ 119262306a36Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], 119362306a36Sopenharmony_ci &mtmp.ints.i1,&status)) 119462306a36Sopenharmony_ci error = 1; 119562306a36Sopenharmony_ci if (dbl_to_sgl_fcnvfxt(&fpregs[ta], 119662306a36Sopenharmony_ci &atmp.ints.i1,&atmp.ints.i1,&status)) 119762306a36Sopenharmony_ci error = 1; 119862306a36Sopenharmony_ci } 119962306a36Sopenharmony_ci else { 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 120262306a36Sopenharmony_ci &status)) 120362306a36Sopenharmony_ci error = 1; 120462306a36Sopenharmony_ci if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 120562306a36Sopenharmony_ci &status)) 120662306a36Sopenharmony_ci error = 1; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci else 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci { 121362306a36Sopenharmony_ci if (ra == 0) 121462306a36Sopenharmony_ci ra = fpzeroreg; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 121762306a36Sopenharmony_ci &status)) 121862306a36Sopenharmony_ci error = 1; 121962306a36Sopenharmony_ci if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 122062306a36Sopenharmony_ci &status)) 122162306a36Sopenharmony_ci error = 1; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (error) 122662306a36Sopenharmony_ci return(MAJOR_06_EXCP); 122762306a36Sopenharmony_ci else { 122862306a36Sopenharmony_ci /* copy results */ 122962306a36Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 123062306a36Sopenharmony_ci fpregs[tm+1] = mtmp.ints.i2; 123162306a36Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 123262306a36Sopenharmony_ci fpregs[ta+1] = atmp.ints.i2; 123362306a36Sopenharmony_ci fpregs[0] = status; 123462306a36Sopenharmony_ci return(NOEXCEPTION); 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci else { /* SGL */ 123862306a36Sopenharmony_ci /* 123962306a36Sopenharmony_ci * calculate offsets for single precision numbers 124062306a36Sopenharmony_ci * See table 6-14 in PA-89 architecture for mapping 124162306a36Sopenharmony_ci */ 124262306a36Sopenharmony_ci rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 124362306a36Sopenharmony_ci rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 124662306a36Sopenharmony_ci rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 124962306a36Sopenharmony_ci tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 125262306a36Sopenharmony_ci ra |= extru(ir,fprapos-4,1); /* add right word offset */ 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 125562306a36Sopenharmony_ci ta |= extru(ir,fptapos-4,1); /* add right word offset */ 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { 125862306a36Sopenharmony_ci /* special case FMPYCFXT (really 0) 125962306a36Sopenharmony_ci * This instruction is only present on the Timex and 126062306a36Sopenharmony_ci * Rolex fpu's in so if it is the special case and 126162306a36Sopenharmony_ci * one of these fpu's we run the FMPYCFXT instruction 126262306a36Sopenharmony_ci */ 126362306a36Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 126462306a36Sopenharmony_ci &status)) 126562306a36Sopenharmony_ci error = 1; 126662306a36Sopenharmony_ci if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, 126762306a36Sopenharmony_ci &atmp.ints.i1,&status)) 126862306a36Sopenharmony_ci error = 1; 126962306a36Sopenharmony_ci } 127062306a36Sopenharmony_ci else { 127162306a36Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 127262306a36Sopenharmony_ci &status)) 127362306a36Sopenharmony_ci error = 1; 127462306a36Sopenharmony_ci if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 127562306a36Sopenharmony_ci &status)) 127662306a36Sopenharmony_ci error = 1; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci if (error) 127962306a36Sopenharmony_ci return(MAJOR_06_EXCP); 128062306a36Sopenharmony_ci else { 128162306a36Sopenharmony_ci /* copy results */ 128262306a36Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 128362306a36Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 128462306a36Sopenharmony_ci fpregs[0] = status; 128562306a36Sopenharmony_ci return(NOEXCEPTION); 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci/* 129162306a36Sopenharmony_ci * routine to decode the 26 (FMPYSUB) instruction 129262306a36Sopenharmony_ci */ 129362306a36Sopenharmony_cistatic u_int 129462306a36Sopenharmony_cidecode_26(ir,fpregs) 129562306a36Sopenharmony_ciu_int ir; 129662306a36Sopenharmony_ciu_int fpregs[]; 129762306a36Sopenharmony_ci{ 129862306a36Sopenharmony_ci u_int rm1, rm2, tm, ra, ta; /* operands */ 129962306a36Sopenharmony_ci u_int fmt; 130062306a36Sopenharmony_ci u_int error = 0; 130162306a36Sopenharmony_ci u_int status; 130262306a36Sopenharmony_ci union { 130362306a36Sopenharmony_ci double dbl; 130462306a36Sopenharmony_ci float flt; 130562306a36Sopenharmony_ci struct { u_int i1; u_int i2; } ints; 130662306a36Sopenharmony_ci } mtmp, atmp; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci status = fpregs[0]; 131062306a36Sopenharmony_ci fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 131162306a36Sopenharmony_ci if (fmt == 0) { /* DBL */ 131262306a36Sopenharmony_ci rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 131362306a36Sopenharmony_ci if (rm1 == 0) 131462306a36Sopenharmony_ci rm1 = fpzeroreg; 131562306a36Sopenharmony_ci rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 131662306a36Sopenharmony_ci if (rm2 == 0) 131762306a36Sopenharmony_ci rm2 = fpzeroreg; 131862306a36Sopenharmony_ci tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 131962306a36Sopenharmony_ci if (tm == 0) 132062306a36Sopenharmony_ci return(MAJOR_26_EXCP); 132162306a36Sopenharmony_ci ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 132262306a36Sopenharmony_ci if (ra == 0) 132362306a36Sopenharmony_ci return(MAJOR_26_EXCP); 132462306a36Sopenharmony_ci ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 132562306a36Sopenharmony_ci if (ta == 0) 132662306a36Sopenharmony_ci return(MAJOR_26_EXCP); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 132962306a36Sopenharmony_ci error = 1; 133062306a36Sopenharmony_ci if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 133162306a36Sopenharmony_ci error = 1; 133262306a36Sopenharmony_ci if (error) 133362306a36Sopenharmony_ci return(MAJOR_26_EXCP); 133462306a36Sopenharmony_ci else { 133562306a36Sopenharmony_ci /* copy results */ 133662306a36Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 133762306a36Sopenharmony_ci fpregs[tm+1] = mtmp.ints.i2; 133862306a36Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 133962306a36Sopenharmony_ci fpregs[ta+1] = atmp.ints.i2; 134062306a36Sopenharmony_ci fpregs[0] = status; 134162306a36Sopenharmony_ci return(NOEXCEPTION); 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci else { /* SGL */ 134562306a36Sopenharmony_ci /* 134662306a36Sopenharmony_ci * calculate offsets for single precision numbers 134762306a36Sopenharmony_ci * See table 6-14 in PA-89 architecture for mapping 134862306a36Sopenharmony_ci */ 134962306a36Sopenharmony_ci rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 135062306a36Sopenharmony_ci rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 135362306a36Sopenharmony_ci rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 135662306a36Sopenharmony_ci tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 135962306a36Sopenharmony_ci ra |= extru(ir,fprapos-4,1); /* add right word offset */ 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 136262306a36Sopenharmony_ci ta |= extru(ir,fptapos-4,1); /* add right word offset */ 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 136562306a36Sopenharmony_ci error = 1; 136662306a36Sopenharmony_ci if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 136762306a36Sopenharmony_ci error = 1; 136862306a36Sopenharmony_ci if (error) 136962306a36Sopenharmony_ci return(MAJOR_26_EXCP); 137062306a36Sopenharmony_ci else { 137162306a36Sopenharmony_ci /* copy results */ 137262306a36Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 137362306a36Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 137462306a36Sopenharmony_ci fpregs[0] = status; 137562306a36Sopenharmony_ci return(NOEXCEPTION); 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci} 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci/* 138262306a36Sopenharmony_ci * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions 138362306a36Sopenharmony_ci */ 138462306a36Sopenharmony_cistatic u_int 138562306a36Sopenharmony_cidecode_2e(ir,fpregs) 138662306a36Sopenharmony_ciu_int ir; 138762306a36Sopenharmony_ciu_int fpregs[]; 138862306a36Sopenharmony_ci{ 138962306a36Sopenharmony_ci u_int rm1, rm2, ra, t; /* operands */ 139062306a36Sopenharmony_ci u_int fmt; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ 139362306a36Sopenharmony_ci if (fmt == DBL) { /* DBL */ 139462306a36Sopenharmony_ci rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); 139562306a36Sopenharmony_ci if (rm1 == 0) 139662306a36Sopenharmony_ci rm1 = fpzeroreg; 139762306a36Sopenharmony_ci rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); 139862306a36Sopenharmony_ci if (rm2 == 0) 139962306a36Sopenharmony_ci rm2 = fpzeroreg; 140062306a36Sopenharmony_ci ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * 140162306a36Sopenharmony_ci sizeof(double)/sizeof(u_int); 140262306a36Sopenharmony_ci if (ra == 0) 140362306a36Sopenharmony_ci ra = fpzeroreg; 140462306a36Sopenharmony_ci t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 140562306a36Sopenharmony_ci if (t == 0) 140662306a36Sopenharmony_ci return(MAJOR_2E_EXCP); 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 140962306a36Sopenharmony_ci return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 141062306a36Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 141162306a36Sopenharmony_ci } else { 141262306a36Sopenharmony_ci return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 141362306a36Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci } /* end DBL */ 141662306a36Sopenharmony_ci else { /* SGL */ 141762306a36Sopenharmony_ci rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); 141862306a36Sopenharmony_ci if (rm1 == 0) 141962306a36Sopenharmony_ci rm1 = fpzeroreg; 142062306a36Sopenharmony_ci rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); 142162306a36Sopenharmony_ci if (rm2 == 0) 142262306a36Sopenharmony_ci rm2 = fpzeroreg; 142362306a36Sopenharmony_ci ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); 142462306a36Sopenharmony_ci if (ra == 0) 142562306a36Sopenharmony_ci ra = fpzeroreg; 142662306a36Sopenharmony_ci t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 142762306a36Sopenharmony_ci if (t == 0) 142862306a36Sopenharmony_ci return(MAJOR_2E_EXCP); 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 143162306a36Sopenharmony_ci return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 143262306a36Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 143362306a36Sopenharmony_ci } else { 143462306a36Sopenharmony_ci return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 143562306a36Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 143662306a36Sopenharmony_ci } 143762306a36Sopenharmony_ci } /* end SGL */ 143862306a36Sopenharmony_ci} 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci/* 144162306a36Sopenharmony_ci * update_status_cbit 144262306a36Sopenharmony_ci * 144362306a36Sopenharmony_ci * This routine returns the correct FP status register value in 144462306a36Sopenharmony_ci * *status, based on the C-bit & V-bit returned by the FCMP 144562306a36Sopenharmony_ci * emulation routine in new_status. The architecture type 144662306a36Sopenharmony_ci * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field 144762306a36Sopenharmony_ci * and the architecture type are used to determine what flavor 144862306a36Sopenharmony_ci * of FCMP is being emulated. 144962306a36Sopenharmony_ci */ 145062306a36Sopenharmony_cistatic void 145162306a36Sopenharmony_ciupdate_status_cbit(status, new_status, fpu_type, y_field) 145262306a36Sopenharmony_ciu_int *status, new_status; 145362306a36Sopenharmony_ciu_int fpu_type; 145462306a36Sopenharmony_ciu_int y_field; 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci /* 145762306a36Sopenharmony_ci * For PA89 FPU's which implement the Compare Queue and 145862306a36Sopenharmony_ci * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, 145962306a36Sopenharmony_ci * otherwise update the specified bit in the Compare Array. 146062306a36Sopenharmony_ci * Note that the y-field will always be 0 for non-PA2.0 FPU's. 146162306a36Sopenharmony_ci */ 146262306a36Sopenharmony_ci if ((fpu_type & TIMEX_EXTEN_FLAG) || 146362306a36Sopenharmony_ci (fpu_type & ROLEX_EXTEN_FLAG) || 146462306a36Sopenharmony_ci (fpu_type & PA2_0_FPU_FLAG)) { 146562306a36Sopenharmony_ci if (y_field == 0) { 146662306a36Sopenharmony_ci *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ 146762306a36Sopenharmony_ci ((*status & 0x003ff000) >> 1) | /* old CQ */ 146862306a36Sopenharmony_ci (new_status & 0xffc007ff); /* all other bits*/ 146962306a36Sopenharmony_ci } else { 147062306a36Sopenharmony_ci *status = (*status & 0x04000000) | /* old Cbit */ 147162306a36Sopenharmony_ci ((new_status & 0x04000000) >> (y_field+4)) | 147262306a36Sopenharmony_ci (new_status & ~0x04000000 & /* other bits */ 147362306a36Sopenharmony_ci ~(0x04000000 >> (y_field+4))); 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci } 147662306a36Sopenharmony_ci /* if PA83, just update the C-bit */ 147762306a36Sopenharmony_ci else { 147862306a36Sopenharmony_ci *status = new_status; 147962306a36Sopenharmony_ci } 148062306a36Sopenharmony_ci} 1481