18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Floating-point emulation code 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * BEGIN_DESC 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * File: 128c2ecf20Sopenharmony_ci * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Purpose: 158c2ecf20Sopenharmony_ci * <<please update with a synopsis of the functionality provided by this file>> 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * External Interfaces: 188c2ecf20Sopenharmony_ci * <<the following list was autogenerated, please review>> 198c2ecf20Sopenharmony_ci * emfpudispatch(ir, dummy1, dummy2, fpregs) 208c2ecf20Sopenharmony_ci * fpudispatch(ir, excp_code, holder, fpregs) 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Internal Interfaces: 238c2ecf20Sopenharmony_ci * <<the following list was autogenerated, please review>> 248c2ecf20Sopenharmony_ci * static u_int decode_06(u_int, u_int *) 258c2ecf20Sopenharmony_ci * static u_int decode_0c(u_int, u_int, u_int, u_int *) 268c2ecf20Sopenharmony_ci * static u_int decode_0e(u_int, u_int, u_int, u_int *) 278c2ecf20Sopenharmony_ci * static u_int decode_26(u_int, u_int *) 288c2ecf20Sopenharmony_ci * static u_int decode_2e(u_int, u_int *) 298c2ecf20Sopenharmony_ci * static void update_status_cbit(u_int *, u_int, u_int, u_int) 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * Theory: 328c2ecf20Sopenharmony_ci * <<please update with a overview of the operation of this file>> 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * END_DESC 358c2ecf20Sopenharmony_ci*/ 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define FPUDEBUG 0 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "float.h" 408c2ecf20Sopenharmony_ci#include <linux/bug.h> 418c2ecf20Sopenharmony_ci#include <linux/kernel.h> 428c2ecf20Sopenharmony_ci#include <asm/processor.h> 438c2ecf20Sopenharmony_ci/* #include <sys/debug.h> */ 448c2ecf20Sopenharmony_ci/* #include <machine/sys/mdep_private.h> */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define COPR_INST 0x30000000 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* 498c2ecf20Sopenharmony_ci * definition of extru macro. If pos and len are constants, the compiler 508c2ecf20Sopenharmony_ci * will generate an extru instruction when optimized 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) 538c2ecf20Sopenharmony_ci/* definitions of bit field locations in the instruction */ 548c2ecf20Sopenharmony_ci#define fpmajorpos 5 558c2ecf20Sopenharmony_ci#define fpr1pos 10 568c2ecf20Sopenharmony_ci#define fpr2pos 15 578c2ecf20Sopenharmony_ci#define fptpos 31 588c2ecf20Sopenharmony_ci#define fpsubpos 18 598c2ecf20Sopenharmony_ci#define fpclass1subpos 16 608c2ecf20Sopenharmony_ci#define fpclasspos 22 618c2ecf20Sopenharmony_ci#define fpfmtpos 20 628c2ecf20Sopenharmony_ci#define fpdfpos 18 638c2ecf20Sopenharmony_ci#define fpnulpos 26 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * the following are the extra bits for the 0E major op 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci#define fpxr1pos 24 688c2ecf20Sopenharmony_ci#define fpxr2pos 19 698c2ecf20Sopenharmony_ci#define fpxtpos 25 708c2ecf20Sopenharmony_ci#define fpxpos 23 718c2ecf20Sopenharmony_ci#define fp0efmtpos 20 728c2ecf20Sopenharmony_ci/* 738c2ecf20Sopenharmony_ci * the following are for the multi-ops 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci#define fprm1pos 10 768c2ecf20Sopenharmony_ci#define fprm2pos 15 778c2ecf20Sopenharmony_ci#define fptmpos 31 788c2ecf20Sopenharmony_ci#define fprapos 25 798c2ecf20Sopenharmony_ci#define fptapos 20 808c2ecf20Sopenharmony_ci#define fpmultifmt 26 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * the following are for the fused FP instructions 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci /* fprm1pos 10 */ 858c2ecf20Sopenharmony_ci /* fprm2pos 15 */ 868c2ecf20Sopenharmony_ci#define fpraupos 18 878c2ecf20Sopenharmony_ci#define fpxrm2pos 19 888c2ecf20Sopenharmony_ci /* fpfmtpos 20 */ 898c2ecf20Sopenharmony_ci#define fpralpos 23 908c2ecf20Sopenharmony_ci#define fpxrm1pos 24 918c2ecf20Sopenharmony_ci /* fpxtpos 25 */ 928c2ecf20Sopenharmony_ci#define fpfusedsubop 26 938c2ecf20Sopenharmony_ci /* fptpos 31 */ 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * offset to constant zero in the FP emulation registers 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci#define fpzeroreg (32*sizeof(double)/sizeof(u_int)) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * extract the major opcode from the instruction 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci#define get_major(op) extru(op,fpmajorpos,6) 1048c2ecf20Sopenharmony_ci/* 1058c2ecf20Sopenharmony_ci * extract the two bit class field from the FP instruction. The class is at bit 1068c2ecf20Sopenharmony_ci * positions 21-22 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci#define get_class(op) extru(op,fpclasspos,2) 1098c2ecf20Sopenharmony_ci/* 1108c2ecf20Sopenharmony_ci * extract the 3 bit subop field. For all but class 1 instructions, it is 1118c2ecf20Sopenharmony_ci * located at bit positions 16-18 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_ci#define get_subop(op) extru(op,fpsubpos,3) 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * extract the 2 or 3 bit subop field from class 1 instructions. It is located 1168c2ecf20Sopenharmony_ci * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ 1198c2ecf20Sopenharmony_ci#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* definitions of unimplemented exceptions */ 1228c2ecf20Sopenharmony_ci#define MAJOR_0C_EXCP 0x09 1238c2ecf20Sopenharmony_ci#define MAJOR_0E_EXCP 0x0b 1248c2ecf20Sopenharmony_ci#define MAJOR_06_EXCP 0x03 1258c2ecf20Sopenharmony_ci#define MAJOR_26_EXCP 0x23 1268c2ecf20Sopenharmony_ci#define MAJOR_2E_EXCP 0x2b 1278c2ecf20Sopenharmony_ci#define PA83_UNIMP_EXCP 0x01 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/* 1308c2ecf20Sopenharmony_ci * Special Defines for TIMEX specific code 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) 1348c2ecf20Sopenharmony_ci#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* 1378c2ecf20Sopenharmony_ci * Static function definitions 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci#define _PROTOTYPES 1408c2ecf20Sopenharmony_ci#if defined(_PROTOTYPES) || defined(_lint) 1418c2ecf20Sopenharmony_cistatic u_int decode_0c(u_int, u_int, u_int, u_int *); 1428c2ecf20Sopenharmony_cistatic u_int decode_0e(u_int, u_int, u_int, u_int *); 1438c2ecf20Sopenharmony_cistatic u_int decode_06(u_int, u_int *); 1448c2ecf20Sopenharmony_cistatic u_int decode_26(u_int, u_int *); 1458c2ecf20Sopenharmony_cistatic u_int decode_2e(u_int, u_int *); 1468c2ecf20Sopenharmony_cistatic void update_status_cbit(u_int *, u_int, u_int, u_int); 1478c2ecf20Sopenharmony_ci#else /* !_PROTOTYPES&&!_lint */ 1488c2ecf20Sopenharmony_cistatic u_int decode_0c(); 1498c2ecf20Sopenharmony_cistatic u_int decode_0e(); 1508c2ecf20Sopenharmony_cistatic u_int decode_06(); 1518c2ecf20Sopenharmony_cistatic u_int decode_26(); 1528c2ecf20Sopenharmony_cistatic u_int decode_2e(); 1538c2ecf20Sopenharmony_cistatic void update_status_cbit(); 1548c2ecf20Sopenharmony_ci#endif /* _PROTOTYPES&&!_lint */ 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define VASSERT(x) 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic void parisc_linux_get_fpu_type(u_int fpregs[]) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci /* on pa-linux the fpu type is not filled in by the 1618c2ecf20Sopenharmony_ci * caller; it is constructed here 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ci if (boot_cpu_data.cpu_type == pcxs) 1648c2ecf20Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG; 1658c2ecf20Sopenharmony_ci else if (boot_cpu_data.cpu_type == pcxt || 1668c2ecf20Sopenharmony_ci boot_cpu_data.cpu_type == pcxt_) 1678c2ecf20Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG; 1688c2ecf20Sopenharmony_ci else if (boot_cpu_data.cpu_type >= pcxu) 1698c2ecf20Sopenharmony_ci fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* 1738c2ecf20Sopenharmony_ci * this routine will decode the excepting floating point instruction and 1748c2ecf20Sopenharmony_ci * call the appropriate emulation routine. 1758c2ecf20Sopenharmony_ci * It is called by decode_fpu with the following parameters: 1768c2ecf20Sopenharmony_ci * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) 1778c2ecf20Sopenharmony_ci * where current_ir is the instruction to be emulated, 1788c2ecf20Sopenharmony_ci * unimplemented_code is the exception_code that the hardware generated 1798c2ecf20Sopenharmony_ci * and &Fpu_register is the address of emulated FP reg 0. 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ciu_int 1828c2ecf20Sopenharmony_cifpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci u_int class, subop; 1858c2ecf20Sopenharmony_ci u_int fpu_type_flags; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* All FP emulation code assumes that ints are 4-bytes in length */ 1888c2ecf20Sopenharmony_ci VASSERT(sizeof(int) == 4); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci parisc_linux_get_fpu_type(fpregs); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci class = get_class(ir); 1958c2ecf20Sopenharmony_ci if (class == 1) { 1968c2ecf20Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) 1978c2ecf20Sopenharmony_ci subop = get_subop1_PA2_0(ir); 1988c2ecf20Sopenharmony_ci else 1998c2ecf20Sopenharmony_ci subop = get_subop1_PA1_1(ir); 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci else 2028c2ecf20Sopenharmony_ci subop = get_subop(ir); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (FPUDEBUG) printk("class %d subop %d\n", class, subop); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci switch (excp_code) { 2078c2ecf20Sopenharmony_ci case MAJOR_0C_EXCP: 2088c2ecf20Sopenharmony_ci case PA83_UNIMP_EXCP: 2098c2ecf20Sopenharmony_ci return(decode_0c(ir,class,subop,fpregs)); 2108c2ecf20Sopenharmony_ci case MAJOR_0E_EXCP: 2118c2ecf20Sopenharmony_ci return(decode_0e(ir,class,subop,fpregs)); 2128c2ecf20Sopenharmony_ci case MAJOR_06_EXCP: 2138c2ecf20Sopenharmony_ci return(decode_06(ir,fpregs)); 2148c2ecf20Sopenharmony_ci case MAJOR_26_EXCP: 2158c2ecf20Sopenharmony_ci return(decode_26(ir,fpregs)); 2168c2ecf20Sopenharmony_ci case MAJOR_2E_EXCP: 2178c2ecf20Sopenharmony_ci return(decode_2e(ir,fpregs)); 2188c2ecf20Sopenharmony_ci default: 2198c2ecf20Sopenharmony_ci /* "crashme Night Gallery painting nr 2. (asm_crash.s). 2208c2ecf20Sopenharmony_ci * This was fixed for multi-user kernels, but 2218c2ecf20Sopenharmony_ci * workstation kernels had a panic here. This allowed 2228c2ecf20Sopenharmony_ci * any arbitrary user to panic the kernel by executing 2238c2ecf20Sopenharmony_ci * setting the FP exception registers to strange values 2248c2ecf20Sopenharmony_ci * and generating an emulation trap. The emulation and 2258c2ecf20Sopenharmony_ci * exception code must never be able to panic the 2268c2ecf20Sopenharmony_ci * kernel. 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ci return(UNIMPLEMENTEDEXCEPTION); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* 2338c2ecf20Sopenharmony_ci * this routine is called by $emulation_trap to emulate a coprocessor 2348c2ecf20Sopenharmony_ci * instruction if one doesn't exist 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_ciu_int 2378c2ecf20Sopenharmony_ciemfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci u_int class, subop, major; 2408c2ecf20Sopenharmony_ci u_int fpu_type_flags; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* All FP emulation code assumes that ints are 4-bytes in length */ 2438c2ecf20Sopenharmony_ci VASSERT(sizeof(int) == 4); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci major = get_major(ir); 2488c2ecf20Sopenharmony_ci class = get_class(ir); 2498c2ecf20Sopenharmony_ci if (class == 1) { 2508c2ecf20Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) 2518c2ecf20Sopenharmony_ci subop = get_subop1_PA2_0(ir); 2528c2ecf20Sopenharmony_ci else 2538c2ecf20Sopenharmony_ci subop = get_subop1_PA1_1(ir); 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci subop = get_subop(ir); 2578c2ecf20Sopenharmony_ci switch (major) { 2588c2ecf20Sopenharmony_ci case 0x0C: 2598c2ecf20Sopenharmony_ci return(decode_0c(ir,class,subop,fpregs)); 2608c2ecf20Sopenharmony_ci case 0x0E: 2618c2ecf20Sopenharmony_ci return(decode_0e(ir,class,subop,fpregs)); 2628c2ecf20Sopenharmony_ci case 0x06: 2638c2ecf20Sopenharmony_ci return(decode_06(ir,fpregs)); 2648c2ecf20Sopenharmony_ci case 0x26: 2658c2ecf20Sopenharmony_ci return(decode_26(ir,fpregs)); 2668c2ecf20Sopenharmony_ci case 0x2E: 2678c2ecf20Sopenharmony_ci return(decode_2e(ir,fpregs)); 2688c2ecf20Sopenharmony_ci default: 2698c2ecf20Sopenharmony_ci return(PA83_UNIMP_EXCP); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic u_int 2758c2ecf20Sopenharmony_cidecode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci u_int r1,r2,t; /* operand register offsets */ 2788c2ecf20Sopenharmony_ci u_int fmt; /* also sf for class 1 conversions */ 2798c2ecf20Sopenharmony_ci u_int df; /* for class 1 conversions */ 2808c2ecf20Sopenharmony_ci u_int *status; 2818c2ecf20Sopenharmony_ci u_int retval, local_status; 2828c2ecf20Sopenharmony_ci u_int fpu_type_flags; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (ir == COPR_INST) { 2858c2ecf20Sopenharmony_ci fpregs[0] = EMULATION_VERSION << 11; 2868c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci status = &fpregs[0]; /* fp status register */ 2898c2ecf20Sopenharmony_ci local_status = fpregs[0]; /* and local copy */ 2908c2ecf20Sopenharmony_ci r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); 2918c2ecf20Sopenharmony_ci if (r1 == 0) /* map fr0 source to constant zero */ 2928c2ecf20Sopenharmony_ci r1 = fpzeroreg; 2938c2ecf20Sopenharmony_ci t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 2948c2ecf20Sopenharmony_ci if (t == 0 && class != 2) /* don't allow fr0 as a dest */ 2958c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 2968c2ecf20Sopenharmony_ci fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci switch (class) { 2998c2ecf20Sopenharmony_ci case 0: 3008c2ecf20Sopenharmony_ci switch (subop) { 3018c2ecf20Sopenharmony_ci case 0: /* COPR 0,0 emulated above*/ 3028c2ecf20Sopenharmony_ci case 1: 3038c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3048c2ecf20Sopenharmony_ci case 2: /* FCPY */ 3058c2ecf20Sopenharmony_ci switch (fmt) { 3068c2ecf20Sopenharmony_ci case 2: /* illegal */ 3078c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3088c2ecf20Sopenharmony_ci case 3: /* quad */ 3098c2ecf20Sopenharmony_ci t &= ~3; /* force to even reg #s */ 3108c2ecf20Sopenharmony_ci r1 &= ~3; 3118c2ecf20Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 3128c2ecf20Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 3138c2ecf20Sopenharmony_ci fallthrough; 3148c2ecf20Sopenharmony_ci case 1: /* double */ 3158c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 3168c2ecf20Sopenharmony_ci fallthrough; 3178c2ecf20Sopenharmony_ci case 0: /* single */ 3188c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1]; 3198c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci BUG(); 3228c2ecf20Sopenharmony_ci case 3: /* FABS */ 3238c2ecf20Sopenharmony_ci switch (fmt) { 3248c2ecf20Sopenharmony_ci case 2: /* illegal */ 3258c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3268c2ecf20Sopenharmony_ci case 3: /* quad */ 3278c2ecf20Sopenharmony_ci t &= ~3; /* force to even reg #s */ 3288c2ecf20Sopenharmony_ci r1 &= ~3; 3298c2ecf20Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 3308c2ecf20Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 3318c2ecf20Sopenharmony_ci fallthrough; 3328c2ecf20Sopenharmony_ci case 1: /* double */ 3338c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 3348c2ecf20Sopenharmony_ci fallthrough; 3358c2ecf20Sopenharmony_ci case 0: /* single */ 3368c2ecf20Sopenharmony_ci /* copy and clear sign bit */ 3378c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] & 0x7fffffff; 3388c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci BUG(); 3418c2ecf20Sopenharmony_ci case 6: /* FNEG */ 3428c2ecf20Sopenharmony_ci switch (fmt) { 3438c2ecf20Sopenharmony_ci case 2: /* illegal */ 3448c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3458c2ecf20Sopenharmony_ci case 3: /* quad */ 3468c2ecf20Sopenharmony_ci t &= ~3; /* force to even reg #s */ 3478c2ecf20Sopenharmony_ci r1 &= ~3; 3488c2ecf20Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 3498c2ecf20Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 3508c2ecf20Sopenharmony_ci fallthrough; 3518c2ecf20Sopenharmony_ci case 1: /* double */ 3528c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 3538c2ecf20Sopenharmony_ci fallthrough; 3548c2ecf20Sopenharmony_ci case 0: /* single */ 3558c2ecf20Sopenharmony_ci /* copy and invert sign bit */ 3568c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] ^ 0x80000000; 3578c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci BUG(); 3608c2ecf20Sopenharmony_ci case 7: /* FNEGABS */ 3618c2ecf20Sopenharmony_ci switch (fmt) { 3628c2ecf20Sopenharmony_ci case 2: /* illegal */ 3638c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3648c2ecf20Sopenharmony_ci case 3: /* quad */ 3658c2ecf20Sopenharmony_ci t &= ~3; /* force to even reg #s */ 3668c2ecf20Sopenharmony_ci r1 &= ~3; 3678c2ecf20Sopenharmony_ci fpregs[t+3] = fpregs[r1+3]; 3688c2ecf20Sopenharmony_ci fpregs[t+2] = fpregs[r1+2]; 3698c2ecf20Sopenharmony_ci fallthrough; 3708c2ecf20Sopenharmony_ci case 1: /* double */ 3718c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 3728c2ecf20Sopenharmony_ci fallthrough; 3738c2ecf20Sopenharmony_ci case 0: /* single */ 3748c2ecf20Sopenharmony_ci /* copy and set sign bit */ 3758c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] | 0x80000000; 3768c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci BUG(); 3798c2ecf20Sopenharmony_ci case 4: /* FSQRT */ 3808c2ecf20Sopenharmony_ci switch (fmt) { 3818c2ecf20Sopenharmony_ci case 0: 3828c2ecf20Sopenharmony_ci return(sgl_fsqrt(&fpregs[r1],0, 3838c2ecf20Sopenharmony_ci &fpregs[t],status)); 3848c2ecf20Sopenharmony_ci case 1: 3858c2ecf20Sopenharmony_ci return(dbl_fsqrt(&fpregs[r1],0, 3868c2ecf20Sopenharmony_ci &fpregs[t],status)); 3878c2ecf20Sopenharmony_ci case 2: 3888c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 3898c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci BUG(); 3928c2ecf20Sopenharmony_ci case 5: /* FRND */ 3938c2ecf20Sopenharmony_ci switch (fmt) { 3948c2ecf20Sopenharmony_ci case 0: 3958c2ecf20Sopenharmony_ci return(sgl_frnd(&fpregs[r1],0, 3968c2ecf20Sopenharmony_ci &fpregs[t],status)); 3978c2ecf20Sopenharmony_ci case 1: 3988c2ecf20Sopenharmony_ci return(dbl_frnd(&fpregs[r1],0, 3998c2ecf20Sopenharmony_ci &fpregs[t],status)); 4008c2ecf20Sopenharmony_ci case 2: 4018c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 4028c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci } /* end of switch (subop) */ 4058c2ecf20Sopenharmony_ci BUG(); 4068c2ecf20Sopenharmony_ci case 1: /* class 1 */ 4078c2ecf20Sopenharmony_ci df = extru(ir,fpdfpos,2); /* get dest format */ 4088c2ecf20Sopenharmony_ci if ((df & 2) || (fmt & 2)) { 4098c2ecf20Sopenharmony_ci /* 4108c2ecf20Sopenharmony_ci * fmt's 2 and 3 are illegal of not implemented 4118c2ecf20Sopenharmony_ci * quad conversions 4128c2ecf20Sopenharmony_ci */ 4138c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci /* 4168c2ecf20Sopenharmony_ci * encode source and dest formats into 2 bits. 4178c2ecf20Sopenharmony_ci * high bit is source, low bit is dest. 4188c2ecf20Sopenharmony_ci * bit = 1 --> double precision 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_ci fmt = (fmt << 1) | df; 4218c2ecf20Sopenharmony_ci switch (subop) { 4228c2ecf20Sopenharmony_ci case 0: /* FCNVFF */ 4238c2ecf20Sopenharmony_ci switch(fmt) { 4248c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 4258c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 4268c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 4278c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 4288c2ecf20Sopenharmony_ci &fpregs[t],status)); 4298c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 4308c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 4318c2ecf20Sopenharmony_ci &fpregs[t],status)); 4328c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 4338c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci BUG(); 4368c2ecf20Sopenharmony_ci case 1: /* FCNVXF */ 4378c2ecf20Sopenharmony_ci switch(fmt) { 4388c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 4398c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 4408c2ecf20Sopenharmony_ci &fpregs[t],status)); 4418c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 4428c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 4438c2ecf20Sopenharmony_ci &fpregs[t],status)); 4448c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 4458c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 4468c2ecf20Sopenharmony_ci &fpregs[t],status)); 4478c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 4488c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 4498c2ecf20Sopenharmony_ci &fpregs[t],status)); 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci BUG(); 4528c2ecf20Sopenharmony_ci case 2: /* FCNVFX */ 4538c2ecf20Sopenharmony_ci switch(fmt) { 4548c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 4558c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 4568c2ecf20Sopenharmony_ci &fpregs[t],status)); 4578c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 4588c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 4598c2ecf20Sopenharmony_ci &fpregs[t],status)); 4608c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 4618c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 4628c2ecf20Sopenharmony_ci &fpregs[t],status)); 4638c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 4648c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 4658c2ecf20Sopenharmony_ci &fpregs[t],status)); 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci BUG(); 4688c2ecf20Sopenharmony_ci case 3: /* FCNVFXT */ 4698c2ecf20Sopenharmony_ci switch(fmt) { 4708c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 4718c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 4728c2ecf20Sopenharmony_ci &fpregs[t],status)); 4738c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 4748c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 4758c2ecf20Sopenharmony_ci &fpregs[t],status)); 4768c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 4778c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 4788c2ecf20Sopenharmony_ci &fpregs[t],status)); 4798c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 4808c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 4818c2ecf20Sopenharmony_ci &fpregs[t],status)); 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci BUG(); 4848c2ecf20Sopenharmony_ci case 5: /* FCNVUF (PA2.0 only) */ 4858c2ecf20Sopenharmony_ci switch(fmt) { 4868c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 4878c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 4888c2ecf20Sopenharmony_ci &fpregs[t],status)); 4898c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 4908c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 4918c2ecf20Sopenharmony_ci &fpregs[t],status)); 4928c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 4938c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 4948c2ecf20Sopenharmony_ci &fpregs[t],status)); 4958c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 4968c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 4978c2ecf20Sopenharmony_ci &fpregs[t],status)); 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci BUG(); 5008c2ecf20Sopenharmony_ci case 6: /* FCNVFU (PA2.0 only) */ 5018c2ecf20Sopenharmony_ci switch(fmt) { 5028c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 5038c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 5048c2ecf20Sopenharmony_ci &fpregs[t],status)); 5058c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 5068c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 5078c2ecf20Sopenharmony_ci &fpregs[t],status)); 5088c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 5098c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 5108c2ecf20Sopenharmony_ci &fpregs[t],status)); 5118c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 5128c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 5138c2ecf20Sopenharmony_ci &fpregs[t],status)); 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci BUG(); 5168c2ecf20Sopenharmony_ci case 7: /* FCNVFUT (PA2.0 only) */ 5178c2ecf20Sopenharmony_ci switch(fmt) { 5188c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 5198c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 5208c2ecf20Sopenharmony_ci &fpregs[t],status)); 5218c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 5228c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 5238c2ecf20Sopenharmony_ci &fpregs[t],status)); 5248c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 5258c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 5268c2ecf20Sopenharmony_ci &fpregs[t],status)); 5278c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 5288c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 5298c2ecf20Sopenharmony_ci &fpregs[t],status)); 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci BUG(); 5328c2ecf20Sopenharmony_ci case 4: /* undefined */ 5338c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 5348c2ecf20Sopenharmony_ci } /* end of switch subop */ 5358c2ecf20Sopenharmony_ci BUG(); 5368c2ecf20Sopenharmony_ci case 2: /* class 2 */ 5378c2ecf20Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 5388c2ecf20Sopenharmony_ci r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); 5398c2ecf20Sopenharmony_ci if (r2 == 0) 5408c2ecf20Sopenharmony_ci r2 = fpzeroreg; 5418c2ecf20Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) { 5428c2ecf20Sopenharmony_ci /* FTEST if nullify bit set, otherwise FCMP */ 5438c2ecf20Sopenharmony_ci if (extru(ir, fpnulpos, 1)) { /* FTEST */ 5448c2ecf20Sopenharmony_ci switch (fmt) { 5458c2ecf20Sopenharmony_ci case 0: 5468c2ecf20Sopenharmony_ci /* 5478c2ecf20Sopenharmony_ci * arg0 is not used 5488c2ecf20Sopenharmony_ci * second param is the t field used for 5498c2ecf20Sopenharmony_ci * ftest,acc and ftest,rej 5508c2ecf20Sopenharmony_ci * third param is the subop (y-field) 5518c2ecf20Sopenharmony_ci */ 5528c2ecf20Sopenharmony_ci BUG(); 5538c2ecf20Sopenharmony_ci /* Unsupported 5548c2ecf20Sopenharmony_ci * return(ftest(0L,extru(ir,fptpos,5), 5558c2ecf20Sopenharmony_ci * &fpregs[0],subop)); 5568c2ecf20Sopenharmony_ci */ 5578c2ecf20Sopenharmony_ci case 1: 5588c2ecf20Sopenharmony_ci case 2: 5598c2ecf20Sopenharmony_ci case 3: 5608c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci } else { /* FCMP */ 5638c2ecf20Sopenharmony_ci switch (fmt) { 5648c2ecf20Sopenharmony_ci case 0: 5658c2ecf20Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 5668c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 5678c2ecf20Sopenharmony_ci &local_status); 5688c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 5698c2ecf20Sopenharmony_ci fpu_type_flags, subop); 5708c2ecf20Sopenharmony_ci return(retval); 5718c2ecf20Sopenharmony_ci case 1: 5728c2ecf20Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 5738c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 5748c2ecf20Sopenharmony_ci &local_status); 5758c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 5768c2ecf20Sopenharmony_ci fpu_type_flags, subop); 5778c2ecf20Sopenharmony_ci return(retval); 5788c2ecf20Sopenharmony_ci case 2: /* illegal */ 5798c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 5808c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci } /* end of if for PA2.0 */ 5848c2ecf20Sopenharmony_ci else { /* PA1.0 & PA1.1 */ 5858c2ecf20Sopenharmony_ci switch (subop) { 5868c2ecf20Sopenharmony_ci case 2: 5878c2ecf20Sopenharmony_ci case 3: 5888c2ecf20Sopenharmony_ci case 4: 5898c2ecf20Sopenharmony_ci case 5: 5908c2ecf20Sopenharmony_ci case 6: 5918c2ecf20Sopenharmony_ci case 7: 5928c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 5938c2ecf20Sopenharmony_ci case 0: /* FCMP */ 5948c2ecf20Sopenharmony_ci switch (fmt) { 5958c2ecf20Sopenharmony_ci case 0: 5968c2ecf20Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 5978c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 5988c2ecf20Sopenharmony_ci &local_status); 5998c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 6008c2ecf20Sopenharmony_ci fpu_type_flags, subop); 6018c2ecf20Sopenharmony_ci return(retval); 6028c2ecf20Sopenharmony_ci case 1: 6038c2ecf20Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 6048c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 6058c2ecf20Sopenharmony_ci &local_status); 6068c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 6078c2ecf20Sopenharmony_ci fpu_type_flags, subop); 6088c2ecf20Sopenharmony_ci return(retval); 6098c2ecf20Sopenharmony_ci case 2: /* illegal */ 6108c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 6118c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci BUG(); 6148c2ecf20Sopenharmony_ci case 1: /* FTEST */ 6158c2ecf20Sopenharmony_ci switch (fmt) { 6168c2ecf20Sopenharmony_ci case 0: 6178c2ecf20Sopenharmony_ci /* 6188c2ecf20Sopenharmony_ci * arg0 is not used 6198c2ecf20Sopenharmony_ci * second param is the t field used for 6208c2ecf20Sopenharmony_ci * ftest,acc and ftest,rej 6218c2ecf20Sopenharmony_ci * third param is the subop (y-field) 6228c2ecf20Sopenharmony_ci */ 6238c2ecf20Sopenharmony_ci BUG(); 6248c2ecf20Sopenharmony_ci /* unsupported 6258c2ecf20Sopenharmony_ci * return(ftest(0L,extru(ir,fptpos,5), 6268c2ecf20Sopenharmony_ci * &fpregs[0],subop)); 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_ci case 1: 6298c2ecf20Sopenharmony_ci case 2: 6308c2ecf20Sopenharmony_ci case 3: 6318c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci BUG(); 6348c2ecf20Sopenharmony_ci } /* end of switch subop */ 6358c2ecf20Sopenharmony_ci } /* end of else for PA1.0 & PA1.1 */ 6368c2ecf20Sopenharmony_ci BUG(); 6378c2ecf20Sopenharmony_ci case 3: /* class 3 */ 6388c2ecf20Sopenharmony_ci r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); 6398c2ecf20Sopenharmony_ci if (r2 == 0) 6408c2ecf20Sopenharmony_ci r2 = fpzeroreg; 6418c2ecf20Sopenharmony_ci switch (subop) { 6428c2ecf20Sopenharmony_ci case 5: 6438c2ecf20Sopenharmony_ci case 6: 6448c2ecf20Sopenharmony_ci case 7: 6458c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci case 0: /* FADD */ 6488c2ecf20Sopenharmony_ci switch (fmt) { 6498c2ecf20Sopenharmony_ci case 0: 6508c2ecf20Sopenharmony_ci return(sgl_fadd(&fpregs[r1],&fpregs[r2], 6518c2ecf20Sopenharmony_ci &fpregs[t],status)); 6528c2ecf20Sopenharmony_ci case 1: 6538c2ecf20Sopenharmony_ci return(dbl_fadd(&fpregs[r1],&fpregs[r2], 6548c2ecf20Sopenharmony_ci &fpregs[t],status)); 6558c2ecf20Sopenharmony_ci case 2: /* illegal */ 6568c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 6578c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci BUG(); 6608c2ecf20Sopenharmony_ci case 1: /* FSUB */ 6618c2ecf20Sopenharmony_ci switch (fmt) { 6628c2ecf20Sopenharmony_ci case 0: 6638c2ecf20Sopenharmony_ci return(sgl_fsub(&fpregs[r1],&fpregs[r2], 6648c2ecf20Sopenharmony_ci &fpregs[t],status)); 6658c2ecf20Sopenharmony_ci case 1: 6668c2ecf20Sopenharmony_ci return(dbl_fsub(&fpregs[r1],&fpregs[r2], 6678c2ecf20Sopenharmony_ci &fpregs[t],status)); 6688c2ecf20Sopenharmony_ci case 2: /* illegal */ 6698c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 6708c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci BUG(); 6738c2ecf20Sopenharmony_ci case 2: /* FMPY */ 6748c2ecf20Sopenharmony_ci switch (fmt) { 6758c2ecf20Sopenharmony_ci case 0: 6768c2ecf20Sopenharmony_ci return(sgl_fmpy(&fpregs[r1],&fpregs[r2], 6778c2ecf20Sopenharmony_ci &fpregs[t],status)); 6788c2ecf20Sopenharmony_ci case 1: 6798c2ecf20Sopenharmony_ci return(dbl_fmpy(&fpregs[r1],&fpregs[r2], 6808c2ecf20Sopenharmony_ci &fpregs[t],status)); 6818c2ecf20Sopenharmony_ci case 2: /* illegal */ 6828c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 6838c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci BUG(); 6868c2ecf20Sopenharmony_ci case 3: /* FDIV */ 6878c2ecf20Sopenharmony_ci switch (fmt) { 6888c2ecf20Sopenharmony_ci case 0: 6898c2ecf20Sopenharmony_ci return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 6908c2ecf20Sopenharmony_ci &fpregs[t],status)); 6918c2ecf20Sopenharmony_ci case 1: 6928c2ecf20Sopenharmony_ci return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 6938c2ecf20Sopenharmony_ci &fpregs[t],status)); 6948c2ecf20Sopenharmony_ci case 2: /* illegal */ 6958c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 6968c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci BUG(); 6998c2ecf20Sopenharmony_ci case 4: /* FREM */ 7008c2ecf20Sopenharmony_ci switch (fmt) { 7018c2ecf20Sopenharmony_ci case 0: 7028c2ecf20Sopenharmony_ci return(sgl_frem(&fpregs[r1],&fpregs[r2], 7038c2ecf20Sopenharmony_ci &fpregs[t],status)); 7048c2ecf20Sopenharmony_ci case 1: 7058c2ecf20Sopenharmony_ci return(dbl_frem(&fpregs[r1],&fpregs[r2], 7068c2ecf20Sopenharmony_ci &fpregs[t],status)); 7078c2ecf20Sopenharmony_ci case 2: /* illegal */ 7088c2ecf20Sopenharmony_ci case 3: /* quad not implemented */ 7098c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci BUG(); 7128c2ecf20Sopenharmony_ci } /* end of class 3 switch */ 7138c2ecf20Sopenharmony_ci } /* end of switch(class) */ 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* If we get here, something is really wrong! */ 7168c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic u_int 7208c2ecf20Sopenharmony_cidecode_0e(ir,class,subop,fpregs) 7218c2ecf20Sopenharmony_ciu_int ir,class,subop; 7228c2ecf20Sopenharmony_ciu_int fpregs[]; 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci u_int r1,r2,t; /* operand register offsets */ 7258c2ecf20Sopenharmony_ci u_int fmt; /* also sf for class 1 conversions */ 7268c2ecf20Sopenharmony_ci u_int df; /* dest format for class 1 conversions */ 7278c2ecf20Sopenharmony_ci u_int *status; 7288c2ecf20Sopenharmony_ci u_int retval, local_status; 7298c2ecf20Sopenharmony_ci u_int fpu_type_flags; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci status = &fpregs[0]; 7328c2ecf20Sopenharmony_ci local_status = fpregs[0]; 7338c2ecf20Sopenharmony_ci r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); 7348c2ecf20Sopenharmony_ci if (r1 == 0) 7358c2ecf20Sopenharmony_ci r1 = fpzeroreg; 7368c2ecf20Sopenharmony_ci t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 7378c2ecf20Sopenharmony_ci if (t == 0 && class != 2) 7388c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 7398c2ecf20Sopenharmony_ci if (class < 2) /* class 0 or 1 has 2 bit fmt */ 7408c2ecf20Sopenharmony_ci fmt = extru(ir,fpfmtpos,2); 7418c2ecf20Sopenharmony_ci else /* class 2 and 3 have 1 bit fmt */ 7428c2ecf20Sopenharmony_ci fmt = extru(ir,fp0efmtpos,1); 7438c2ecf20Sopenharmony_ci /* 7448c2ecf20Sopenharmony_ci * An undefined combination, double precision accessing the 7458c2ecf20Sopenharmony_ci * right half of a FPR, can get us into trouble. 7468c2ecf20Sopenharmony_ci * Let's just force proper alignment on it. 7478c2ecf20Sopenharmony_ci */ 7488c2ecf20Sopenharmony_ci if (fmt == DBL) { 7498c2ecf20Sopenharmony_ci r1 &= ~1; 7508c2ecf20Sopenharmony_ci if (class != 1) 7518c2ecf20Sopenharmony_ci t &= ~1; 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci switch (class) { 7558c2ecf20Sopenharmony_ci case 0: 7568c2ecf20Sopenharmony_ci switch (subop) { 7578c2ecf20Sopenharmony_ci case 0: /* unimplemented */ 7588c2ecf20Sopenharmony_ci case 1: 7598c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 7608c2ecf20Sopenharmony_ci case 2: /* FCPY */ 7618c2ecf20Sopenharmony_ci switch (fmt) { 7628c2ecf20Sopenharmony_ci case 2: 7638c2ecf20Sopenharmony_ci case 3: 7648c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 7658c2ecf20Sopenharmony_ci case 1: /* double */ 7668c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 7678c2ecf20Sopenharmony_ci fallthrough; 7688c2ecf20Sopenharmony_ci case 0: /* single */ 7698c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1]; 7708c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci BUG(); 7738c2ecf20Sopenharmony_ci case 3: /* FABS */ 7748c2ecf20Sopenharmony_ci switch (fmt) { 7758c2ecf20Sopenharmony_ci case 2: 7768c2ecf20Sopenharmony_ci case 3: 7778c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 7788c2ecf20Sopenharmony_ci case 1: /* double */ 7798c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 7808c2ecf20Sopenharmony_ci fallthrough; 7818c2ecf20Sopenharmony_ci case 0: /* single */ 7828c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] & 0x7fffffff; 7838c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci BUG(); 7868c2ecf20Sopenharmony_ci case 6: /* FNEG */ 7878c2ecf20Sopenharmony_ci switch (fmt) { 7888c2ecf20Sopenharmony_ci case 2: 7898c2ecf20Sopenharmony_ci case 3: 7908c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 7918c2ecf20Sopenharmony_ci case 1: /* double */ 7928c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 7938c2ecf20Sopenharmony_ci fallthrough; 7948c2ecf20Sopenharmony_ci case 0: /* single */ 7958c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] ^ 0x80000000; 7968c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci BUG(); 7998c2ecf20Sopenharmony_ci case 7: /* FNEGABS */ 8008c2ecf20Sopenharmony_ci switch (fmt) { 8018c2ecf20Sopenharmony_ci case 2: 8028c2ecf20Sopenharmony_ci case 3: 8038c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8048c2ecf20Sopenharmony_ci case 1: /* double */ 8058c2ecf20Sopenharmony_ci fpregs[t+1] = fpregs[r1+1]; 8068c2ecf20Sopenharmony_ci fallthrough; 8078c2ecf20Sopenharmony_ci case 0: /* single */ 8088c2ecf20Sopenharmony_ci fpregs[t] = fpregs[r1] | 0x80000000; 8098c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci BUG(); 8128c2ecf20Sopenharmony_ci case 4: /* FSQRT */ 8138c2ecf20Sopenharmony_ci switch (fmt) { 8148c2ecf20Sopenharmony_ci case 0: 8158c2ecf20Sopenharmony_ci return(sgl_fsqrt(&fpregs[r1],0, 8168c2ecf20Sopenharmony_ci &fpregs[t], status)); 8178c2ecf20Sopenharmony_ci case 1: 8188c2ecf20Sopenharmony_ci return(dbl_fsqrt(&fpregs[r1],0, 8198c2ecf20Sopenharmony_ci &fpregs[t], status)); 8208c2ecf20Sopenharmony_ci case 2: 8218c2ecf20Sopenharmony_ci case 3: 8228c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci BUG(); 8258c2ecf20Sopenharmony_ci case 5: /* FRMD */ 8268c2ecf20Sopenharmony_ci switch (fmt) { 8278c2ecf20Sopenharmony_ci case 0: 8288c2ecf20Sopenharmony_ci return(sgl_frnd(&fpregs[r1],0, 8298c2ecf20Sopenharmony_ci &fpregs[t], status)); 8308c2ecf20Sopenharmony_ci case 1: 8318c2ecf20Sopenharmony_ci return(dbl_frnd(&fpregs[r1],0, 8328c2ecf20Sopenharmony_ci &fpregs[t], status)); 8338c2ecf20Sopenharmony_ci case 2: 8348c2ecf20Sopenharmony_ci case 3: 8358c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci } /* end of switch (subop */ 8388c2ecf20Sopenharmony_ci BUG(); 8398c2ecf20Sopenharmony_ci case 1: /* class 1 */ 8408c2ecf20Sopenharmony_ci df = extru(ir,fpdfpos,2); /* get dest format */ 8418c2ecf20Sopenharmony_ci /* 8428c2ecf20Sopenharmony_ci * Fix Crashme problem (writing to 31R in double precision) 8438c2ecf20Sopenharmony_ci * here too. 8448c2ecf20Sopenharmony_ci */ 8458c2ecf20Sopenharmony_ci if (df == DBL) { 8468c2ecf20Sopenharmony_ci t &= ~1; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci if ((df & 2) || (fmt & 2)) 8498c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci fmt = (fmt << 1) | df; 8528c2ecf20Sopenharmony_ci switch (subop) { 8538c2ecf20Sopenharmony_ci case 0: /* FCNVFF */ 8548c2ecf20Sopenharmony_ci switch(fmt) { 8558c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 8568c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8578c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 8588c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 8598c2ecf20Sopenharmony_ci &fpregs[t],status)); 8608c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 8618c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 8628c2ecf20Sopenharmony_ci &fpregs[t],status)); 8638c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 8648c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 8658c2ecf20Sopenharmony_ci } 8668c2ecf20Sopenharmony_ci BUG(); 8678c2ecf20Sopenharmony_ci case 1: /* FCNVXF */ 8688c2ecf20Sopenharmony_ci switch(fmt) { 8698c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 8708c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 8718c2ecf20Sopenharmony_ci &fpregs[t],status)); 8728c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 8738c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 8748c2ecf20Sopenharmony_ci &fpregs[t],status)); 8758c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 8768c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 8778c2ecf20Sopenharmony_ci &fpregs[t],status)); 8788c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 8798c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 8808c2ecf20Sopenharmony_ci &fpregs[t],status)); 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci BUG(); 8838c2ecf20Sopenharmony_ci case 2: /* FCNVFX */ 8848c2ecf20Sopenharmony_ci switch(fmt) { 8858c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 8868c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 8878c2ecf20Sopenharmony_ci &fpregs[t],status)); 8888c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 8898c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 8908c2ecf20Sopenharmony_ci &fpregs[t],status)); 8918c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 8928c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 8938c2ecf20Sopenharmony_ci &fpregs[t],status)); 8948c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 8958c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 8968c2ecf20Sopenharmony_ci &fpregs[t],status)); 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci BUG(); 8998c2ecf20Sopenharmony_ci case 3: /* FCNVFXT */ 9008c2ecf20Sopenharmony_ci switch(fmt) { 9018c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 9028c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 9038c2ecf20Sopenharmony_ci &fpregs[t],status)); 9048c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 9058c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 9068c2ecf20Sopenharmony_ci &fpregs[t],status)); 9078c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 9088c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 9098c2ecf20Sopenharmony_ci &fpregs[t],status)); 9108c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 9118c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 9128c2ecf20Sopenharmony_ci &fpregs[t],status)); 9138c2ecf20Sopenharmony_ci } 9148c2ecf20Sopenharmony_ci BUG(); 9158c2ecf20Sopenharmony_ci case 5: /* FCNVUF (PA2.0 only) */ 9168c2ecf20Sopenharmony_ci switch(fmt) { 9178c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 9188c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 9198c2ecf20Sopenharmony_ci &fpregs[t],status)); 9208c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 9218c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 9228c2ecf20Sopenharmony_ci &fpregs[t],status)); 9238c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 9248c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 9258c2ecf20Sopenharmony_ci &fpregs[t],status)); 9268c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 9278c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 9288c2ecf20Sopenharmony_ci &fpregs[t],status)); 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci BUG(); 9318c2ecf20Sopenharmony_ci case 6: /* FCNVFU (PA2.0 only) */ 9328c2ecf20Sopenharmony_ci switch(fmt) { 9338c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 9348c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 9358c2ecf20Sopenharmony_ci &fpregs[t],status)); 9368c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 9378c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 9388c2ecf20Sopenharmony_ci &fpregs[t],status)); 9398c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 9408c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 9418c2ecf20Sopenharmony_ci &fpregs[t],status)); 9428c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 9438c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 9448c2ecf20Sopenharmony_ci &fpregs[t],status)); 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci BUG(); 9478c2ecf20Sopenharmony_ci case 7: /* FCNVFUT (PA2.0 only) */ 9488c2ecf20Sopenharmony_ci switch(fmt) { 9498c2ecf20Sopenharmony_ci case 0: /* sgl/sgl */ 9508c2ecf20Sopenharmony_ci return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 9518c2ecf20Sopenharmony_ci &fpregs[t],status)); 9528c2ecf20Sopenharmony_ci case 1: /* sgl/dbl */ 9538c2ecf20Sopenharmony_ci return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 9548c2ecf20Sopenharmony_ci &fpregs[t],status)); 9558c2ecf20Sopenharmony_ci case 2: /* dbl/sgl */ 9568c2ecf20Sopenharmony_ci return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 9578c2ecf20Sopenharmony_ci &fpregs[t],status)); 9588c2ecf20Sopenharmony_ci case 3: /* dbl/dbl */ 9598c2ecf20Sopenharmony_ci return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 9608c2ecf20Sopenharmony_ci &fpregs[t],status)); 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci BUG(); 9638c2ecf20Sopenharmony_ci case 4: /* undefined */ 9648c2ecf20Sopenharmony_ci return(MAJOR_0C_EXCP); 9658c2ecf20Sopenharmony_ci } /* end of switch subop */ 9668c2ecf20Sopenharmony_ci BUG(); 9678c2ecf20Sopenharmony_ci case 2: /* class 2 */ 9688c2ecf20Sopenharmony_ci /* 9698c2ecf20Sopenharmony_ci * Be careful out there. 9708c2ecf20Sopenharmony_ci * Crashme can generate cases where FR31R is specified 9718c2ecf20Sopenharmony_ci * as the source or target of a double precision operation. 9728c2ecf20Sopenharmony_ci * Since we just pass the address of the floating-point 9738c2ecf20Sopenharmony_ci * register to the emulation routines, this can cause 9748c2ecf20Sopenharmony_ci * corruption of fpzeroreg. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_ci if (fmt == DBL) 9778c2ecf20Sopenharmony_ci r2 = (extru(ir,fpr2pos,5)<<1); 9788c2ecf20Sopenharmony_ci else 9798c2ecf20Sopenharmony_ci r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 9808c2ecf20Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 9818c2ecf20Sopenharmony_ci if (r2 == 0) 9828c2ecf20Sopenharmony_ci r2 = fpzeroreg; 9838c2ecf20Sopenharmony_ci if (fpu_type_flags & PA2_0_FPU_FLAG) { 9848c2ecf20Sopenharmony_ci /* FTEST if nullify bit set, otherwise FCMP */ 9858c2ecf20Sopenharmony_ci if (extru(ir, fpnulpos, 1)) { /* FTEST */ 9868c2ecf20Sopenharmony_ci /* not legal */ 9878c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 9888c2ecf20Sopenharmony_ci } else { /* FCMP */ 9898c2ecf20Sopenharmony_ci switch (fmt) { 9908c2ecf20Sopenharmony_ci /* 9918c2ecf20Sopenharmony_ci * fmt is only 1 bit long 9928c2ecf20Sopenharmony_ci */ 9938c2ecf20Sopenharmony_ci case 0: 9948c2ecf20Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 9958c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 9968c2ecf20Sopenharmony_ci &local_status); 9978c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 9988c2ecf20Sopenharmony_ci fpu_type_flags, subop); 9998c2ecf20Sopenharmony_ci return(retval); 10008c2ecf20Sopenharmony_ci case 1: 10018c2ecf20Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 10028c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 10038c2ecf20Sopenharmony_ci &local_status); 10048c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 10058c2ecf20Sopenharmony_ci fpu_type_flags, subop); 10068c2ecf20Sopenharmony_ci return(retval); 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci } /* end of if for PA2.0 */ 10108c2ecf20Sopenharmony_ci else { /* PA1.0 & PA1.1 */ 10118c2ecf20Sopenharmony_ci switch (subop) { 10128c2ecf20Sopenharmony_ci case 1: 10138c2ecf20Sopenharmony_ci case 2: 10148c2ecf20Sopenharmony_ci case 3: 10158c2ecf20Sopenharmony_ci case 4: 10168c2ecf20Sopenharmony_ci case 5: 10178c2ecf20Sopenharmony_ci case 6: 10188c2ecf20Sopenharmony_ci case 7: 10198c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 10208c2ecf20Sopenharmony_ci case 0: /* FCMP */ 10218c2ecf20Sopenharmony_ci switch (fmt) { 10228c2ecf20Sopenharmony_ci /* 10238c2ecf20Sopenharmony_ci * fmt is only 1 bit long 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_ci case 0: 10268c2ecf20Sopenharmony_ci retval = sgl_fcmp(&fpregs[r1], 10278c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 10288c2ecf20Sopenharmony_ci &local_status); 10298c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 10308c2ecf20Sopenharmony_ci fpu_type_flags, subop); 10318c2ecf20Sopenharmony_ci return(retval); 10328c2ecf20Sopenharmony_ci case 1: 10338c2ecf20Sopenharmony_ci retval = dbl_fcmp(&fpregs[r1], 10348c2ecf20Sopenharmony_ci &fpregs[r2],extru(ir,fptpos,5), 10358c2ecf20Sopenharmony_ci &local_status); 10368c2ecf20Sopenharmony_ci update_status_cbit(status,local_status, 10378c2ecf20Sopenharmony_ci fpu_type_flags, subop); 10388c2ecf20Sopenharmony_ci return(retval); 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci } /* end of switch subop */ 10418c2ecf20Sopenharmony_ci } /* end of else for PA1.0 & PA1.1 */ 10428c2ecf20Sopenharmony_ci BUG(); 10438c2ecf20Sopenharmony_ci case 3: /* class 3 */ 10448c2ecf20Sopenharmony_ci /* 10458c2ecf20Sopenharmony_ci * Be careful out there. 10468c2ecf20Sopenharmony_ci * Crashme can generate cases where FR31R is specified 10478c2ecf20Sopenharmony_ci * as the source or target of a double precision operation. 10488c2ecf20Sopenharmony_ci * Since we just pass the address of the floating-point 10498c2ecf20Sopenharmony_ci * register to the emulation routines, this can cause 10508c2ecf20Sopenharmony_ci * corruption of fpzeroreg. 10518c2ecf20Sopenharmony_ci */ 10528c2ecf20Sopenharmony_ci if (fmt == DBL) 10538c2ecf20Sopenharmony_ci r2 = (extru(ir,fpr2pos,5)<<1); 10548c2ecf20Sopenharmony_ci else 10558c2ecf20Sopenharmony_ci r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 10568c2ecf20Sopenharmony_ci if (r2 == 0) 10578c2ecf20Sopenharmony_ci r2 = fpzeroreg; 10588c2ecf20Sopenharmony_ci switch (subop) { 10598c2ecf20Sopenharmony_ci case 5: 10608c2ecf20Sopenharmony_ci case 6: 10618c2ecf20Sopenharmony_ci case 7: 10628c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci /* 10658c2ecf20Sopenharmony_ci * Note that fmt is only 1 bit for class 3 */ 10668c2ecf20Sopenharmony_ci case 0: /* FADD */ 10678c2ecf20Sopenharmony_ci switch (fmt) { 10688c2ecf20Sopenharmony_ci case 0: 10698c2ecf20Sopenharmony_ci return(sgl_fadd(&fpregs[r1],&fpregs[r2], 10708c2ecf20Sopenharmony_ci &fpregs[t],status)); 10718c2ecf20Sopenharmony_ci case 1: 10728c2ecf20Sopenharmony_ci return(dbl_fadd(&fpregs[r1],&fpregs[r2], 10738c2ecf20Sopenharmony_ci &fpregs[t],status)); 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci BUG(); 10768c2ecf20Sopenharmony_ci case 1: /* FSUB */ 10778c2ecf20Sopenharmony_ci switch (fmt) { 10788c2ecf20Sopenharmony_ci case 0: 10798c2ecf20Sopenharmony_ci return(sgl_fsub(&fpregs[r1],&fpregs[r2], 10808c2ecf20Sopenharmony_ci &fpregs[t],status)); 10818c2ecf20Sopenharmony_ci case 1: 10828c2ecf20Sopenharmony_ci return(dbl_fsub(&fpregs[r1],&fpregs[r2], 10838c2ecf20Sopenharmony_ci &fpregs[t],status)); 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci BUG(); 10868c2ecf20Sopenharmony_ci case 2: /* FMPY or XMPYU */ 10878c2ecf20Sopenharmony_ci /* 10888c2ecf20Sopenharmony_ci * check for integer multiply (x bit set) 10898c2ecf20Sopenharmony_ci */ 10908c2ecf20Sopenharmony_ci if (extru(ir,fpxpos,1)) { 10918c2ecf20Sopenharmony_ci /* 10928c2ecf20Sopenharmony_ci * emulate XMPYU 10938c2ecf20Sopenharmony_ci */ 10948c2ecf20Sopenharmony_ci switch (fmt) { 10958c2ecf20Sopenharmony_ci case 0: 10968c2ecf20Sopenharmony_ci /* 10978c2ecf20Sopenharmony_ci * bad instruction if t specifies 10988c2ecf20Sopenharmony_ci * the right half of a register 10998c2ecf20Sopenharmony_ci */ 11008c2ecf20Sopenharmony_ci if (t & 1) 11018c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 11028c2ecf20Sopenharmony_ci BUG(); 11038c2ecf20Sopenharmony_ci /* unsupported 11048c2ecf20Sopenharmony_ci * impyu(&fpregs[r1],&fpregs[r2], 11058c2ecf20Sopenharmony_ci * &fpregs[t]); 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci return(NOEXCEPTION); 11088c2ecf20Sopenharmony_ci case 1: 11098c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci else { /* FMPY */ 11138c2ecf20Sopenharmony_ci switch (fmt) { 11148c2ecf20Sopenharmony_ci case 0: 11158c2ecf20Sopenharmony_ci return(sgl_fmpy(&fpregs[r1], 11168c2ecf20Sopenharmony_ci &fpregs[r2],&fpregs[t],status)); 11178c2ecf20Sopenharmony_ci case 1: 11188c2ecf20Sopenharmony_ci return(dbl_fmpy(&fpregs[r1], 11198c2ecf20Sopenharmony_ci &fpregs[r2],&fpregs[t],status)); 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci BUG(); 11238c2ecf20Sopenharmony_ci case 3: /* FDIV */ 11248c2ecf20Sopenharmony_ci switch (fmt) { 11258c2ecf20Sopenharmony_ci case 0: 11268c2ecf20Sopenharmony_ci return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 11278c2ecf20Sopenharmony_ci &fpregs[t],status)); 11288c2ecf20Sopenharmony_ci case 1: 11298c2ecf20Sopenharmony_ci return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 11308c2ecf20Sopenharmony_ci &fpregs[t],status)); 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci BUG(); 11338c2ecf20Sopenharmony_ci case 4: /* FREM */ 11348c2ecf20Sopenharmony_ci switch (fmt) { 11358c2ecf20Sopenharmony_ci case 0: 11368c2ecf20Sopenharmony_ci return(sgl_frem(&fpregs[r1],&fpregs[r2], 11378c2ecf20Sopenharmony_ci &fpregs[t],status)); 11388c2ecf20Sopenharmony_ci case 1: 11398c2ecf20Sopenharmony_ci return(dbl_frem(&fpregs[r1],&fpregs[r2], 11408c2ecf20Sopenharmony_ci &fpregs[t],status)); 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci } /* end of class 3 switch */ 11438c2ecf20Sopenharmony_ci } /* end of switch(class) */ 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci /* If we get here, something is really wrong! */ 11468c2ecf20Sopenharmony_ci return(MAJOR_0E_EXCP); 11478c2ecf20Sopenharmony_ci} 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci/* 11518c2ecf20Sopenharmony_ci * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction 11528c2ecf20Sopenharmony_ci */ 11538c2ecf20Sopenharmony_cistatic u_int 11548c2ecf20Sopenharmony_cidecode_06(ir,fpregs) 11558c2ecf20Sopenharmony_ciu_int ir; 11568c2ecf20Sopenharmony_ciu_int fpregs[]; 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci u_int rm1, rm2, tm, ra, ta; /* operands */ 11598c2ecf20Sopenharmony_ci u_int fmt; 11608c2ecf20Sopenharmony_ci u_int error = 0; 11618c2ecf20Sopenharmony_ci u_int status; 11628c2ecf20Sopenharmony_ci u_int fpu_type_flags; 11638c2ecf20Sopenharmony_ci union { 11648c2ecf20Sopenharmony_ci double dbl; 11658c2ecf20Sopenharmony_ci float flt; 11668c2ecf20Sopenharmony_ci struct { u_int i1; u_int i2; } ints; 11678c2ecf20Sopenharmony_ci } mtmp, atmp; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci status = fpregs[0]; /* use a local copy of status reg */ 11718c2ecf20Sopenharmony_ci fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 11728c2ecf20Sopenharmony_ci fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 11738c2ecf20Sopenharmony_ci if (fmt == 0) { /* DBL */ 11748c2ecf20Sopenharmony_ci rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 11758c2ecf20Sopenharmony_ci if (rm1 == 0) 11768c2ecf20Sopenharmony_ci rm1 = fpzeroreg; 11778c2ecf20Sopenharmony_ci rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 11788c2ecf20Sopenharmony_ci if (rm2 == 0) 11798c2ecf20Sopenharmony_ci rm2 = fpzeroreg; 11808c2ecf20Sopenharmony_ci tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 11818c2ecf20Sopenharmony_ci if (tm == 0) 11828c2ecf20Sopenharmony_ci return(MAJOR_06_EXCP); 11838c2ecf20Sopenharmony_ci ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 11848c2ecf20Sopenharmony_ci ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 11858c2ecf20Sopenharmony_ci if (ta == 0) 11868c2ecf20Sopenharmony_ci return(MAJOR_06_EXCP); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci if (ra == 0) { 11918c2ecf20Sopenharmony_ci /* special case FMPYCFXT, see sgl case below */ 11928c2ecf20Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], 11938c2ecf20Sopenharmony_ci &mtmp.ints.i1,&status)) 11948c2ecf20Sopenharmony_ci error = 1; 11958c2ecf20Sopenharmony_ci if (dbl_to_sgl_fcnvfxt(&fpregs[ta], 11968c2ecf20Sopenharmony_ci &atmp.ints.i1,&atmp.ints.i1,&status)) 11978c2ecf20Sopenharmony_ci error = 1; 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci else { 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 12028c2ecf20Sopenharmony_ci &status)) 12038c2ecf20Sopenharmony_ci error = 1; 12048c2ecf20Sopenharmony_ci if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 12058c2ecf20Sopenharmony_ci &status)) 12068c2ecf20Sopenharmony_ci error = 1; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci else 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci { 12138c2ecf20Sopenharmony_ci if (ra == 0) 12148c2ecf20Sopenharmony_ci ra = fpzeroreg; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 12178c2ecf20Sopenharmony_ci &status)) 12188c2ecf20Sopenharmony_ci error = 1; 12198c2ecf20Sopenharmony_ci if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 12208c2ecf20Sopenharmony_ci &status)) 12218c2ecf20Sopenharmony_ci error = 1; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci if (error) 12268c2ecf20Sopenharmony_ci return(MAJOR_06_EXCP); 12278c2ecf20Sopenharmony_ci else { 12288c2ecf20Sopenharmony_ci /* copy results */ 12298c2ecf20Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 12308c2ecf20Sopenharmony_ci fpregs[tm+1] = mtmp.ints.i2; 12318c2ecf20Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 12328c2ecf20Sopenharmony_ci fpregs[ta+1] = atmp.ints.i2; 12338c2ecf20Sopenharmony_ci fpregs[0] = status; 12348c2ecf20Sopenharmony_ci return(NOEXCEPTION); 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci else { /* SGL */ 12388c2ecf20Sopenharmony_ci /* 12398c2ecf20Sopenharmony_ci * calculate offsets for single precision numbers 12408c2ecf20Sopenharmony_ci * See table 6-14 in PA-89 architecture for mapping 12418c2ecf20Sopenharmony_ci */ 12428c2ecf20Sopenharmony_ci rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 12438c2ecf20Sopenharmony_ci rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 12468c2ecf20Sopenharmony_ci rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 12498c2ecf20Sopenharmony_ci tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 12528c2ecf20Sopenharmony_ci ra |= extru(ir,fprapos-4,1); /* add right word offset */ 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 12558c2ecf20Sopenharmony_ci ta |= extru(ir,fptapos-4,1); /* add right word offset */ 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { 12588c2ecf20Sopenharmony_ci /* special case FMPYCFXT (really 0) 12598c2ecf20Sopenharmony_ci * This instruction is only present on the Timex and 12608c2ecf20Sopenharmony_ci * Rolex fpu's in so if it is the special case and 12618c2ecf20Sopenharmony_ci * one of these fpu's we run the FMPYCFXT instruction 12628c2ecf20Sopenharmony_ci */ 12638c2ecf20Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 12648c2ecf20Sopenharmony_ci &status)) 12658c2ecf20Sopenharmony_ci error = 1; 12668c2ecf20Sopenharmony_ci if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, 12678c2ecf20Sopenharmony_ci &atmp.ints.i1,&status)) 12688c2ecf20Sopenharmony_ci error = 1; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci else { 12718c2ecf20Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 12728c2ecf20Sopenharmony_ci &status)) 12738c2ecf20Sopenharmony_ci error = 1; 12748c2ecf20Sopenharmony_ci if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 12758c2ecf20Sopenharmony_ci &status)) 12768c2ecf20Sopenharmony_ci error = 1; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci if (error) 12798c2ecf20Sopenharmony_ci return(MAJOR_06_EXCP); 12808c2ecf20Sopenharmony_ci else { 12818c2ecf20Sopenharmony_ci /* copy results */ 12828c2ecf20Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 12838c2ecf20Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 12848c2ecf20Sopenharmony_ci fpregs[0] = status; 12858c2ecf20Sopenharmony_ci return(NOEXCEPTION); 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci/* 12918c2ecf20Sopenharmony_ci * routine to decode the 26 (FMPYSUB) instruction 12928c2ecf20Sopenharmony_ci */ 12938c2ecf20Sopenharmony_cistatic u_int 12948c2ecf20Sopenharmony_cidecode_26(ir,fpregs) 12958c2ecf20Sopenharmony_ciu_int ir; 12968c2ecf20Sopenharmony_ciu_int fpregs[]; 12978c2ecf20Sopenharmony_ci{ 12988c2ecf20Sopenharmony_ci u_int rm1, rm2, tm, ra, ta; /* operands */ 12998c2ecf20Sopenharmony_ci u_int fmt; 13008c2ecf20Sopenharmony_ci u_int error = 0; 13018c2ecf20Sopenharmony_ci u_int status; 13028c2ecf20Sopenharmony_ci union { 13038c2ecf20Sopenharmony_ci double dbl; 13048c2ecf20Sopenharmony_ci float flt; 13058c2ecf20Sopenharmony_ci struct { u_int i1; u_int i2; } ints; 13068c2ecf20Sopenharmony_ci } mtmp, atmp; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci status = fpregs[0]; 13108c2ecf20Sopenharmony_ci fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 13118c2ecf20Sopenharmony_ci if (fmt == 0) { /* DBL */ 13128c2ecf20Sopenharmony_ci rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 13138c2ecf20Sopenharmony_ci if (rm1 == 0) 13148c2ecf20Sopenharmony_ci rm1 = fpzeroreg; 13158c2ecf20Sopenharmony_ci rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 13168c2ecf20Sopenharmony_ci if (rm2 == 0) 13178c2ecf20Sopenharmony_ci rm2 = fpzeroreg; 13188c2ecf20Sopenharmony_ci tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 13198c2ecf20Sopenharmony_ci if (tm == 0) 13208c2ecf20Sopenharmony_ci return(MAJOR_26_EXCP); 13218c2ecf20Sopenharmony_ci ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 13228c2ecf20Sopenharmony_ci if (ra == 0) 13238c2ecf20Sopenharmony_ci return(MAJOR_26_EXCP); 13248c2ecf20Sopenharmony_ci ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 13258c2ecf20Sopenharmony_ci if (ta == 0) 13268c2ecf20Sopenharmony_ci return(MAJOR_26_EXCP); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 13298c2ecf20Sopenharmony_ci error = 1; 13308c2ecf20Sopenharmony_ci if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 13318c2ecf20Sopenharmony_ci error = 1; 13328c2ecf20Sopenharmony_ci if (error) 13338c2ecf20Sopenharmony_ci return(MAJOR_26_EXCP); 13348c2ecf20Sopenharmony_ci else { 13358c2ecf20Sopenharmony_ci /* copy results */ 13368c2ecf20Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 13378c2ecf20Sopenharmony_ci fpregs[tm+1] = mtmp.ints.i2; 13388c2ecf20Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 13398c2ecf20Sopenharmony_ci fpregs[ta+1] = atmp.ints.i2; 13408c2ecf20Sopenharmony_ci fpregs[0] = status; 13418c2ecf20Sopenharmony_ci return(NOEXCEPTION); 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci else { /* SGL */ 13458c2ecf20Sopenharmony_ci /* 13468c2ecf20Sopenharmony_ci * calculate offsets for single precision numbers 13478c2ecf20Sopenharmony_ci * See table 6-14 in PA-89 architecture for mapping 13488c2ecf20Sopenharmony_ci */ 13498c2ecf20Sopenharmony_ci rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 13508c2ecf20Sopenharmony_ci rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 13538c2ecf20Sopenharmony_ci rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 13568c2ecf20Sopenharmony_ci tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 13598c2ecf20Sopenharmony_ci ra |= extru(ir,fprapos-4,1); /* add right word offset */ 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 13628c2ecf20Sopenharmony_ci ta |= extru(ir,fptapos-4,1); /* add right word offset */ 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 13658c2ecf20Sopenharmony_ci error = 1; 13668c2ecf20Sopenharmony_ci if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 13678c2ecf20Sopenharmony_ci error = 1; 13688c2ecf20Sopenharmony_ci if (error) 13698c2ecf20Sopenharmony_ci return(MAJOR_26_EXCP); 13708c2ecf20Sopenharmony_ci else { 13718c2ecf20Sopenharmony_ci /* copy results */ 13728c2ecf20Sopenharmony_ci fpregs[tm] = mtmp.ints.i1; 13738c2ecf20Sopenharmony_ci fpregs[ta] = atmp.ints.i1; 13748c2ecf20Sopenharmony_ci fpregs[0] = status; 13758c2ecf20Sopenharmony_ci return(NOEXCEPTION); 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci } 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci/* 13828c2ecf20Sopenharmony_ci * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions 13838c2ecf20Sopenharmony_ci */ 13848c2ecf20Sopenharmony_cistatic u_int 13858c2ecf20Sopenharmony_cidecode_2e(ir,fpregs) 13868c2ecf20Sopenharmony_ciu_int ir; 13878c2ecf20Sopenharmony_ciu_int fpregs[]; 13888c2ecf20Sopenharmony_ci{ 13898c2ecf20Sopenharmony_ci u_int rm1, rm2, ra, t; /* operands */ 13908c2ecf20Sopenharmony_ci u_int fmt; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ 13938c2ecf20Sopenharmony_ci if (fmt == DBL) { /* DBL */ 13948c2ecf20Sopenharmony_ci rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); 13958c2ecf20Sopenharmony_ci if (rm1 == 0) 13968c2ecf20Sopenharmony_ci rm1 = fpzeroreg; 13978c2ecf20Sopenharmony_ci rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); 13988c2ecf20Sopenharmony_ci if (rm2 == 0) 13998c2ecf20Sopenharmony_ci rm2 = fpzeroreg; 14008c2ecf20Sopenharmony_ci ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * 14018c2ecf20Sopenharmony_ci sizeof(double)/sizeof(u_int); 14028c2ecf20Sopenharmony_ci if (ra == 0) 14038c2ecf20Sopenharmony_ci ra = fpzeroreg; 14048c2ecf20Sopenharmony_ci t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 14058c2ecf20Sopenharmony_ci if (t == 0) 14068c2ecf20Sopenharmony_ci return(MAJOR_2E_EXCP); 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 14098c2ecf20Sopenharmony_ci return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 14108c2ecf20Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 14118c2ecf20Sopenharmony_ci } else { 14128c2ecf20Sopenharmony_ci return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 14138c2ecf20Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 14148c2ecf20Sopenharmony_ci } 14158c2ecf20Sopenharmony_ci } /* end DBL */ 14168c2ecf20Sopenharmony_ci else { /* SGL */ 14178c2ecf20Sopenharmony_ci rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); 14188c2ecf20Sopenharmony_ci if (rm1 == 0) 14198c2ecf20Sopenharmony_ci rm1 = fpzeroreg; 14208c2ecf20Sopenharmony_ci rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); 14218c2ecf20Sopenharmony_ci if (rm2 == 0) 14228c2ecf20Sopenharmony_ci rm2 = fpzeroreg; 14238c2ecf20Sopenharmony_ci ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); 14248c2ecf20Sopenharmony_ci if (ra == 0) 14258c2ecf20Sopenharmony_ci ra = fpzeroreg; 14268c2ecf20Sopenharmony_ci t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 14278c2ecf20Sopenharmony_ci if (t == 0) 14288c2ecf20Sopenharmony_ci return(MAJOR_2E_EXCP); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 14318c2ecf20Sopenharmony_ci return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 14328c2ecf20Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 14338c2ecf20Sopenharmony_ci } else { 14348c2ecf20Sopenharmony_ci return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 14358c2ecf20Sopenharmony_ci &fpregs[ra], &fpregs[0], &fpregs[t])); 14368c2ecf20Sopenharmony_ci } 14378c2ecf20Sopenharmony_ci } /* end SGL */ 14388c2ecf20Sopenharmony_ci} 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci/* 14418c2ecf20Sopenharmony_ci * update_status_cbit 14428c2ecf20Sopenharmony_ci * 14438c2ecf20Sopenharmony_ci * This routine returns the correct FP status register value in 14448c2ecf20Sopenharmony_ci * *status, based on the C-bit & V-bit returned by the FCMP 14458c2ecf20Sopenharmony_ci * emulation routine in new_status. The architecture type 14468c2ecf20Sopenharmony_ci * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field 14478c2ecf20Sopenharmony_ci * and the architecture type are used to determine what flavor 14488c2ecf20Sopenharmony_ci * of FCMP is being emulated. 14498c2ecf20Sopenharmony_ci */ 14508c2ecf20Sopenharmony_cistatic void 14518c2ecf20Sopenharmony_ciupdate_status_cbit(status, new_status, fpu_type, y_field) 14528c2ecf20Sopenharmony_ciu_int *status, new_status; 14538c2ecf20Sopenharmony_ciu_int fpu_type; 14548c2ecf20Sopenharmony_ciu_int y_field; 14558c2ecf20Sopenharmony_ci{ 14568c2ecf20Sopenharmony_ci /* 14578c2ecf20Sopenharmony_ci * For PA89 FPU's which implement the Compare Queue and 14588c2ecf20Sopenharmony_ci * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, 14598c2ecf20Sopenharmony_ci * otherwise update the specified bit in the Compare Array. 14608c2ecf20Sopenharmony_ci * Note that the y-field will always be 0 for non-PA2.0 FPU's. 14618c2ecf20Sopenharmony_ci */ 14628c2ecf20Sopenharmony_ci if ((fpu_type & TIMEX_EXTEN_FLAG) || 14638c2ecf20Sopenharmony_ci (fpu_type & ROLEX_EXTEN_FLAG) || 14648c2ecf20Sopenharmony_ci (fpu_type & PA2_0_FPU_FLAG)) { 14658c2ecf20Sopenharmony_ci if (y_field == 0) { 14668c2ecf20Sopenharmony_ci *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ 14678c2ecf20Sopenharmony_ci ((*status & 0x003ff000) >> 1) | /* old CQ */ 14688c2ecf20Sopenharmony_ci (new_status & 0xffc007ff); /* all other bits*/ 14698c2ecf20Sopenharmony_ci } else { 14708c2ecf20Sopenharmony_ci *status = (*status & 0x04000000) | /* old Cbit */ 14718c2ecf20Sopenharmony_ci ((new_status & 0x04000000) >> (y_field+4)) | 14728c2ecf20Sopenharmony_ci (new_status & ~0x04000000 & /* other bits */ 14738c2ecf20Sopenharmony_ci ~(0x04000000 >> (y_field+4))); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci } 14768c2ecf20Sopenharmony_ci /* if PA83, just update the C-bit */ 14778c2ecf20Sopenharmony_ci else { 14788c2ecf20Sopenharmony_ci *status = new_status; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci} 1481